diff -urN multipath-0.0.16.4/ChangeLog multipath-0.0.16.5/ChangeLog --- multipath-0.0.16.4/ChangeLog 2004-02-12 14:12:29.000000000 +0100 +++ multipath-0.0.16.5/ChangeLog 2004-02-12 16:53:08.000000000 +0100 @@ -1,4 +1,8 @@ 2004-02-04 multipath-016 + * add a GROUP_BY_SERIAL flag. This should be useful for + controlers that activate they spare paths on simple IO + submition with a penalty. The StorageWorks HW defaults to + this mode, even if the MULTIBUS mode is OK. * remove unused sg_err.c * big restructuring : split devinfo.c from main.c. Export : * void basename (char *, char *); diff -urN multipath-0.0.16.4/devinfo.c multipath-0.0.16.5/devinfo.c --- multipath-0.0.16.4/devinfo.c 2004-02-12 14:08:44.000000000 +0100 +++ multipath-0.0.16.5/devinfo.c 2004-02-12 16:06:14.000000000 +0100 @@ -73,19 +73,25 @@ } int -get_serial (int fd, char * str) +get_serial (char * str, char * devname) { - char buff[MX_ALLOC_LEN + 1]; + int fd; int len; + char buff[MX_ALLOC_LEN + 1]; - if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) { - len = buff[3]; - if (len > 0) { - memcpy(str, buff + 4, len); - buff[len] = '\0'; - } - return 1; - } + if ((fd = open(devname, O_RDONLY)) < 0) + return 0; + + if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) { + len = buff[3]; + if (len > 0) { + memcpy(str, buff + 4, len); + buff[len] = '\0'; + } + close(fd); + return 1; + } + close(fd); return 0; } diff -urN multipath-0.0.16.4/devinfo.h multipath-0.0.16.5/devinfo.h --- multipath-0.0.16.4/devinfo.h 2004-02-12 12:24:49.000000000 +0100 +++ multipath-0.0.16.5/devinfo.h 2004-02-12 14:55:00.000000000 +0100 @@ -13,7 +13,7 @@ #define SG_ERR_DRIVER_SENSE 0x08 void basename (char *, char *); -int get_serial (int, char *); +int get_serial (char *, char *); int get_lun_strings (char *, char *, char *, char *); int get_evpd_wwid(char *, char *); long get_disk_size (char *); diff -urN multipath-0.0.16.4/main.c multipath-0.0.16.5/main.c --- multipath-0.0.16.4/main.c 2004-02-12 14:10:33.000000000 +0100 +++ multipath-0.0.16.5/main.c 2004-02-12 16:45:29.000000000 +0100 @@ -41,11 +41,11 @@ int iopolicy; int (*getuid) (char *, char *); } wlist[] = { - {"COMPAQ ", "HSV110 (C)COMPAQ", MULTIBUS, &get_evpd_wwid}, - {"COMPAQ ", "MSA1000 ", MULTIBUS, &get_evpd_wwid}, - {"COMPAQ ", "MSA1000 VOLUME ", MULTIBUS, &get_evpd_wwid}, - {"DEC ", "HSG80 ", MULTIBUS, &get_evpd_wwid}, - {"HP ", "HSV100 ", MULTIBUS, &get_evpd_wwid}, + {"COMPAQ ", "HSV110 (C)COMPAQ", GROUP_BY_SERIAL, &get_evpd_wwid}, + {"COMPAQ ", "MSA1000 ", GROUP_BY_SERIAL, &get_evpd_wwid}, + {"COMPAQ ", "MSA1000 VOLUME ", GROUP_BY_SERIAL, &get_evpd_wwid}, + {"DEC ", "HSG80 ", GROUP_BY_SERIAL, &get_evpd_wwid}, + {"HP ", "HSV100 ", GROUP_BY_SERIAL, &get_evpd_wwid}, {"HP ", "A6189A ", MULTIBUS, &get_evpd_wwid}, {"HP ", "OPEN- ", MULTIBUS, &get_evpd_wwid}, {"DDN ", "SAN DataDirector", MULTIBUS, &get_evpd_wwid}, @@ -130,6 +130,7 @@ curpath.product_id, curpath.rev, curpath.sg_dev); + get_serial(curpath.serial, curpath.sg_dev); if (!get_unique_id(&curpath)) return 0; strcpy(refwwid, curpath.wwid); @@ -165,6 +166,7 @@ curpath.product_id, curpath.rev, curpath.sg_dev); + get_serial(curpath.serial, curpath.sg_dev); if(!get_unique_id(&curpath)) { memset(&curpath, 0, sizeof(path)); continue; @@ -216,6 +218,7 @@ all_paths[k].product_id, all_paths[k].rev, all_paths[k].sg_dev); + get_serial(all_paths[k].serial, all_paths[k].sg_dev); if (!get_unique_id(&all_paths[k])) continue; @@ -368,7 +371,7 @@ if (memcmp(empty_buff, all_paths[k].wwid, WWID_SIZE) == 0) continue; - /* 2. mp with this uid already instanciated */ + /* 2. if mp with this uid already instanciated */ for (i = 0; i <= nmp; i++) { if (0 == strcmp(mp[i].wwid, all_paths[k].wwid)) already_done = 1; @@ -398,6 +401,49 @@ return nmp; } +static void +group_by_serial(struct multipath * mp, struct path * all_paths, char * str) { + int path_count, pg_count = 0; + int i, k; + int * bitmap; + char path_buff[FILE_NAME_SIZE]; + char pg_buff[FILE_NAME_SIZE]; + char * path_buff_p = &path_buff[0]; + char * pg_buff_p = &pg_buff[0]; + + /* init the bitmap */ + bitmap = malloc((mp->npaths + 1) * sizeof(int)); + memset(bitmap, 0, (mp->npaths + 1) * sizeof(int)); + + for (i = 0; i <= mp->npaths; i++) { + if (bitmap[i]) + continue; + + /* here, we really got a new pg */ + pg_count++; + path_count = 1; + memset(&path_buff, 0, FILE_NAME_SIZE * sizeof(char)); + path_buff_p = &path_buff[0]; + + path_buff_p += sprintf(path_buff_p, " %s", all_paths[mp->pindex[i]].dev); + bitmap[i] = 1; + + for (k = i + 1; k <= mp->npaths; k++) { + if (bitmap[k]) + continue; + if (0 == strcmp(all_paths[mp->pindex[i]].serial, + all_paths[mp->pindex[k]].serial)) { + path_buff_p += sprintf(path_buff_p, " %s", all_paths[mp->pindex[k]].dev); + bitmap[k] = 1; + path_count++; + } + } + pg_buff_p += sprintf(pg_buff_p, " 1 round-robin %i 0%s", + path_count, path_buff); + } + sprintf(str, " %i%s", pg_count, pg_buff); +} + static int dm_simplecmd(int task, const char *name) { int r = 0; @@ -491,6 +537,11 @@ } } + if (all_paths[PINDEX(index,0)].iopolicy == GROUP_BY_SERIAL && + !conf->forcedfailover ) { + group_by_serial(&mp[index], all_paths, params_p); + } + if (mp[index].size < 0) return 0; diff -urN multipath-0.0.16.4/main.h multipath-0.0.16.5/main.h --- multipath-0.0.16.4/main.h 2004-02-12 12:10:39.000000000 +0100 +++ multipath-0.0.16.5/main.h 2004-02-12 14:54:51.000000000 +0100 @@ -33,6 +33,7 @@ /* global defs */ #define WWID_SIZE 33 +#define SERIAL_SIZE 14 #define MAX_DEVS 128 #define MAX_MP MAX_DEVS / 2 #define MAX_MP_PATHS MAX_DEVS / 4 @@ -45,6 +46,7 @@ /* Storage controlers cpabilities */ #define FAILOVER 0 #define MULTIBUS 1 +#define GROUP_BY_SERIAL 2 #define PINDEX(x,y) mp[(x)].pindex[(y)] @@ -82,6 +84,7 @@ char vendor_id[8]; char product_id[16]; char rev[4]; + char serial[SERIAL_SIZE]; int iopolicy; };