[dm-devel] Hitachi prioritizer ?
Matthias Rudolph
Matthias.Rudolph at hds.com
Mon Apr 24 12:27:39 UTC 2006
Hi all,
here is the source. Feel free with it:
/*
* (C) Copyright HDS GmbH 2006. All Rights Reserved.
*
* pp_hds_modular.c
* Version 1.12
*
* Prioritizer for multipath tools device mapper and HDS Storage
*
* Hitachis Modular Storage contains two controllers for redundancy. The
Storage internal LUN (LDEV)
* will normally allocated via two pathes to the server (one path per
controller). For performance
* reasons should the server access to a LDEV only via one controller.
The other path to the other
* controller is stand-by. It is also possible to allocate more as one
path for a LDEV per controller.
* Here is active/active access allowed. The other pathes via the other
controller are stand-by.
*
* This prioritizer checks with inquiry commands the represented LDEV
and Controller number and gives
* back a priority followed by this scheme:
*
* CONTROLLER ODD and LDEV ODD: PRIORITY 1
* CONTROLLER ODD and LDEV EVEN: PRIORITY 0
* CONTROLLER EVEN and LDEV ODD: PRIORITY 0
* CONTROLLER EVEN and LDEV EVEN: PRIORITY 1
*
* In the storage you can define for each LDEV a owner controller. If
the server makes IOs via the
* other controller the storage will switch the ownership automatically.
In this case you can see
* in the storage that the current controller is different from the
default controller, but this is
* absolutely no problem.
*
* With this prioritizer it is possible to establish a static load
balancing. Half of the LUNs are
* accessed via one HBA/storage controller and the other half via the
other HBA/storage controller.
*
* In cluster environmemnts (RAC) it also guarantees that all cluster
nodes have access to the LDEVs
* via the same controller.
*
* You can run the prioritizer manually in verbose mode:
* # pp_hds_modular -v 8:224
* VENDOR: HITACHI
* PRODUCT: DF600F-CM
* SERIAL: 0x0105
* LDEV: 0x00C6
* CTRL: 1
* PORT: B
* CTRL ODD, LDEV EVEN, PRIO 0
*
* The items VENDOR and PRODUCT helps you to make the correct entries in
file /etc/multipath.conf:
* # cat /etc/multipath.conf
* ...
* devices {
* device {
* vendor "HITACHI"
* product "DF600F"
* path_grouping_policy group_by_prio
* prio_callout "/sbin/pp_hds_modular %d"
* path_checker readsector0
* getuid_callout "/sbin/scsi_id -g -u -s
/block/%n"
* failback immediate
* }
* device {
* vendor "HITACHI"
* product "DF600F-CM"
* path_grouping_policy group_by_prio
* prio_callout "/sbin/pp_hds_modular %d"
* path_checker readsector0
* getuid_callout "/sbin/scsi_id -g -u -s
/block/%n"
* failback immediate
*
*
* Author: Matthias Rudolph <matthias.rudolph at hds.com>
*
* This file is released under the GPL.
*
*/
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <libdevmapper.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <scsi/sg.h> /* take care: fetches glibc's
/usr/include/scsi/sg.h */
#define INQ_REPLY_LEN 255
#define INQ_CMD_CODE 0x12
#define INQ_CMD_LEN 6
#define FILE_NAME_SIZE 255
#define safe_sprintf(var, format, args...) \
snprintf(var, sizeof(var), format, ##args) >= sizeof(var)
#define safe_snprintf(var, size, format, args...) \
snprintf(var, size, format, ##args) >= size
int verbose;
int hds_modular_prio(char * major_minor) {
int sg_fd, k, i;
char vendor[32];
char product[32];
char serial[32];
char ldev[32];
char ctrl[32];
char port[32];
char devpath[FILE_NAME_SIZE];
unsigned int major;
unsigned int minor;
unsigned char inqCmdBlk[INQ_CMD_LEN] = {INQ_CMD_CODE, 0, 0, 0,
INQ_REPLY_LEN, 0};
unsigned char inqBuff[INQ_REPLY_LEN];
unsigned char sense_buffer[32];
sg_io_hdr_t io_hdr;
sscanf(major_minor, "%u:%u", &major, &minor);
memset(devpath, 0, FILE_NAME_SIZE);
if (safe_sprintf(devpath, "/tmp/.pp_balance.%u.%u.devnode",
major, minor)) exit(1);
unlink (devpath);
mknod(devpath, S_IFBLK|S_IRUSR|S_IWUSR, makedev(major, minor));
if ((sg_fd = open(devpath, O_RDONLY)) < 0) exit(1);
if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000))
exit(1);
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = sizeof(inqCmdBlk);
io_hdr.mx_sb_len = sizeof(sense_buffer);
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = INQ_REPLY_LEN;
io_hdr.dxferp = inqBuff;
io_hdr.cmdp = inqCmdBlk;
io_hdr.sbp = sense_buffer;
io_hdr.timeout = 2000; /* TimeOut = 2 seconds */
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) exit(1);
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) exit(1);
for (i = 0; i < 8 ; i++) vendor[i] = inqBuff[i+8];
vendor[8] = 0;
for (i = 0; i < 16 ; i++) product[i] = inqBuff[i+16];
product[16] = 0;
for (i = 0; i < 4 ; i++) serial[i] = inqBuff[i+40];
serial[4] = 0;
for (i = 0; i < 4 ; i++) ldev[i] = inqBuff[i+44];
ldev[4] = 0;
ctrl[0] = inqBuff[49];
ctrl[1] = 0;
port[0] = inqBuff[50];
port[1] = 0;
close(sg_fd);
if (1 == verbose) {
printf("VENDOR: %s\n", vendor);
printf("PRODUCT: %s\n", product);
printf("SERIAL: 0x%s\n", serial);
printf("LDEV: 0x%s\n", ldev);
printf("CTRL: %s\n", ctrl);
printf("PORT: %s\n", port);
}
switch( ctrl[0] ) {
case '0': case '2': case '4': case '6': case '8':
switch( ldev[3] ) {
case '0': case '2': case '4': case '6':
case '8': case 'A': case 'C': case 'E':
if (1 == verbose) printf("CTRL
EVEN, LDEV EVEN, PRIO 1\n");
return 1;
break;
case '1': case '3': case '5': case '7':
case '9': case 'B': case 'D': case 'F':
if (1 == verbose) printf("CTRL
EVEN, LDEV ODD, PRIO 0\n");
return 0;
break;
}
case '1': case '3': case '5': case '7': case '9':
switch( ldev[3] ) {
case '0': case '2': case '4': case '6':
case '8': case 'A': case 'C': case 'E':
if (1 == verbose) printf("CTRL
ODD, LDEV EVEN, PRIO 0\n");
return 0;
break;
case '1': case '3': case '5': case '7':
case '9': case 'B': case 'D': case 'F':
if (1 == verbose) printf("CTRL
ODD, LDEV ODD, PRIO 1\n");
return 1;
break;
}
}
exit(1);
}
print_help() {
printf("\n");
printf("Usage: pp_hds_modular [-v]
<device_major:device_minor>\n");
printf("Option: -v verbose mode\n");
printf("Description: Prioritizer for Multipath Tools and HDS
Storage\n");
printf("Version: 1.12\n");
printf("Author: Matthias Rudolph
<matthias.rudolph at hds.com>\n");
printf("\n");
return;
}
int main(int argc, char * argv[]) {
int prio;
if (2 == argc) {
if (0 == strcmp(argv[1], "-h")) {
print_help();
exit(0);
}
else {
verbose = 0;
prio = hds_modular_prio(argv[1]);
printf("%d\n", prio);
exit(0);
}
}
if ((3 == argc) && (0 == strcmp(argv[1], "-v"))) {
verbose = 1;
prio = hds_modular_prio(argv[2]);
printf("%d\n", prio);
exit(0);
}
print_help();
exit(1);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pp_hds_modular_v1.12.tar
Type: application/x-tar
Size: 40960 bytes
Desc: pp_hds_modular_v1.12.tar
URL: <http://listman.redhat.com/archives/dm-devel/attachments/20060424/3c3e3ddf/attachment.tar>
More information about the dm-devel
mailing list