diff -urN multipath-tools-0.1.3/ChangeLog multipath-tools-0.1.4/ChangeLog --- multipath-tools-0.1.3/ChangeLog 2004-03-13 15:43:38.000000000 +0100 +++ multipath-tools-0.1.4/ChangeLog 2004-03-17 12:18:41.000000000 +0100 @@ -1,3 +1,11 @@ +2004-03-17 multipath-tools-0.1.4 + * multipath clean up + * split default hw table in hwtable.h + * split grouping policies in pgpolocies.c + * pass *mp to setup_map instead of mp[]+index + * ensure defhwtable is used if /etc/multipath.conf is buggy + * hwtable is not global anymore + * unlink the runfile in various error paths 2004-03-13 multipath-tools-0.1.3 * multipath config tool now has a config file parser (did I say I make the ugliest parsers ?) diff -urN multipath-tools-0.1.3/multipath/Makefile multipath-tools-0.1.4/multipath/Makefile --- multipath-tools-0.1.3/multipath/Makefile 2004-03-13 00:21:18.000000000 +0100 +++ multipath-tools-0.1.4/multipath/Makefile 2004-03-16 17:16:47.000000000 +0100 @@ -24,7 +24,8 @@ -I$(klibcdir)/klibc/include -I$(klibcdir)/klibc/include/bits32 \ -I$(GCCINCDIR) -I$(KERNEL_DIR)/include -I$(sysfsdir) -I. -I$(klibcarch) -OBJS = configfile.o devinfo.o main.o +OBJS = pgpolicies.o configfile.o devinfo.o main.o + CRT0 = $(klibcdir)/klibc/crt0.o LIB = $(klibcdir)/klibc/libc.a LIBGCC := $(shell $(CC) -print-libgcc-file-name ) diff -urN multipath-tools-0.1.3/multipath/configfile.c multipath-tools-0.1.4/multipath/configfile.c --- multipath-tools-0.1.3/multipath/configfile.c 2004-03-13 15:36:46.000000000 +0100 +++ multipath-tools-0.1.4/multipath/configfile.c 2004-03-16 11:09:54.000000000 +0100 @@ -60,7 +60,7 @@ { struct stat buf; - if(stat(CONFIG, &buf) < 0) + if (stat (CONFIG, &buf) < 0) return 0; return 1; diff -urN multipath-tools-0.1.3/multipath/hwtable.h multipath-tools-0.1.4/multipath/hwtable.h --- multipath-tools-0.1.3/multipath/hwtable.h 1970-01-01 01:00:00.000000000 +0100 +++ multipath-tools-0.1.4/multipath/hwtable.h 2004-03-16 10:08:38.000000000 +0100 @@ -0,0 +1,22 @@ +#define setup_default_hwtable struct hwentry defhwtable[] = { \ + {"COMPAQ ", "HSV110 (C)COMPAQ", GROUP_BY_TUR, &get_evpd_wwid}, \ + {"COMPAQ ", "MSA1000 ", GROUP_BY_TUR, &get_evpd_wwid}, \ + {"COMPAQ ", "MSA1000 VOLUME ", GROUP_BY_TUR, &get_evpd_wwid}, \ + {"DEC ", "HSG80 ", GROUP_BY_TUR, &get_evpd_wwid}, \ + {"HP ", "HSV100 ", GROUP_BY_TUR, &get_evpd_wwid}, \ + {"HP ", "A6189A ", MULTIBUS, &get_evpd_wwid}, \ + {"HP ", "OPEN- ", MULTIBUS, &get_evpd_wwid}, \ + {"DDN ", "SAN DataDirector", MULTIBUS, &get_evpd_wwid}, \ + {"FSC ", "CentricStor ", MULTIBUS, &get_evpd_wwid}, \ + {"HITACHI ", "DF400 ", MULTIBUS, &get_evpd_wwid}, \ + {"HITACHI ", "DF500 ", MULTIBUS, &get_evpd_wwid}, \ + {"HITACHI ", "DF600 ", MULTIBUS, &get_evpd_wwid}, \ + {"IBM ", "ProFibre 4000R ", MULTIBUS, &get_evpd_wwid}, \ + {"SGI ", "TP9100 ", MULTIBUS, &get_evpd_wwid}, \ + {"SGI ", "TP9300 ", MULTIBUS, &get_evpd_wwid}, \ + {"SGI ", "TP9400 ", MULTIBUS, &get_evpd_wwid}, \ + {"SGI ", "TP9500 ", MULTIBUS, &get_evpd_wwid}, \ + {"", "", 0, NULL}, \ +}; \ + +#define default_hwtable_addr &defhwtable[0] diff -urN multipath-tools-0.1.3/multipath/main.c multipath-tools-0.1.4/multipath/main.c --- multipath-tools-0.1.3/multipath/main.c 2004-03-13 15:37:49.000000000 +0100 +++ multipath-tools-0.1.4/multipath/main.c 2004-03-17 12:09:50.000000000 +0100 @@ -28,54 +28,21 @@ #include #include #include + #include "../libdevmapper/libdevmapper.h" #include "main.h" #include "devinfo.h" #include "configfile.h" +#include "hwtable.h" +#include "pgpolicies.h" -/* global default hardware list */ -struct hwentry defwlist[] = { - {"COMPAQ ", "HSV110 (C)COMPAQ", GROUP_BY_TUR, &get_evpd_wwid}, - {"COMPAQ ", "MSA1000 ", GROUP_BY_TUR, &get_evpd_wwid}, - {"COMPAQ ", "MSA1000 VOLUME ", GROUP_BY_TUR, &get_evpd_wwid}, - {"DEC ", "HSG80 ", GROUP_BY_TUR, &get_evpd_wwid}, - {"HP ", "HSV100 ", GROUP_BY_TUR, &get_evpd_wwid}, - {"HP ", "A6189A ", MULTIBUS, &get_evpd_wwid}, - {"HP ", "OPEN- ", MULTIBUS, &get_evpd_wwid}, - {"DDN ", "SAN DataDirector", MULTIBUS, &get_evpd_wwid}, - {"FSC ", "CentricStor ", MULTIBUS, &get_evpd_wwid}, - {"HITACHI ", "DF400 ", MULTIBUS, &get_evpd_wwid}, - {"HITACHI ", "DF500 ", MULTIBUS, &get_evpd_wwid}, - {"HITACHI ", "DF600 ", MULTIBUS, &get_evpd_wwid}, - {"IBM ", "ProFibre 4000R ", MULTIBUS, &get_evpd_wwid}, - {"SGI ", "TP9100 ", MULTIBUS, &get_evpd_wwid}, - {"SGI ", "TP9300 ", MULTIBUS, &get_evpd_wwid}, - {"SGI ", "TP9400 ", MULTIBUS, &get_evpd_wwid}, - {"SGI ", "TP9500 ", MULTIBUS, &get_evpd_wwid}, - {"", "", 0, NULL}, -}; - -struct hwentry * wlist = &defwlist[0]; +/* argv parser helper */ +#define argis(x) if (0 == strcmp (x, argv[i])) +/* not nice */ void *getuid_list[] = {&get_evpd_wwid, NULL}; static int -get_path_tunables(struct path * mypath) -{ - int i; - - for (i = 0; wlist[i].getuid; i++) { - if (strncmp(mypath->vendor_id, wlist[i].vendor, 8) == 0 && - strncmp(mypath->product_id, wlist[i].product, 16) == 0) { - mypath->iopolicy = wlist[i].iopolicy; - if (!wlist[i].getuid(mypath->sg_dev, mypath->wwid)) - return 0; - } - } - return 1; -} - -static int sysfsdevice2devname (char *devname, char *device) { char sysfs_path[FILE_NAME_SIZE]; @@ -83,19 +50,19 @@ char link_path[FILE_NAME_SIZE]; int r; - if (sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) { - fprintf(stderr, "[device] feature available with sysfs only\n"); + if (sysfs_get_mnt_path (sysfs_path, FILE_NAME_SIZE)) { + fprintf (stderr, "[device] feature available with sysfs only\n"); exit (1); } - sprintf(link_path, "%s%s/block", sysfs_path, device); + sprintf (link_path, "%s%s/block", sysfs_path, device); - r = sysfs_get_link(link_path, block_path, FILE_NAME_SIZE); + r = sysfs_get_link (link_path, block_path, FILE_NAME_SIZE); if (r != 0) return 1; - sysfs_get_name_from_path(block_path, devname, FILE_NAME_SIZE); + sysfs_get_name_from_path (block_path, devname, FILE_NAME_SIZE); return 0; } @@ -112,28 +79,28 @@ char attr_value[16]; char attr_ref_value[16]; - if (sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) { - fprintf(stderr, "-D feature available with sysfs only\n"); + if (sysfs_get_mnt_path (sysfs_path, FILE_NAME_SIZE)) { + fprintf (stderr, "-D feature available with sysfs only\n"); exit (1); } - sprintf(attr_ref_value, "%i:%i\n", major, minor); - sprintf(block_path, "%s/block", sysfs_path); - sdir = sysfs_open_directory(block_path); - sysfs_read_directory(sdir); - - dlist_for_each_data(sdir->subdirs, devp, struct sysfs_directory) { - sprintf(attr_path, "%s/%s/dev", block_path, devp->name); - sysfs_read_attribute_value(attr_path, attr_value, 16); - - if (!strcmp(attr_value, attr_ref_value)) { - sprintf(attr_path, "%s/%s", block_path, devp->name); - sysfs_get_name_from_path(attr_path, devname, FILE_NAME_SIZE); + sprintf (attr_ref_value, "%i:%i\n", major, minor); + sprintf (block_path, "%s/block", sysfs_path); + sdir = sysfs_open_directory (block_path); + sysfs_read_directory (sdir); + + dlist_for_each_data (sdir->subdirs, devp, struct sysfs_directory) { + sprintf (attr_path, "%s/%s/dev", block_path, devp->name); + sysfs_read_attribute_value (attr_path, attr_value, 16); + + if (!strcmp (attr_value, attr_ref_value)) { + sprintf (attr_path, "%s/%s", block_path, devp->name); + sysfs_get_name_from_path (attr_path, devname, FILE_NAME_SIZE); break; } } - sysfs_close_directory(sdir); + sysfs_close_directory (sdir); return 0; } @@ -157,24 +124,34 @@ }; for (i = 0; blist[i].lengh; i++) { - if (strncmp(dev, blist[i].headstr, blist[i].lengh) == 0) + if (strncmp (dev, blist[i].headstr, blist[i].lengh) == 0) return 1; } return 0; } static int -devinfo (struct path *curpath) +devinfo (struct path *curpath, struct hwentry * hwtable) { - get_lun_strings(curpath->vendor_id, + int i; + + get_lun_strings (curpath->vendor_id, curpath->product_id, curpath->rev, curpath->sg_dev); - get_serial(curpath->serial, curpath->sg_dev); - curpath->tur = do_tur(curpath->sg_dev); - if (!get_path_tunables(curpath)) { - fprintf (stderr, "get_path_tunables error\n"); - return 1; + + get_serial (curpath->serial, curpath->sg_dev); + curpath->tur = do_tur (curpath->sg_dev); + + for (i = 0; hwtable[i].getuid; i++) { + if (strncmp (curpath->vendor_id, hwtable[i].vendor, 8) == 0 && + strncmp (curpath->product_id, hwtable[i].product, 16) == 0) { + + curpath->iopolicy = hwtable[i].iopolicy; + + if (!hwtable[i].getuid (curpath->sg_dev, curpath->wwid)) + return 1; + } } return 0; @@ -182,7 +159,7 @@ static int -get_all_paths_sysfs(struct env * conf, struct path * all_paths) +get_all_paths_sysfs (struct env * conf, struct path * all_paths) { int k=0; struct sysfs_directory * sdir; @@ -194,57 +171,57 @@ char path[FILE_NAME_SIZE]; struct path curpath; - memset(empty_buff, 0, WWID_SIZE); - memset(refwwid, 0, WWID_SIZE); + memset (empty_buff, 0, WWID_SIZE); + memset (refwwid, 0, WWID_SIZE); /* if called from hotplug, only consider the paths that relate to the device pointed by conf.hotplugdev */ - if (strncmp("/devices", conf->hotplugdev, 8) == 0) { + if (strncmp ("/devices", conf->hotplugdev, 8) == 0) { if (sysfsdevice2devname (buff, conf->hotplugdev)) return 0; - sprintf(curpath.sg_dev, "/dev/%s", buff); + sprintf (curpath.sg_dev, "/dev/%s", buff); - if (devinfo(&curpath)) + if (devinfo (&curpath, conf->hwtable)) return 0; - strcpy(refwwid, curpath.wwid); - memset(&curpath, 0, sizeof(path)); + strcpy (refwwid, curpath.wwid); + memset (&curpath, 0, sizeof (path)); } /* if major/minor specified on the cmd line, only consider affiliated paths */ if (conf->major >= 0 && conf->minor >= 0) { - if (devt2devname(buff, conf->major, conf->minor)) + if (devt2devname (buff, conf->major, conf->minor)) return 0; - sprintf(curpath.sg_dev, "/dev/%s", buff); + sprintf (curpath.sg_dev, "/dev/%s", buff); - if (devinfo(&curpath)) + if (devinfo (&curpath, conf->hwtable)) return 0; - strcpy(refwwid, curpath.wwid); - memset(&curpath, 0, sizeof(path)); + strcpy (refwwid, curpath.wwid); + memset (&curpath, 0, sizeof (path)); } - sprintf(path, "%s/block", conf->sysfs_path); - sdir = sysfs_open_directory(path); - sysfs_read_directory(sdir); + sprintf (path, "%s/block", conf->sysfs_path); + sdir = sysfs_open_directory (path); + sysfs_read_directory (sdir); - dlist_for_each_data(sdir->subdirs, devp, struct sysfs_directory) { - if (blacklist(devp->name)) + dlist_for_each_data (sdir->subdirs, devp, struct sysfs_directory) { + if (blacklist (devp->name)) continue; - sysfs_read_directory(devp); + sysfs_read_directory (devp); - if(devp->links == NULL) + if (devp->links == NULL) continue; - dlist_for_each_data(devp->links, linkp, struct sysfs_link) { - if (!strncmp(linkp->name, "device", 6)) + dlist_for_each_data (devp->links, linkp, struct sysfs_link) { + if (!strncmp (linkp->name, "device", 6)) break; } @@ -252,45 +229,45 @@ continue; } - basename(devp->path, buff); - sprintf(curpath.sg_dev, "/dev/%s", buff); + basename (devp->path, buff); + sprintf (curpath.sg_dev, "/dev/%s", buff); - if(devinfo(&curpath)) { - memset(&curpath, 0, sizeof(path)); + if (devinfo (&curpath, conf->hwtable)) { + memset (&curpath, 0, sizeof (path)); continue; } - if (memcmp(empty_buff, refwwid, WWID_SIZE) != 0 && - strncmp(curpath.wwid, refwwid, WWID_SIZE) != 0) { - memset(&curpath, 0, sizeof(path)); + if (memcmp (empty_buff, refwwid, WWID_SIZE) != 0 && + strncmp (curpath.wwid, refwwid, WWID_SIZE) != 0) { + memset (&curpath, 0, sizeof (path)); continue; } - strcpy(all_paths[k].sg_dev, curpath.sg_dev); - strcpy(all_paths[k].dev, curpath.sg_dev); - strcpy(all_paths[k].wwid, curpath.wwid); - strcpy(all_paths[k].vendor_id, curpath.vendor_id); - strcpy(all_paths[k].product_id, curpath.product_id); + strcpy (all_paths[k].sg_dev, curpath.sg_dev); + strcpy (all_paths[k].dev, curpath.sg_dev); + strcpy (all_paths[k].wwid, curpath.wwid); + strcpy (all_paths[k].vendor_id, curpath.vendor_id); + strcpy (all_paths[k].product_id, curpath.product_id); all_paths[k].iopolicy = curpath.iopolicy; all_paths[k].tur = curpath.tur; /* done with curpath, zero for reuse */ - memset(&curpath, 0, sizeof(path)); + memset (&curpath, 0, sizeof (path)); - basename(linkp->target, buff); - sscanf(buff, "%i:%i:%i:%i", + basename (linkp->target, buff); + sscanf (buff, "%i:%i:%i:%i", &all_paths[k].sg_id.host_no, &all_paths[k].sg_id.channel, &all_paths[k].sg_id.scsi_id, &all_paths[k].sg_id.lun); k++; } - sysfs_close_directory(sdir); + sysfs_close_directory (sdir); return 0; } static int -get_all_paths_nosysfs(struct env * conf, struct path * all_paths, +get_all_paths_nosysfs (struct env * conf, struct path * all_paths, struct scsi_dev * all_scsi_ids) { int k, i, fd; @@ -298,27 +275,21 @@ char file_name[FILE_NAME_SIZE]; for (k = 0; k < conf->max_devs; k++) { - strcpy(file_name, "/dev/sg"); - sprintf(buff, "%d", k); - strncat(file_name, buff, FILE_NAME_SIZE); - strcpy(all_paths[k].sg_dev, file_name); - - get_lun_strings(all_paths[k].vendor_id, - 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_path_tunables(&all_paths[k])) - continue; + strcpy (file_name, "/dev/sg"); + sprintf (buff, "%d", k); + strncat (file_name, buff, FILE_NAME_SIZE); + strcpy (all_paths[k].sg_dev, file_name); - if ((fd = open(all_paths[k].sg_dev, O_RDONLY)) < 0) + devinfo (&all_paths[k], conf->hwtable); + + if ((fd = open (all_paths[k].sg_dev, O_RDONLY)) < 0) return 0; - if (0 > ioctl(fd, SG_GET_SCSI_ID, &(all_paths[k].sg_id))) - printf("device %s failed on sg ioctl, skip\n", + if (0 > ioctl (fd, SG_GET_SCSI_ID, &(all_paths[k].sg_id))) + printf ("device %s failed on sg ioctl, skip\n", file_name); - close(fd); + close (fd); for (i = 0; i < conf->max_devs; i++) { if ((all_paths[k].sg_id.host_no == @@ -330,7 +301,7 @@ && (all_paths[k].sg_id.channel == ((all_scsi_ids[i].scsi_id. dev_id >> 16) & 0xff))) { - strcpy(all_paths[k].dev, all_scsi_ids[i].dev); + strcpy (all_paths[k].dev, all_scsi_ids[i].dev); break; } } @@ -339,7 +310,7 @@ } static int -get_all_scsi_ids(struct env * conf, struct scsi_dev * all_scsi_ids) +get_all_scsi_ids (struct env * conf, struct scsi_dev * all_scsi_ids) { int k, big, little, res, host_no, fd; char buff[64]; @@ -347,11 +318,11 @@ struct scsi_idlun my_scsi_id; for (k = 0; k < conf->max_devs; k++) { - strcpy(fname, "/dev/sd"); + strcpy (fname, "/dev/sd"); if (k < 26) { buff[0] = 'a' + (char) k; buff[1] = '\0'; - strcat(fname, buff); + strcat (fname, buff); } else if (k <= 255) { /* assumes sequence goes x,y,z,aa,ab,ac etc */ big = k / 26; @@ -361,34 +332,34 @@ buff[0] = 'a' + (char) big; buff[1] = 'a' + (char) little; buff[2] = '\0'; - strcat(fname, buff); + strcat (fname, buff); } else - strcat(fname, "xxxx"); + strcat (fname, "xxxx"); - if ((fd = open(fname, O_RDONLY)) < 0) { + if ((fd = open (fname, O_RDONLY)) < 0) { if (conf->verbose) - fprintf(stderr, "can't open %s. mknod ?", + fprintf (stderr, "can't open %s. mknod ?", fname); continue; } - res = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &my_scsi_id); + res = ioctl (fd, SCSI_IOCTL_GET_IDLUN, &my_scsi_id); if (res < 0) { - close(fd); - printf("Could not get scsi idlun\n"); + close (fd); + printf ("Could not get scsi idlun\n"); continue; } - res = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no); + res = ioctl (fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no); if (res < 0) { - close(fd); - printf("Could not get host_no\n"); + close (fd); + printf ("Could not get host_no\n"); continue; } - close(fd); + close (fd); - strcpy(all_scsi_ids[k].dev, fname); + strcpy (all_scsi_ids[k].dev, fname); all_scsi_ids[k].scsi_id = my_scsi_id; all_scsi_ids[k].host_no = host_no; } @@ -400,50 +371,65 @@ #define NOWWID 1 static void -print_path(struct path * all_paths, int k, int style) +print_path (struct path * all_paths, int k, int style) { if (style != NOWWID) - printf("%s ", all_paths[k].wwid); + printf ("%s ", all_paths[k].wwid); else - printf(" \\_"); - printf("(%i %i %i %i) ", + printf (" \\_"); + + printf ("(%i %i %i %i) ", all_paths[k].sg_id.host_no, all_paths[k].sg_id.channel, - all_paths[k].sg_id.scsi_id, all_paths[k].sg_id.lun); - if(0 != strcmp(all_paths[k].sg_dev, all_paths[k].dev)) - printf("%s ", all_paths[k].sg_dev); - printf("%s ", all_paths[k].dev); - printf("[%.16s]\n", all_paths[k].product_id); + all_paths[k].sg_id.scsi_id, + all_paths[k].sg_id.lun); + + /* for 2.4 kernels, sg_dev should be printed */ + if (0 != strcmp (all_paths[k].sg_dev, all_paths[k].dev)) + printf ("%s ", all_paths[k].sg_dev); + + printf ("%s ", all_paths[k].dev); + printf ("[%.16s]\n", all_paths[k].product_id); } static void -print_all_path(struct env * conf, struct path * all_paths) +print_all_path (struct env * conf, struct path * all_paths) { int k; char empty_buff[WWID_SIZE]; - memset(empty_buff, 0, WWID_SIZE); + /* initialize a cmp 0-filled buffer */ + memset (empty_buff, 0, WWID_SIZE); + + fprintf (stdout, "# all paths :\n"); + for (k = 0; k < conf->max_devs; k++) { - if (memcmp(empty_buff, all_paths[k].wwid, WWID_SIZE) == 0) + + /* leave out paths with incomplete devinfo */ + if (memcmp (empty_buff, all_paths[k].wwid, WWID_SIZE) == 0) continue; - print_path(all_paths, k, ALL); + + print_path (all_paths, k, ALL); } } static void -print_all_mp(struct path * all_paths, struct multipath * mp, int nmp) +print_all_mp (struct path * all_paths, struct multipath * mp, int nmp) { int k, i; + fprintf (stdout, "# all multipaths :\n"); + for (k = 0; k <= nmp; k++) { - printf("%s\n", mp[k].wwid); + printf ("%s\n", mp[k].wwid); + for (i = 0; i <= mp[k].npaths; i++) - print_path(all_paths, PINDEX(k,i), NOWWID); + print_path (all_paths, PINDEX(k,i), NOWWID); } } static int -coalesce_paths(struct env * conf, struct multipath * mp, +coalesce_paths (struct env * conf, struct multipath * mp, struct path * all_paths) { int k, i, nmp, np, already_done; @@ -451,18 +437,18 @@ nmp = -1; already_done = 0; - memset(empty_buff, 0, WWID_SIZE); + memset (empty_buff, 0, WWID_SIZE); for (k = 0; k < conf->max_devs - 1; k++) { /* skip this path for some reason */ /* 1. if path has no unique id */ - if (memcmp(empty_buff, all_paths[k].wwid, WWID_SIZE) == 0) + if (memcmp (empty_buff, all_paths[k].wwid, WWID_SIZE) == 0) continue; /* 2. if mp with this uid already instanciated */ for (i = 0; i <= nmp; i++) { - if (0 == strcmp(mp[i].wwid, all_paths[k].wwid)) + if (0 == strcmp (mp[i].wwid, all_paths[k].wwid)) already_done = 1; } if (already_done) { @@ -473,14 +459,14 @@ /* at this point, we know we really got a new mp */ np = 0; nmp++; - strcpy(mp[nmp].wwid, all_paths[k].wwid); + strcpy (mp[nmp].wwid, all_paths[k].wwid); PINDEX(nmp,np) = k; if (mp[nmp].size == 0) - mp[nmp].size = get_disk_size(all_paths[k].dev); + mp[nmp].size = get_disk_size (all_paths[k].dev); for (i = k + 1; i < conf->max_devs; i++) { - if (0 == strcmp(all_paths[k].wwid, all_paths[i].wwid)) { + if (0 == strcmp (all_paths[k].wwid, all_paths[i].wwid)) { np++; PINDEX(nmp,np) = i; mp[nmp].npaths = np; @@ -490,216 +476,115 @@ return nmp; } -static void -group_by_tur(struct multipath * mp, struct path * all_paths, char * str) { - int left_path_count = 0; - int right_path_count = 0; - int i; - char left_path_buff[FILE_NAME_SIZE], right_path_buff[FILE_NAME_SIZE]; - char * left_path_buff_p = &left_path_buff[0]; - char * right_path_buff_p = &right_path_buff[0]; - - for (i = 0; i <= mp->npaths; i++) { - if (all_paths[mp->pindex[i]].tur) { - left_path_buff_p += sprintf(left_path_buff_p, " %s", all_paths[mp->pindex[i]].dev); - left_path_count++; - } else { - right_path_buff_p += sprintf(right_path_buff_p, " %s", all_paths[mp->pindex[i]].dev); - right_path_count++; - } - } - if (!left_path_count) - sprintf(str, " 1 round-robin %i 0 %s", right_path_count, right_path_buff); - else if (!right_path_count) - sprintf(str, " 1 round-robin %i 0 %s", left_path_count, left_path_buff); - else - sprintf(str, " 2 round-robin %i 0 %s round-robin %i 0 %s", - left_path_count, left_path_buff, - right_path_count, right_path_buff); -} - -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, " round-robin %i 0%s", - path_count, path_buff); - } - sprintf(str, " %i%s", pg_count, pg_buff); - free(bitmap); -} - static int -dm_simplecmd(int task, const char *name) { +dm_simplecmd (int task, const char *name) { int r = 0; struct dm_task *dmt; - if (!(dmt = dm_task_create(task))) + if (!(dmt = dm_task_create (task))) return 0; - if (!dm_task_set_name(dmt, name)) + if (!dm_task_set_name (dmt, name)) goto out; - r = dm_task_run(dmt); + r = dm_task_run (dmt); out: - dm_task_destroy(dmt); + dm_task_destroy (dmt); return r; } static int -dm_addmap(int task, const char *name, const char *params, long size) { +dm_addmap (int task, const char *name, const char *params, long size) { struct dm_task *dmt; - if (!(dmt = dm_task_create(task))) + if (!(dmt = dm_task_create (task))) return 0; - if (!dm_task_set_name(dmt, name)) + if (!dm_task_set_name (dmt, name)) goto addout; - if (!dm_task_add_target(dmt, 0, size, DM_TARGET, params)) + if (!dm_task_add_target (dmt, 0, size, DM_TARGET, params)) goto addout; - if (!dm_task_run(dmt)) + if (!dm_task_run (dmt)) goto addout; addout: - dm_task_destroy(dmt); + dm_task_destroy (dmt); return 1; } +/* helper for grouping policy selection */ + +#define policyis(x) (all_paths[mp->pindex[0]].iopolicy == x && conf->iopolicy == -1) \ + || conf->iopolicy == x + static int -setup_map(struct env * conf, struct path * all_paths, - struct multipath * mp, int index, int op) +setup_map (struct env * conf, struct path * all_paths, + struct multipath * mp, int op) { char params[255]; char * params_p; - int i, np; - - /* defaults for multipath target */ - char * dm_ps_name = "round-robin"; - int dm_ps_nr_args = 0; params_p = ¶ms[0]; - np = 0; - for (i=0; i<=mp[index].npaths; i++) { - if (0 == all_paths[PINDEX(index,i)].sg_id.scsi_type) - np++; - } + /* paths grouping policy selector */ + /* implementations in pgpolicies.c */ - if (np < 1) - return 0; + if (policyis (MULTIBUS)) + one_group (mp, all_paths, params_p); - if ((all_paths[PINDEX(index,0)].iopolicy == MULTIBUS && - conf->iopolicy == -1) || conf->iopolicy == MULTIBUS) { - params_p += sprintf(params_p, "1 %s %i %i", - dm_ps_name, np, dm_ps_nr_args); - - for (i=0; i<=mp[index].npaths; i++) { - if (0 != all_paths[PINDEX(index,i)].sg_id.scsi_type) - continue; - params_p += sprintf(params_p, " %s", - all_paths[PINDEX(index,i)].dev); - } - } + if (policyis (FAILOVER)) + one_path_per_group (mp, all_paths, params_p); - if ((all_paths[PINDEX(index,0)].iopolicy == FAILOVER && - conf->iopolicy == -1) || conf->iopolicy == FAILOVER) { - params_p += sprintf(params_p, "%i", mp[index].npaths + 1); - for (i=0; i<=mp[index].npaths; i++) { - if (0 != all_paths[PINDEX(index,i)].sg_id.scsi_type) - continue; - params_p += sprintf(params_p, " %s ", - dm_ps_name); - params_p += sprintf(params_p, "1 %i", - dm_ps_nr_args); - params_p += sprintf(params_p, " %s", - all_paths[PINDEX(index,i)].dev); - } - } + if (policyis (GROUP_BY_SERIAL)) + group_by_serial (mp, all_paths, params_p); - if ((all_paths[PINDEX(index,0)].iopolicy == GROUP_BY_SERIAL && - conf->iopolicy == -1) || conf->iopolicy == GROUP_BY_SERIAL) { - group_by_serial(&mp[index], all_paths, params_p); - } - - if ((all_paths[PINDEX(index,0)].iopolicy == GROUP_BY_TUR && - conf->iopolicy == -1) || conf->iopolicy == GROUP_BY_TUR) { - group_by_tur(&mp[index], all_paths, params_p); - } + if (policyis (GROUP_BY_TUR)) + group_by_tur (mp, all_paths, params_p); - if (mp[index].size < 0) + if (mp->size < 0) return 0; if (!conf->quiet) { + if (op == DM_DEVICE_RELOAD) - printf("U:"); + printf ("U:"); + if (op == DM_DEVICE_CREATE) - printf("N:"); - printf("%s:0 %li %s %s\n", - mp[index].wwid, mp[index].size, DM_TARGET, params); + printf ("N:"); + + printf ("%s:0 %li %s%s\n", + mp->wwid, mp->size, DM_TARGET, params); } if (op == DM_DEVICE_RELOAD) - dm_simplecmd(DM_DEVICE_SUSPEND, mp[index].wwid); + dm_simplecmd (DM_DEVICE_SUSPEND, mp->wwid); - dm_addmap(op, mp[index].wwid, params, mp[index].size); + dm_addmap (op, mp->wwid, params, mp->size); if (op == DM_DEVICE_RELOAD) - dm_simplecmd(DM_DEVICE_RESUME, mp[index].wwid); + dm_simplecmd (DM_DEVICE_RESUME, mp->wwid); return 1; } static int -map_present(char * str) +map_present (char * str) { int r = 0; struct dm_task *dmt; struct dm_names *names; unsigned next = 0; - if (!(dmt = dm_task_create(DM_DEVICE_LIST))) + if (!(dmt = dm_task_create (DM_DEVICE_LIST))) return 0; - if (!dm_task_run(dmt)) + if (!dm_task_run (dmt)) goto out; - if (!(names = dm_task_get_names(dmt))) + if (!(names = dm_task_get_names (dmt))) goto out; if (!names->dev) { @@ -707,14 +592,14 @@ } do { - if (0 == strcmp(names->name, str)) + if (0 == strcmp (names->name, str)) r = 1; next = names->next; names = (void *) names + next; } while (next); out: - dm_task_destroy(dmt); + dm_task_destroy (dmt); return r; } @@ -730,7 +615,7 @@ file = fopen (PIDFILE, "r"); if (!file) { - fprintf(stderr, "cannot signal daemon, pidfile not found\n"); + fprintf (stderr, "cannot signal daemon, pidfile not found\n"); return; } @@ -740,25 +625,25 @@ pid = (pid_t) atol (buf); free (buf); - kill(pid, SIGHUP); + kill (pid, SIGHUP); } static int -filepresent(char * run) { +filepresent (char * run) { struct stat buf; - if(!stat(run, &buf)) + if(!stat (run, &buf)) return 1; return 0; } static void -usage(char * progname) +usage (char * progname) { - fprintf(stderr, VERSION_STRING); - fprintf(stderr, "Usage: %s [-v|-q] [-d] [-m max_devs]\n", + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage: %s [-v|-q] [-d] [-m max_devs]\n", progname); - fprintf(stderr, " [-p failover|multibus|group_by_serial]\n" \ + fprintf (stderr, " [-p failover|multibus|group_by_serial]\n" \ " [device]\n" \ "\n" \ "\t-v\t\tverbose, print all paths and multipaths\n" \ @@ -777,11 +662,13 @@ "\tdevice\t\tlimit scope to the device's multipath\n" \ "\t\t\t(hotplug-style $DEVPATH reference)\n" ); - exit(1); + + unlink (RUN); + exit (1); } int -main(int argc, char *argv[]) +main (int argc, char *argv[]) { struct multipath * mp; struct path * all_paths; @@ -791,17 +678,17 @@ int try = 0; /* Don't run in parallel */ - while (filepresent(RUN) && try++ < MAXTRY) - usleep(100000); + while (filepresent (RUN) && try++ < MAXTRY) + usleep (100000); - if (filepresent(RUN)) { - fprintf(stderr, "waited for to long. exiting\n"); + if (filepresent (RUN)) { + fprintf (stderr, "waited for to long. exiting\n"); exit (1); } /* Our turn */ - if (!open(RUN, O_CREAT)) { - fprintf(stderr, "can't create runfile\n"); + if (!open (RUN, O_CREAT)) { + fprintf (stderr, "can't create runfile\n"); exit (1); } @@ -813,90 +700,124 @@ conf.iopolicy = -1; /* do not override defaults */ conf.major = -1; conf.minor = -1; + conf.hwtable = NULL; + /* argv parser */ for (i = 1; i < argc; ++i) { - if (0 == strcmp("-v", argv[i])) { + + argis ("-v") { if (conf.quiet == 1) - usage(argv[0]); + usage (argv[0]); conf.verbose = 1; - } else if (0 == strcmp("-m", argv[i])) { - conf.max_devs = atoi(argv[++i]); + } + + else argis ("-m") { + conf.max_devs = atoi (argv[++i]); if (conf.max_devs < 2) - usage(argv[0]); - } else if (0 == strcmp("-D", argv[i])) { - conf.major = atoi(argv[++i]); - conf.minor = atoi(argv[++i]); - } else if (0 == strcmp("-q", argv[i])) { + usage (argv[0]); + } + + else argis ("-D") { + conf.major = atoi (argv[++i]); + conf.minor = atoi (argv[++i]); + } + + else argis ("-q") { if (conf.verbose == 1) - usage(argv[0]); + usage (argv[0]); conf.quiet = 1; - } else if (0 == strcmp("-d", argv[i])) + } + + else argis ("-d") conf.dry_run = 1; - else if (0 == strcmp("-p", argv[i])) { + + else argis ("-p") { i++; - if (!strcmp(argv[i], "failover")) + argis ("failover") conf.iopolicy = FAILOVER; - if (!strcmp(argv[i], "multibus")) + + argis ("multibus") conf.iopolicy = MULTIBUS; - if (!strcmp(argv[i], "group_by_serial")) + + argis ("group_by_serial") conf.iopolicy = GROUP_BY_SERIAL; - if (!strcmp(argv[i], "group_by_tur")) + + argis ("group_by_tur") conf.iopolicy = GROUP_BY_TUR; - } else if (*argv[i] == '-') { - fprintf(stderr, "Unknown switch: %s\n", argv[i]); - usage(argv[0]); + } + + else if (*argv[i] == '-') { + fprintf (stderr, "Unknown switch: %s\n", argv[i]); + usage (argv[0]); } else - strncpy(conf.hotplugdev, argv[i], FILE_NAME_SIZE); + strncpy (conf.hotplugdev, argv[i], FILE_NAME_SIZE); + } + + /* if we have a config file read it (overwrite hwtable) */ + if (check_config () && conf.iopolicy < 0) { + conf.hwtable = read_config (getuid_list); + + /* read_config went nuts, fall back to defaults */ + if (conf.hwtable == NULL) { + setup_default_hwtable; + conf.hwtable = default_hwtable_addr; + } + + } else { + setup_default_hwtable; + conf.hwtable = default_hwtable_addr; } - /* if we have a config file read it (overwrite wlist) */ - if (check_config() && conf.iopolicy < 0) - wlist = read_config(getuid_list); /* dynamic allocations */ - mp = malloc(conf.max_devs * sizeof(struct multipath)); - all_paths = malloc(conf.max_devs * sizeof(struct path)); - all_scsi_ids = malloc(conf.max_devs * sizeof(struct scsi_dev)); + mp = malloc (conf.max_devs * sizeof (struct multipath)); + all_paths = malloc (conf.max_devs * sizeof (struct path)); + all_scsi_ids = malloc (conf.max_devs * sizeof (struct scsi_dev)); + if (mp == NULL || all_paths == NULL || all_scsi_ids == NULL) - exit(1); + exit (1); - if (sysfs_get_mnt_path(conf.sysfs_path, FILE_NAME_SIZE)) { - get_all_scsi_ids(&conf, all_scsi_ids); - get_all_paths_nosysfs(&conf, all_paths, all_scsi_ids); + if (sysfs_get_mnt_path (conf.sysfs_path, FILE_NAME_SIZE)) { + get_all_scsi_ids (&conf, all_scsi_ids); + get_all_paths_nosysfs (&conf, all_paths, all_scsi_ids); } else { - get_all_paths_sysfs(&conf, all_paths); + get_all_paths_sysfs (&conf, all_paths); } - nmp = coalesce_paths(&conf, mp, all_paths); + nmp = coalesce_paths (&conf, mp, all_paths); if (conf.verbose) { - print_all_path(&conf, all_paths); - fprintf(stdout, "\n"); - print_all_mp(all_paths, mp, nmp); - fprintf(stdout, "\n"); + print_all_path (&conf, all_paths); + print_all_mp (all_paths, mp, nmp); + } + + /* last chance to quit before messing with devmaps */ + if (conf.dry_run) { + unlink (RUN); + exit (0); } - if (conf.dry_run) - exit(0); + if (conf.verbose) + fprintf (stdout, "# device maps :\n"); for (k=0; k<=nmp; k++) { - if (map_present(mp[k].wwid)) { - setup_map(&conf, all_paths, mp, k, DM_DEVICE_RELOAD); + if (map_present (mp[k].wwid)) { + setup_map (&conf, all_paths, &mp[k], DM_DEVICE_RELOAD); } else { - setup_map(&conf, all_paths, mp, k, DM_DEVICE_CREATE); + setup_map (&conf, all_paths, &mp[k], DM_DEVICE_CREATE); } } /* signal multipathd that new devmaps may have come up */ - signal_daemon(); + signal_daemon (); /* free allocs */ - free(mp); - free(all_paths); - free(all_scsi_ids); + free (mp); + free (all_paths); + free (all_scsi_ids); /* release runfile */ - unlink(RUN); + unlink (RUN); - exit(0); + exit (0); } diff -urN multipath-tools-0.1.3/multipath/main.h multipath-tools-0.1.4/multipath/main.h --- multipath-tools-0.1.3/multipath/main.h 2004-03-13 15:35:47.000000000 +0100 +++ multipath-tools-0.1.4/multipath/main.h 2004-03-16 10:25:10.000000000 +0100 @@ -103,6 +103,13 @@ int pindex[MAX_MP_PATHS]; }; +struct hwentry { + char vendor[8]; + char product[16]; + int iopolicy; + int (*getuid) (char *, char *); +}; + struct env { int max_devs; int verbose; @@ -114,13 +121,7 @@ int minor; char sysfs_path[FILE_NAME_SIZE]; char hotplugdev[FILE_NAME_SIZE]; -}; - -struct hwentry { - char vendor[8]; - char product[16]; - int iopolicy; - int (*getuid) (char *, char *); + struct hwentry * hwtable; }; /* Build version */ diff -urN multipath-tools-0.1.3/multipath/pgpolicies.c multipath-tools-0.1.4/multipath/pgpolicies.c --- multipath-tools-0.1.3/multipath/pgpolicies.c 1970-01-01 01:00:00.000000000 +0100 +++ multipath-tools-0.1.4/multipath/pgpolicies.c 2004-03-16 17:53:36.000000000 +0100 @@ -0,0 +1,158 @@ +#include +#include +#include +#include "main.h" +#include "pgpolicies.h" + +#define SELECTOR "round-robin" +#define SELECTOR_ARGS 0 + +extern void +group_by_tur (struct multipath * mp, struct path * all_paths, char * str) { + int left_path_count = 0; + int right_path_count = 0; + int i; + char left_path_buff[FILE_NAME_SIZE]; + char right_path_buff[FILE_NAME_SIZE]; + char * left_path_buff_p = &left_path_buff[0]; + char * right_path_buff_p = &right_path_buff[0]; + + for (i = 0; i <= mp->npaths; i++) { + + if (all_paths[mp->pindex[i]].tur) { + + left_path_buff_p += sprintf (left_path_buff_p, " %s", + all_paths[mp->pindex[i]].dev); + + left_path_count++; + + } else { + + right_path_buff_p += sprintf (right_path_buff_p, " %s", + all_paths[mp->pindex[i]].dev); + + right_path_count++; + } + } + + if (!left_path_count) + sprintf (str, " 1 " SELECTOR " %i %i%s", + right_path_count, SELECTOR_ARGS, right_path_buff); + + else if (!right_path_count) + sprintf (str, " 1 " SELECTOR " %i %i%s", + left_path_count, SELECTOR_ARGS, left_path_buff); + + else + sprintf (str, " 2 " SELECTOR " %i %i%s " \ + SELECTOR " %i %i%s", + left_path_count, SELECTOR_ARGS, left_path_buff, + right_path_count, SELECTOR_ARGS, right_path_buff); +} + +extern 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, + " " SELECTOR " %i %i%s", + path_count, SELECTOR_ARGS, path_buff); + + } + + sprintf (str, " %i%s", pg_count, pg_buff); + free (bitmap); +} + + +extern void +one_path_per_group (struct multipath * mp, struct path * all_paths, char * str) +{ + int i; + char * p; + + p = str; + + p += sprintf (p, " %i", mp->npaths + 1); + + for (i=0; i <= mp->npaths; i++) { + + if (0 != all_paths[mp->pindex[i]].sg_id.scsi_type) + continue; + + p += sprintf (p, " " SELECTOR); + + p += sprintf (p, " 1 %i", SELECTOR_ARGS); + + p += sprintf (p, " %s", + all_paths[mp->pindex[i]].dev); + } + +} + +extern void +one_group (struct multipath * mp, struct path * all_paths, char * str) +{ + int i, np = 0; + char * p; + + p = str; + + for (i=0; i <= mp->npaths; i++) { + if (0 == all_paths[mp->pindex[i]].sg_id.scsi_type) + np++; + } + + p += sprintf (p, " 1 " SELECTOR " %i %i", np, SELECTOR_ARGS); + + for (i=0; i<= mp->npaths; i++) { + + if (0 != all_paths[mp->pindex[i]].sg_id.scsi_type) + continue; + + p += sprintf (p, " %s", + all_paths[mp->pindex[i]].dev); + } +} + diff -urN multipath-tools-0.1.3/multipath/pgpolicies.h multipath-tools-0.1.4/multipath/pgpolicies.h --- multipath-tools-0.1.3/multipath/pgpolicies.h 1970-01-01 01:00:00.000000000 +0100 +++ multipath-tools-0.1.4/multipath/pgpolicies.h 2004-03-16 12:37:25.000000000 +0100 @@ -0,0 +1,4 @@ +void one_path_per_group (struct multipath *, struct path *, char *); +void one_group (struct multipath *, struct path *, char *); +void group_by_serial (struct multipath *, struct path *, char *); +void group_by_tur (struct multipath *, struct path *, char *);