--- multipath-tools-0.4.8/Makefile.inc +++ multipath-tools-0.4.8/Makefile.inc @@ -13,7 +13,7 @@ TOPDIR = .. endif -prefix = +prefix = exec_prefix = $(prefix) bindir = $(exec_prefix)/sbin libudevdir = ${prefix}/lib/udev --- multipath-tools-0.4.8/kpartx/Makefile +++ multipath-tools-0.4.8/kpartx/Makefile @@ -15,21 +15,29 @@ $(EXEC): $(OBJS) $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) - $(GZIP) $(EXEC).8 > $(EXEC).8.gz - + install: $(EXEC) $(EXEC).8 $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -m 755 activate_dm_linear $(DESTDIR)$(bindir) $(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir) $(INSTALL_PROGRAM) -m 755 kpartx_id $(DESTDIR)$(libudevdir) $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d - $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/ + $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/70-kpartx.rules $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) - $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -d $(DESTDIR)/lib/mkinitrd/scripts + $(INSTALL_PROGRAM) -m 755 boot-kpartx.sh $(DESTDIR)/lib/mkinitrd/scripts + $(INSTALL_PROGRAM) -m 755 setup-kpartx.sh $(DESTDIR)/lib/mkinitrd/scripts uninstall: rm -f $(DESTDIR)$(bindir)/$(EXEC) - rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz + rm -f $(DESTDIR)$(bindir)/activate_dm_linear + rm -f $(DESTDIR)$(libudevdir)/kpartx_id + rm -f $(DESTDIR)/etc/udev/rules.d/70-kpartx.rules + rm -f $(DESTDIR)$(mandir)/$(EXEC).8 + rm -f $(DESTDIR)/lib/mkinitrd/scripts/boot-kpartx.sh + rm -f $(DESTDIR)/lib/mkinitrd/scripts/setup-kpartx.sh clean: - rm -f core *.o $(EXEC) *.gz + rm -f core *.o $(EXEC) --- multipath-tools-0.4.8/kpartx/activate_dm_linear +++ multipath-tools-0.4.8/kpartx/activate_dm_linear @@ -0,0 +1,72 @@ +#!/bin/sh +# +# activate_dm_linear +# +# Activate a linear mapping on top of an existing block device. +# This allows for partitions to be mapped via kpartx, so all +# partitions on a device can be accessed. +# + +RULE=/etc/udev/rules.d/62-dm_linear.rules + +if [ -z "$1" ] ; then + echo "Usage: $0 [-d] devname" + exit 1 +fi + +if [ "$1" == "-d" ] ; then + remove_only=1 + shift +fi + +if [ ! -b "$1" ] ; then + echo "$1 is not a block device" + exit 1 +fi + +dev=${1#/dev/} + +if [ ! -d /sys/block/$dev ] ; then + echo "$1 is not a disk device" + exit 1 +fi + +blksize=$(/sbin/blockdev --getsize $1) +if [ $? -ne 0 ] ; then + echo "blockdev --getsize $1 failed: $?" + exit 1 +fi + +for link in $(udevadm info -q symlink -p /block/$dev) ; do + case "$link" in + */by-id/ata*) + atalink=${link#*/by-id/ata-} + ;; + */by-id/scsi*) + scsilink=${link#*/by-id/scsi-} + ;; + esac +done +if [ "$atalink" ] ; then + # Remove existing rules + echo "/$atalink/d +w +q +" | ed $RULE > /dev/null 2>&1 + [ "$remove_only" = 1 ] && exit 0 + cat >> $RULE < /dev/null 2>&1 + [ "$remove_only" = 1 ] && exit 0 + # And create a new one + cat >> $RULE < params + strlen(params)) + break; + /* Skip whitespaces */ + while(ptr && *ptr == ' ') ptr++; + if (!strncmp(ptr, FEATURE_NO_PART, strlen(FEATURE_NO_PART))) + return 1; + ptr = strchr(ptr, ' '); + } + return 0; +} + --- multipath-tools-0.4.8/kpartx/devmapper.h +++ multipath-tools-0.4.8/kpartx/devmapper.h @@ -7,3 +7,4 @@ dev_t dm_get_first_dep(char *devname); char * dm_mapuuid(int major, int minor); int dm_devn (char * mapname, int *major, int *minor); +int dm_no_partitions(int major, int minor); --- multipath-tools-0.4.8/kpartx/kpartx.c +++ multipath-tools-0.4.8/kpartx/kpartx.c @@ -257,7 +257,7 @@ } if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE)) { - fprintf(stderr, "device mapper prerequisites not met\n"); + fprintf(stderr, "device mapper prerequisites not met\n"); exit(1); } @@ -314,8 +314,13 @@ if (!uuid) uuid = device + off; - if (!mapname) + if (!mapname) { mapname = device + off; + } else if (dm_no_partitions((unsigned int)MAJOR(buf.st_rdev), + (unsigned int)MINOR(buf.st_rdev))) { + /* Feature 'no_partitions' is set, return */ + return 0; + } fd = open(device, O_RDONLY); @@ -423,7 +428,7 @@ break; case ADD: - for (j=0, c = 0; jregex, str, 0, NULL, 0)) + vector_foreach_slot (elist, ele, i) { + if (!regexec(&ele->regex, str, 0, NULL, 0)) return 1; } - return 0; + return 0; } int @@ -194,11 +194,11 @@ } #define LOG_BLIST(M) \ - if (vendor && product) \ + if (vendor && product) \ condlog(3, "%s: (%s:%s) %s", dev, vendor, product, (M)); \ - else if (wwid) \ - condlog(3, "%s: (%s) %s", dev, wwid, (M)); \ - else \ + else if (wwid) \ + condlog(3, "%s: (%s) %s", dev, wwid, (M)); \ + else \ condlog(3, "%s: %s", dev, (M)) void @@ -300,7 +300,7 @@ if (r > 0) return r; r = _filter_device(conf->blist_device, conf->elist_device, - pp->vendor_id, pp->product_id); + pp->vendor_id, pp->product_id); if (r > 0) return r; r = _filter_wwid(conf->blist_wwid, conf->elist_wwid, pp->wwid); --- multipath-tools-0.4.8/libmultipath/callout.c +++ multipath-tools-0.4.8/libmultipath/callout.c @@ -83,8 +83,8 @@ null_fd = open("/dev/null", O_WRONLY); if (null_fd > 0) { close(STDERR_FILENO); - dup(null_fd); - close(null_fd); + if (dup(null_fd) >= 0) + close(null_fd); } retval = execv(argv[0], argv); --- multipath-tools-0.4.8/libmultipath/config.c +++ multipath-tools-0.4.8/libmultipath/config.c @@ -50,42 +50,55 @@ return ret; } +static int +hwe_regmatch (struct hwentry *hwe1, struct hwentry *hwe2) +{ + regex_t vre, pre, rre; + int retval = 1; + + if (hwe1->vendor && + regcomp(&vre, hwe1->vendor, REG_EXTENDED|REG_NOSUB)) + goto out; + + if (hwe1->product && + regcomp(&pre, hwe1->product, REG_EXTENDED|REG_NOSUB)) + goto out_vre; + + if (hwe1->revision && + regcomp(&rre, hwe1->revision, REG_EXTENDED|REG_NOSUB)) + goto out_pre; + + if ((!hwe1->vendor || !regexec(&vre, hwe2->vendor, 0, NULL, 0)) && + (!hwe1->product || !regexec(&pre, hwe2->product, 0, NULL, 0)) && + (!hwe1->revision || !regexec(&rre, hwe2->revision, 0, NULL, 0))) + retval = 0; + + if (hwe1->revision) + regfree(&rre); +out_pre: + if (hwe1->product) + regfree(&pre); +out_vre: + if (hwe1->vendor) + regfree(&vre); +out: + return retval; +} + struct hwentry * find_hwe (vector hwtable, char * vendor, char * product, char * revision) { int i; - struct hwentry *hwe, *ret = NULL; - regex_t vre, pre, rre; + struct hwentry hwe, *tmp, *ret = NULL; - vector_foreach_slot (hwtable, hwe, i) { - if (hwe->vendor && - regcomp(&vre, hwe->vendor, REG_EXTENDED|REG_NOSUB)) - break; - if (hwe->product && - regcomp(&pre, hwe->product, REG_EXTENDED|REG_NOSUB)) { - regfree(&vre); - break; - } - if (hwe->revision && - regcomp(&rre, hwe->revision, REG_EXTENDED|REG_NOSUB)) { - regfree(&vre); - regfree(&pre); - break; - } - if ((!hwe->vendor || !regexec(&vre, vendor, 0, NULL, 0)) && - (!hwe->product || !regexec(&pre, product, 0, NULL, 0)) && - (!hwe->revision || !regexec(&rre, revision, 0, NULL, 0))) - ret = hwe; - - if (hwe->revision) - regfree(&rre); - if (hwe->product) - regfree(&pre); - if (hwe->vendor) - regfree(&vre); - - if (ret) - break; + hwe.vendor = vendor; + hwe.product = product; + hwe.revision = revision; + vector_foreach_slot (hwtable, tmp, i) { + if (hwe_regmatch(tmp, &hwe)) + continue; + ret = tmp; + break; } return ret; } @@ -289,25 +302,25 @@ if (find_hwe_strmatch(hwtable, dhwe)) return 0; - + if (!(hwe = alloc_hwe())) return 1; if (!dhwe->vendor || !(hwe->vendor = set_param_str(dhwe->vendor))) goto out; - + if (!dhwe->product || !(hwe->product = set_param_str(dhwe->product))) goto out; - + if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision))) goto out; - + if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid))) goto out; if (dhwe->features && !(hwe->features = set_param_str(dhwe->features))) goto out; - + if (dhwe->hwhandler && !(hwe->hwhandler = set_param_str(dhwe->hwhandler))) goto out; @@ -316,10 +329,10 @@ if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name))) goto out; - + if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name))) goto out; - + hwe->pgpolicy = dhwe->pgpolicy; hwe->pgfailback = dhwe->pgfailback; hwe->rr_weight = dhwe->rr_weight; @@ -348,7 +361,7 @@ vector_foreach_slot(hw, hwe1, i) { j = i+1; vector_foreach_slot_after(hw, hwe2, j) { - if (hwe_strmatch(hwe1, hwe2)) + if (hwe_regmatch(hwe1, hwe2)) continue; /* dup */ merge_hwe(hwe1, hwe2); @@ -393,6 +406,9 @@ if (conf->hwhandler) FREE(conf->hwhandler); + if (conf->bindings_file) + FREE(conf->bindings_file); + free_blacklist(conf->blist_devnode); free_blacklist(conf->blist_wwid); free_blacklist_device(conf->blist_device); @@ -425,7 +441,6 @@ conf->dev_type = DEV_NONE; conf->minio = 1000; conf->max_fds = 0; - conf->bindings_file = DEFAULT_BINDINGS_FILE; conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR); /* @@ -443,12 +458,15 @@ /* * read the config file */ + set_current_keywords(&conf->keywords); + alloc_keywords(); if (filepresent(file)) { - set_current_keywords(&conf->keywords); if (init_data(file, init_keywords)) { condlog(0, "error parsing config file"); goto out; } + } else { + init_keywords(); } /* @@ -503,7 +521,6 @@ if (conf->mptable == NULL) { conf->mptable = vector_alloc(); - if (!conf->mptable) goto out; } @@ -522,9 +539,12 @@ if (conf->hwhandler == NULL) conf->hwhandler = set_default(DEFAULT_HWHANDLER); + if (conf->bindings_file == NULL) + conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE); + if (!conf->selector || !conf->udev_dir || !conf->multipath_dir || !conf->getuid || !conf->features || - !conf->hwhandler) + !conf->hwhandler || !conf->bindings_file) goto out; if (!conf->prio_name) --- multipath-tools-0.4.8/libmultipath/configure.c +++ multipath-tools-0.4.8/libmultipath/configure.c @@ -162,7 +162,7 @@ mpp->alias); return; } - + if (pathcount(mpp, PATH_UP) == 0) { mpp->action = ACT_NOTHING; condlog(3, "%s: set ACT_NOTHING (no usable path)", @@ -272,7 +272,7 @@ if (!mpp || !mpp->pg) return 0; - + vector_foreach_slot (mpp->pg, pgp, i) { if (!pgp->paths) continue; @@ -402,7 +402,7 @@ if (strlen(pp->dev)) return 0; /* alive */ } - + return 1; /* dead */ } @@ -460,13 +460,13 @@ remove_map(mpp, vecs, 0); continue; } - + for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) { pp2 = VECTOR_SLOT(pathvec, i); if (strcmp(pp1->wwid, pp2->wwid)) continue; - + if (!pp2->size) continue; --- multipath-tools-0.4.8/libmultipath/defaults.h +++ multipath-tools-0.4.8/libmultipath/defaults.h @@ -1,4 +1,4 @@ -#define DEFAULT_GETUID "/lib/udev/scsi_id -g -u -s /block/%n" +#define DEFAULT_GETUID "/lib/udev/scsi_id -g -u /dev/%n" #define DEFAULT_UDEVDIR "/dev" #define DEFAULT_MULTIPATHDIR "/lib/multipath" #define DEFAULT_SELECTOR "round-robin 0" --- multipath-tools-0.4.8/libmultipath/devmapper.c +++ multipath-tools-0.4.8/libmultipath/devmapper.c @@ -161,9 +161,9 @@ goto out; dm_task_no_open_count(dmt); - dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ + dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ #ifdef LIBDM_API_FLUSH - dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ + dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ #endif r = dm_task_run (dmt); @@ -340,11 +340,11 @@ if (!dmt) return 1; - if (!dm_task_set_name (dmt, name)) - goto uuidout; + if (!dm_task_set_name (dmt, name)) + goto uuidout; if (!dm_task_run(dmt)) - goto uuidout; + goto uuidout; uuidtmp = dm_task_get_uuid(dmt); if (uuidtmp) { @@ -466,7 +466,7 @@ dm_task_destroy(dmt); return r; } - + int dm_get_opencount (const char * mapname) { @@ -491,7 +491,7 @@ dm_task_destroy(dmt); return r; } - + int dm_get_minor (char * mapname) { @@ -516,7 +516,7 @@ dm_task_destroy(dmt); return r; } - + extern int dm_flush_map (const char * mapname) { @@ -534,7 +534,7 @@ if (dm_get_opencount(mapname)) { condlog(2, "%s: map in use", mapname); return 1; - } + } r = dm_simplecmd(DM_DEVICE_REMOVE, mapname); @@ -746,8 +746,8 @@ vector_set_slot(mp, mpp); mpp = NULL; next: - next = names->next; - names = (void *) names + next; + next = names->next; + names = (void *) names + next; } while (next); r = 0; @@ -927,7 +927,7 @@ */ strstr(params, dev_t) ) { - /* + /* * then it's a kpartx generated partition. * remove it. */ @@ -957,7 +957,7 @@ { int r = 1; struct dm_task *dmt = NULL; - + if (!mapname) return 1; @@ -1045,7 +1045,7 @@ */ strstr(buff, dev_t) ) { - /* + /* * then it's a kpartx generated partition. * Rename it. */ @@ -1083,7 +1083,7 @@ if (!dm_task_set_newname(dmt, new)) goto out; - + dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) --- multipath-tools-0.4.8/libmultipath/dict.c +++ multipath-tools-0.4.8/libmultipath/dict.c @@ -88,7 +88,7 @@ if (!conf->getuid) return 1; - + return 0; } @@ -267,6 +267,17 @@ return 0; } +static int +bindings_file_handler(vector strvec) +{ + conf->bindings_file = set_value(strvec); + + if (!conf->bindings_file) + return 1; + + return 0; +} + /* * blacklist block handlers */ @@ -338,12 +349,12 @@ static int ble_except_wwid_handler(vector strvec) { - char * buff; + char * buff; - buff = set_value(strvec); + buff = set_value(strvec); - if (!buff) - return 1; + if (!buff) + return 1; return store_ble(conf->elist_wwid, buff, ORIGIN_CONFIG); } @@ -453,7 +464,7 @@ if (!hwe) return 1; - + hwe->vendor = set_value(strvec); if (!hwe->vendor) @@ -469,7 +480,7 @@ if (!hwe) return 1; - + hwe->product = set_value(strvec); if (!hwe->product) @@ -527,7 +538,7 @@ hw_selector_handler(vector strvec) { struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); - + if (!hwe) return 1; @@ -559,7 +570,7 @@ hw_features_handler(vector strvec) { struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); - + if (!hwe) return 1; @@ -575,7 +586,7 @@ hw_handler_handler(vector strvec) { struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); - + if (!hwe) return 1; @@ -781,7 +792,7 @@ if (!mpe) return 1; - mpe->alias = set_value(strvec); + mpe->alias = set_value(strvec); if (!mpe->alias) return 1; @@ -813,7 +824,7 @@ mp_selector_handler(vector strvec) { struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); - + if (!mpe) return 1; @@ -981,7 +992,7 @@ if (!mpe->pgpolicy) return 0; get_pgpolicy_name(str, POLICY_NAME_SIZE, mpe->pgpolicy); - + return snprintf(buff, len, "%s", str); } @@ -1194,7 +1205,7 @@ return 0; get_pgpolicy_name(str, POLICY_NAME_SIZE, hwe->pgpolicy); - + return snprintf(buff, len, "%s", str); } @@ -1362,7 +1373,7 @@ return 0; get_pgpolicy_name(str, POLICY_NAME_SIZE, conf->pgpolicy); - + return snprintf(buff, len, "%s", str); } @@ -1454,7 +1465,7 @@ return 0; if (conf->max_fds < 0) - return snprintf(buff, len, "unlimited"); + return snprintf(buff, len, "unlimited"); return snprintf(buff, len, "%d", conf->max_fds); } @@ -1520,6 +1531,18 @@ } static int +snprint_def_bindings_file (char * buff, int len, void * data) +{ + if (conf->bindings_file == NULL) + return 0; + if (strlen(conf->bindings_file) == strlen(DEFAULT_BINDINGS_FILE) && + !strcmp(conf->bindings_file, DEFAULT_BINDINGS_FILE)) + return 0; + + return snprintf(buff, len, "%s", conf->bindings_file); +} + +static int snprint_ble_simple (char * buff, int len, void * data) { struct blentry * ble = (struct blentry *)data; @@ -1534,7 +1557,7 @@ return snprintf(buff, len, "\"%s\"", bled->vendor); } - + static int snprint_bled_product (char * buff, int len, void * data) { @@ -1542,7 +1565,7 @@ return snprintf(buff, len, "\"%s\"", bled->product); } - + #define __deprecated void @@ -1566,6 +1589,7 @@ install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry); install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout); install_keyword("user_friendly_names", &names_handler, &snprint_def_user_friendly_names); + install_keyword("bindings_file", &bindings_file_handler, &snprint_def_bindings_file); __deprecated install_keyword("default_selector", &def_selector_handler, NULL); __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); __deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL); --- multipath-tools-0.4.8/libmultipath/discovery.c +++ multipath-tools-0.4.8/libmultipath/discovery.c @@ -70,7 +70,7 @@ condlog(0, "path too small"); return 1; } - + if (strncmp(devname,"cciss",5) && !filepresent(path)) { condlog(4, "path %s not present", path); return 0; @@ -179,7 +179,7 @@ return 0; } - + int sysfs_get_fc_nodename (struct sysfs_device * dev, char * node, unsigned int host, unsigned int channel, @@ -187,7 +187,7 @@ { char attr_path[SYSFS_PATH_SIZE], *attr; - if (safe_sprintf(attr_path, + if (safe_sprintf(attr_path, "/class/fc_transport/target%i:%i:%i", host, channel, target)) { condlog(0, "attr_path too small"); @@ -202,10 +202,7 @@ return 1; } - -/* - * udev might be slow creating node files : wait - */ + static int opennode (char * dev, int mode) { @@ -244,11 +241,11 @@ condlog(0, "Cannot open /proc/partitions"); return 1; } - + while (!feof(fd)) { int r = fscanf(fd,"%u %u %*d %s",&tmpmaj, &tmpmin, dev); if (!r) { - fscanf(fd,"%*s\n"); + r = fscanf(fd,"%*s\n"); continue; } if (r != 3) @@ -280,62 +277,62 @@ do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, void *resp, int mx_resp_len, int noisy) { - unsigned char inqCmdBlk[INQUIRY_CMDLEN] = - { INQUIRY_CMD, 0, 0, 0, 0, 0 }; - unsigned char sense_b[SENSE_BUFF_LEN]; - struct sg_io_hdr io_hdr; - - if (cmddt) - inqCmdBlk[1] |= 2; - if (evpd) - inqCmdBlk[1] |= 1; - inqCmdBlk[2] = (unsigned char) pg_op; + unsigned char inqCmdBlk[INQUIRY_CMDLEN] = + { INQUIRY_CMD, 0, 0, 0, 0, 0 }; + unsigned char sense_b[SENSE_BUFF_LEN]; + struct sg_io_hdr io_hdr; + + if (cmddt) + inqCmdBlk[1] |= 2; + if (evpd) + inqCmdBlk[1] |= 1; + inqCmdBlk[2] = (unsigned char) pg_op; inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (inqCmdBlk); - io_hdr.mx_sb_len = sizeof (sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = mx_resp_len; - io_hdr.dxferp = resp; - io_hdr.cmdp = inqCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) - return -1; - - /* treat SG_ERR here to get rid of sg_err.[ch] */ - io_hdr.status &= 0x7e; - if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && - (0 == io_hdr.driver_status)) - return 0; - if ((SCSI_CHECK_CONDITION == io_hdr.status) || - (SCSI_COMMAND_TERMINATED == io_hdr.status) || - (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { - if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { - int sense_key; - unsigned char * sense_buffer = io_hdr.sbp; - if (sense_buffer[0] & 0x2) - sense_key = sense_buffer[1] & 0xf; - else - sense_key = sense_buffer[2] & 0xf; - if(RECOVERED_ERROR == sense_key) - return 0; - } - } - return -1; + memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = sizeof (inqCmdBlk); + io_hdr.mx_sb_len = sizeof (sense_b); + io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; + io_hdr.dxfer_len = mx_resp_len; + io_hdr.dxferp = resp; + io_hdr.cmdp = inqCmdBlk; + io_hdr.sbp = sense_b; + io_hdr.timeout = DEF_TIMEOUT; + + if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) + return -1; + + /* treat SG_ERR here to get rid of sg_err.[ch] */ + io_hdr.status &= 0x7e; + if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && + (0 == io_hdr.driver_status)) + return 0; + if ((SCSI_CHECK_CONDITION == io_hdr.status) || + (SCSI_COMMAND_TERMINATED == io_hdr.status) || + (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { + if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { + int sense_key; + unsigned char * sense_buffer = io_hdr.sbp; + if (sense_buffer[0] & 0x2) + sense_key = sense_buffer[1] & 0xf; + else + sense_key = sense_buffer[2] & 0xf; + if(RECOVERED_ERROR == sense_key) + return 0; + } + } + return -1; } static int get_serial (char * str, int maxlen, int fd) { - int len = 0; - char buff[MX_ALLOC_LEN + 1] = {0}; + int len = 0; + char buff[MX_ALLOC_LEN + 1] = {0}; if (fd < 0) - return 1; + return 1; if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) { len = buff[3]; @@ -347,7 +344,7 @@ } return 0; } - return 1; + return 1; } static int @@ -459,7 +456,7 @@ /* * host / bus / target / lun - */ + */ basename(parent->devpath, attr_path); pp->sg_id.lun = 0; sscanf(attr_path, "%i.%i.%x", --- multipath-tools-0.4.8/libmultipath/dmparser.c +++ multipath-tools-0.4.8/libmultipath/dmparser.c @@ -59,7 +59,7 @@ minio = mp->minio; p = mp->params; freechar = sizeof(mp->params); - + shift = snprintf(p, freechar, "%s %s %i %i", mp->features, mp->hwhandler, VECTOR_SIZE(mp->pg), mp->bestpg); @@ -70,7 +70,7 @@ } p += shift; freechar -= shift; - + vector_foreach_slot (mp->pg, pgp, i) { pgp = VECTOR_SLOT(mp->pg, i); shift = snprintf(p, freechar, " %s %i 1", mp->selector, @@ -184,11 +184,11 @@ num_pg = atoi(word); FREE(word); - if (num_pg > 0 && !mpp->pg) { + if (num_pg > 0 && !mpp->pg) mpp->pg = vector_alloc(); - if (!mpp->pg) - return 1; - } + + if (!mpp->pg) + return 1; /* * first pg to try @@ -221,7 +221,7 @@ goto out; num_pg_args = atoi(word); - + if (merge_words(&mpp->selector, word, 1)) { FREE(word); goto out1; @@ -239,7 +239,7 @@ * paths */ pgp = alloc_pathgroup(); - + if (!pgp) goto out; --- multipath-tools-0.4.8/libmultipath/hwtable.c +++ multipath-tools-0.4.8/libmultipath/hwtable.c @@ -172,7 +172,7 @@ /* HP Smart Array */ .vendor = "HP", .product = "LOGICAL VOLUME.*", - .getuid = "/lib/udev/scsi_id -n -g -u -s /block/%n", + .getuid = "/lib/udev/scsi_id -n -g -u /dev/%n", .features = DEFAULT_FEATURES, .hwhandler = DEFAULT_HWHANDLER, .selector = DEFAULT_SELECTOR, @@ -214,7 +214,7 @@ { .vendor = "EMC", .product = "SYMMETRIX", - .getuid = "/lib/udev/scsi_id -g -u -ppre-spc3-83 -s /block/%n", + .getuid = "/lib/udev/scsi_id -g -u -ppre-spc3-83 /dev/%n", .features = DEFAULT_FEATURES, .hwhandler = DEFAULT_HWHANDLER, .selector = DEFAULT_SELECTOR, @@ -533,7 +533,7 @@ .no_path_retry = NO_PATH_RETRY_UNDEF, .minio = 128, .checker_name = DIRECTIO, - .prio_name = PRIO_NETAPP, + .prio_name = PRIO_ONTAP, }, /* * IBM NSeries (NETAPP) controller family @@ -554,7 +554,7 @@ .no_path_retry = NO_PATH_RETRY_UNDEF, .minio = 128, .checker_name = DIRECTIO, - .prio_name = PRIO_NETAPP, + .prio_name = PRIO_ONTAP, }, /* * Pillar Data controller family --- multipath-tools-0.4.8/libmultipath/log.c +++ multipath-tools-0.4.8/libmultipath/log.c @@ -18,7 +18,7 @@ static void dump_logarea (void) { struct logmsg * msg; - + logdbg(stderr, "\n==== area: start addr = %p, end addr = %p ====\n", la->start, la->end); logdbg(stderr, "|addr |next |prio|msg\n"); @@ -34,12 +34,12 @@ logdbg(stderr, "\n\n"); } #endif - + static int logarea_init (int size) { logdbg(stderr,"enter logarea_init\n"); la = (struct logarea *)MALLOC(sizeof(struct logarea)); - + if (!la) return 1; @@ -107,7 +107,7 @@ lastmsg = (struct logmsg *)la->tail; if (!la->empty) { - fwd = sizeof(struct logmsg) + + fwd = sizeof(struct logmsg) + strlen((char *)&lastmsg->str) * sizeof(char) + 1; la->tail += ALIGN(fwd, sizeof(void *)); } @@ -118,11 +118,11 @@ /* not enough space on tail : rewind */ if (la->head <= la->tail && len > (la->end - la->tail)) { logdbg(stderr, "enqueue: rewind tail to %p\n", la->tail); - if (la->head == la->start ) { - logdbg(stderr, "enqueue: can not rewind tail, drop msg\n"); - la->tail = lastmsg; - return 1; /* can't reuse */ - } + if (la->head == la->start ) { + logdbg(stderr, "enqueue: can not rewind tail, drop msg\n"); + la->tail = lastmsg; + return 1; /* can't reuse */ + } la->tail = la->start; if (la->empty) --- multipath-tools-0.4.8/libmultipath/log_pthread.c +++ multipath-tools-0.4.8/libmultipath/log_pthread.c @@ -53,17 +53,17 @@ void log_thread_start (void) { pthread_attr_t attr; - + logdbg(stderr,"enter log_thread_start\n"); logq_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); logev_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); logev_cond = (pthread_cond_t *) malloc(sizeof(pthread_cond_t)); - + pthread_mutex_init(logq_lock, NULL); pthread_mutex_init(logev_lock, NULL); pthread_cond_init(logev_cond, NULL); - + pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 64 * 1024); @@ -90,5 +90,11 @@ pthread_mutex_destroy(logev_lock); pthread_cond_destroy(logev_cond); + free(logq_lock); + logq_lock = NULL; + free(logev_lock); + logev_lock = NULL; + free(logev_cond); + logev_cond = NULL; free_logarea(); -} +} --- multipath-tools-0.4.8/libmultipath/parser.c +++ multipath-tools-0.4.8/libmultipath/parser.c @@ -1,11 +1,11 @@ -/* +/* * Part: Configuration file parser/reader. Place into the dynamic * data structure representation the conf file - * + * * Version: $Id: parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $ - * + * * Author: Alexandre Cassen, - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -43,7 +43,7 @@ if (!keyword) return 1; - + if (!vector_alloc_slot(keywords)) { FREE(keyword); return 1; @@ -450,7 +450,7 @@ break; } } - + free_strvec(strvec); } @@ -458,16 +458,23 @@ return r; } +int alloc_keywords(void) +{ + if (!keywords) + keywords = vector_alloc(); + + if (!keywords) + return 1; + + return 0; +} + /* Data initialization */ int init_data(char *conf_file, void (*init_keywords) (void)) { int r; - if (!keywords) - keywords = vector_alloc(); - if (!keywords) - return 1; stream = fopen(conf_file, "r"); if (!stream) { syslog(LOG_WARNING, "Configuration file open problem"); --- multipath-tools-0.4.8/libmultipath/parser.h +++ multipath-tools-0.4.8/libmultipath/parser.h @@ -74,6 +74,7 @@ extern int alloc_value_block(vector strvec, void (*alloc_func) (vector)); extern void *set_value(vector strvec); extern int process_stream(vector keywords); +extern int alloc_keywords(void); extern int init_data(char *conf_file, void (*init_keywords) (void)); extern struct keyword * find_keyword(vector v, char * name); void set_current_keywords (vector *k); --- multipath-tools-0.4.8/libmultipath/pgpolicies.c +++ multipath-tools-0.4.8/libmultipath/pgpolicies.c @@ -67,7 +67,7 @@ struct path * pp; struct pathgroup * pgp; struct path * pp2; - + if (!mp->pg) mp->pg = vector_alloc(); @@ -103,12 +103,12 @@ bitmap[i] = 1; for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) { - + if (bitmap[j]) continue; pp2 = VECTOR_SLOT(mp->paths, j); - + if (!strncmp(pp->tgt_node_name, pp2->tgt_node_name, NODE_NAME_SIZE)) { if (store_path(pgp->paths, pp2)) @@ -140,7 +140,7 @@ struct path * pp; struct pathgroup * pgp; struct path * pp2; - + if (!mp->pg) mp->pg = vector_alloc(); @@ -172,16 +172,16 @@ /* feed the first path */ if (store_path(pgp->paths, pp)) goto out1; - + bitmap[i] = 1; for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) { - + if (bitmap[j]) continue; pp2 = VECTOR_SLOT(mp->paths, j); - + if (0 == strcmp(pp->serial, pp2->serial)) { if (store_path(pgp->paths, pp2)) goto out1; @@ -211,7 +211,7 @@ if (!mp->pg) mp->pg = vector_alloc(); - + if (!mp->pg) return 1; @@ -224,7 +224,7 @@ if (store_pathgroup(mp->pg, pgp)) goto out; - + if (store_path(pgp->paths, pp)) goto out; } @@ -252,10 +252,10 @@ return 1; pgp = alloc_pathgroup(); - + if (!pgp) goto out; - + vector_free(pgp->paths); pgp->paths = mp->paths; mp->paths = NULL; @@ -306,7 +306,7 @@ if (!pgp) goto out; - + if (store_path(pgp->paths, VECTOR_SLOT(mp->paths, 0))) goto out; --- multipath-tools-0.4.8/libmultipath/print.c +++ multipath-tools-0.4.8/libmultipath/print.c @@ -29,7 +29,7 @@ #define PAD(x) while ((int)(c - s) < (x) && (c < (line + len - 1))) \ *c++ = ' '; s = c #define PRINT(var, size, format, args...) \ - fwd = snprintf(var, size, format, ##args); \ + fwd = snprintf(var, size, format, ##args); \ c += (fwd >= size) ? size : fwd; /* @@ -60,7 +60,7 @@ char fmt[6] = {}; char units[] = {'K','M','G','T','P'}; char *u = units; - + while (s >= 1024 && *u != 'P') { s = s / 1024; u++; @@ -112,7 +112,7 @@ int j = PROGRESS_LEN - i; char * c = buff; char * end = buff + len; - + while (i-- > 0) { c += snprintf(c, len, "X"); if ((len = (end - c)) <= 1) goto out; @@ -129,7 +129,7 @@ buff[c - buff + 1] = '\0'; return (c - buff + 1); } - + static int snprint_failback (char * buff, size_t len, struct multipath * mpp) { @@ -239,7 +239,7 @@ if (!pp) return 0; return snprintf(buff, len, "%s,%s", - pp->vendor_id, pp->product_id); + pp->vendor_id, pp->product_id); } static int @@ -335,7 +335,7 @@ snprint_vpr (char * buff, size_t len, struct path * pp) { return snprintf(buff, len, "%s,%s", - pp->vendor_id, pp->product_id); + pp->vendor_id, pp->product_id); } static int @@ -530,10 +530,10 @@ continue; } f++; - + if (!(data = mpd_lookup(*f))) break; /* unknown wildcard */ - + PRINT(c, TAIL, data->header); PAD(data->width); } while (*f++); @@ -565,10 +565,10 @@ continue; } f++; - + if (!(data = mpd_lookup(*f))) break; - + data->snprint(buff, MAX_FIELD_LEN, mpp); PRINT(c, TAIL, buff); PAD(data->width); @@ -600,10 +600,10 @@ continue; } f++; - + if (!(data = pd_lookup(*f))) break; /* unknown wildcard */ - + PRINT(c, TAIL, data->header); PAD(data->width); } while (*f++); @@ -635,10 +635,10 @@ continue; } f++; - + if (!(data = pd_lookup(*f))) break; - + data->snprint(buff, MAX_FIELD_LEN, pp); PRINT(c, TAIL, buff); PAD(data->width); @@ -671,10 +671,10 @@ continue; } f++; - + if (!(data = pgd_lookup(*f))) break; - + data->snprint(buff, MAX_FIELD_LEN, pgp); PRINT(c, TAIL, buff); PAD(data->width); @@ -718,7 +718,7 @@ c += sprintf(c, "%%A: "); c += sprintf(c, "%%n"); - + if (strncmp(mpp->alias, mpp->wwid, WWID_SIZE)) c += sprintf(c, " (%%w)"); @@ -890,7 +890,6 @@ if (fwd > len) return len; return fwd; - } static int @@ -956,7 +955,7 @@ if ((len - fwd - threshold) <= 0) return len; fwd += snprintf(buff + fwd, len - fwd, "device node rules:\n" - "- blacklist:\n"); + "- blacklist:\n"); if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_devnode)) return len; @@ -969,7 +968,7 @@ if ((len - fwd - threshold) <= 0) return len; fwd += snprintf(buff + fwd, len - fwd, "wwid rules:\n" - "- blacklist:\n"); + "- blacklist:\n"); if (snprint_blacklist_group(buff, len, &fwd, &conf->blist_wwid) == 0) return len; @@ -982,7 +981,7 @@ if ((len - fwd - threshold) <= 0) return len; fwd += snprintf(buff + fwd, len - fwd, "device rules:\n" - "- blacklist:\n"); + "- blacklist:\n"); if (snprint_blacklist_devgroup(buff, len, &fwd, &conf->blist_device) == 0) return len; @@ -1258,7 +1257,7 @@ fprintf(stdout, "===== no paths =====\n"); return; } - + if (banner) fprintf(stdout, "===== paths list =====\n"); --- multipath-tools-0.4.8/libmultipath/prio.h +++ multipath-tools-0.4.8/libmultipath/prio.h @@ -21,6 +21,7 @@ #define PRIO_HDS "hds" #define PRIO_HP_SW "hp_sw" #define PRIO_NETAPP "netapp" +#define PRIO_ONTAP "ontap" #define PRIO_RANDOM "random" #define PRIO_RDAC "rdac" --- multipath-tools-0.4.8/libmultipath/prioritizers/Makefile +++ multipath-tools-0.4.8/libmultipath/prioritizers/Makefile @@ -11,7 +11,7 @@ libprioemc.so \ libpriordac.so \ libprioalua.so \ - libprionetapp.so \ + libprioontap.so \ libpriohds.so CFLAGS += -I.. --- multipath-tools-0.4.8/libmultipath/prioritizers/alua.c +++ multipath-tools-0.4.8/libmultipath/prioritizers/alua.c @@ -23,6 +23,7 @@ #define ALUA_PRIO_RTPG_FAILED 2 #define ALUA_PRIO_GETAAS_FAILED 3 #define ALUA_PRIO_TPGS_FAILED 4 +#define ALUA_PRIO_NO_INFORMATION 5 int get_alua_info(int fd) @@ -54,13 +55,18 @@ return -ALUA_PRIO_GETAAS_FAILED; condlog(3, "aas = [%s]", - (aas_string[rc]) ? aas_string[rc] : "invalid/reserved"); + (rc < 4) ? aas_string[rc] : "invalid/reserved"); return rc; } int getprio (struct path * pp) { - int rc = get_alua_info(pp->fd); + int rc; + + if (pp->fd < 0) + return -ALUA_PRIO_NO_INFORMATION; + + rc = get_alua_info(pp->fd); if (rc >= 0) { switch(rc) { case AAS_OPTIMIZED: --- multipath-tools-0.4.8/libmultipath/prioritizers/alua_rtpg.c +++ multipath-tools-0.4.8/libmultipath/prioritizers/alua_rtpg.c @@ -74,7 +74,7 @@ scsi_error(struct sg_io_hdr *hdr) { /* Treat SG_ERR here to get rid of sg_err.[ch] */ - hdr->status &= 0x7e; + hdr->status &= 0x7e; if ( (hdr->status == 0) && @@ -125,18 +125,18 @@ set_uint16(cmd.length, resplen); PRINT_HEX((unsigned char *) &cmd, sizeof(cmd)); - memset(&hdr, 0, sizeof(hdr)); - hdr.interface_id = 'S'; - hdr.cmdp = (unsigned char *) &cmd; - hdr.cmd_len = sizeof(cmd); - hdr.dxfer_direction = SG_DXFER_FROM_DEV; - hdr.dxferp = resp; - hdr.dxfer_len = resplen; - hdr.sbp = sense; - hdr.mx_sb_len = sizeof(sense); - hdr.timeout = DEF_TIMEOUT; - - if (ioctl(fd, SG_IO, &hdr) < 0) { + memset(&hdr, 0, sizeof(hdr)); + hdr.interface_id = 'S'; + hdr.cmdp = (unsigned char *) &cmd; + hdr.cmd_len = sizeof(cmd); + hdr.dxfer_direction = SG_DXFER_FROM_DEV; + hdr.dxferp = resp; + hdr.dxfer_len = resplen; + hdr.sbp = sense; + hdr.mx_sb_len = sizeof(sense); + hdr.timeout = DEF_TIMEOUT; + + if (ioctl(fd, SG_IO, &hdr) < 0) { PRINT_DEBUG("do_inquiry: IOCTL failed!\n"); return -RTPG_INQUIRY_FAILED; } @@ -146,8 +146,8 @@ return -RTPG_INQUIRY_FAILED; } PRINT_HEX((unsigned char *) resp, resplen); - - return 0; + + return 0; } /* @@ -160,6 +160,7 @@ struct inquiry_data inq; int rc; + memset((unsigned char *)&inq, 0, sizeof(inq)); rc = do_inquiry(fd, 0, 0x00, &inq, sizeof(inq)); if (!rc) { rc = inquiry_data_get_tpgs(&inq); @@ -176,6 +177,7 @@ struct vpd83_dscr * dscr; int rc; + memset(buf, 0, sizeof(buf)); rc = do_inquiry(fd, 1, 0x83, buf, sizeof(buf)); if (!rc) { vpd83 = (struct vpd83_data *) buf; @@ -221,19 +223,19 @@ set_uint32(cmd.length, resplen); PRINT_HEX((unsigned char *) &cmd, sizeof(cmd)); - memset(&hdr, 0, sizeof(hdr)); + memset(&hdr, 0, sizeof(hdr)); hdr.interface_id = 'S'; - hdr.cmdp = (unsigned char *) &cmd; - hdr.cmd_len = sizeof(cmd); - hdr.dxfer_direction = SG_DXFER_FROM_DEV; - hdr.dxferp = resp; - hdr.dxfer_len = resplen; - hdr.mx_sb_len = sizeof(sense); - hdr.sbp = sense; - hdr.timeout = DEF_TIMEOUT; - + hdr.cmdp = (unsigned char *) &cmd; + hdr.cmd_len = sizeof(cmd); + hdr.dxfer_direction = SG_DXFER_FROM_DEV; + hdr.dxferp = resp; + hdr.dxfer_len = resplen; + hdr.mx_sb_len = sizeof(sense); + hdr.sbp = sense; + hdr.timeout = DEF_TIMEOUT; + if (ioctl(fd, SG_IO, &hdr) < 0) - return -RTPG_RTPG_FAILED; + return -RTPG_RTPG_FAILED; if (scsi_error(&hdr)) { PRINT_DEBUG("do_rtpg: SCSI error!\n"); @@ -241,8 +243,8 @@ } PRINT_HEX(resp, resplen); - return 0; -} + return 0; +} int get_asymmetric_access_state(int fd, unsigned int tpg) @@ -261,6 +263,7 @@ "%u bytes\n", buflen); return -RTPG_RTPG_FAILED; } + memset(buf, 0, buflen); rc = do_rtpg(fd, buf, buflen); if (rc < 0) return rc; @@ -274,11 +277,11 @@ return -RTPG_RTPG_FAILED; } buflen = scsi_buflen; + memset(buf, 0, buflen); rc = do_rtpg(fd, buf, buflen); if (rc < 0) goto out; } - tpgd = (struct rtpg_data *) buf; rc = -RTPG_TPG_NOT_FOUND; @@ -289,7 +292,7 @@ "more than one entry with same port " "group.\n"); } else { - PRINT_DEBUG("pref=%i\n", dscr->pref); + PRINT_DEBUG("pref=%i\n", dscr->b0); rc = rtpg_tpg_dscr_get_aas(dscr); } } --- multipath-tools-0.4.8/libmultipath/prioritizers/hds.c +++ multipath-tools-0.4.8/libmultipath/prioritizers/hds.c @@ -86,7 +86,7 @@ int hds_modular_prio (const char *dev, int fd) { int k; - char vendor[8]; + char vendor[9]; char product[32]; char serial[32]; char ldev[32]; --- multipath-tools-0.4.8/libmultipath/prioritizers/netapp.c +++ multipath-tools-0.4.8/libmultipath/prioritizers/netapp.c @@ -1,243 +0,0 @@ -/* - * Copyright 2005 Network Appliance, Inc., All Rights Reserved - * Author: David Wysochanski available at davidw@netapp.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License v2 for more details. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define INQUIRY_CMD 0x12 -#define INQUIRY_CMDLEN 6 -#define DEFAULT_PRIOVAL 10 -#define RESULTS_MAX 256 -#define SG_TIMEOUT 30000 - -#define pp_netapp_log(prio, fmt, args...) \ - condlog(prio, "%s: netapp prio: " fmt, dev, ##args) - -static void dump_cdb(unsigned char *cdb, int size) -{ - int i; - char buf[10*5+1]; - char * p = &buf[0]; - - condlog(0, "- SCSI CDB: "); - for (i=0; imasked_status, - io_hdr->host_status, io_hdr->driver_status); - if (io_hdr->sb_len_wr > 0) { - condlog(0, "- SCSI sense data: "); - for (i=0; isb_len_wr; i++) { - p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ", - io_hdr->sbp[i]); - } - condlog(0, "%s", buf); - } -} - -/* - * Returns: - * -1: error, errno set - * 0: success - */ -static int send_gva(const char *dev, int fd, unsigned char pg, - unsigned char *results, int *results_size) -{ - unsigned char sb[128]; - unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa, - pg, sizeof(sb), 0, 0}; - struct sg_io_hdr io_hdr; - int ret = -1; - - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (cdb); - io_hdr.mx_sb_len = sizeof (sb); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = *results_size; - io_hdr.dxferp = results; - io_hdr.cmdp = cdb; - io_hdr.sbp = sb; - io_hdr.timeout = SG_TIMEOUT; - io_hdr.pack_id = 0; - if (ioctl(fd, SG_IO, &io_hdr) < 0) { - pp_netapp_log(0, "SG_IO ioctl failed, errno=%d", errno); - dump_cdb(cdb, sizeof(cdb)); - goto out; - } - if (io_hdr.info & SG_INFO_OK_MASK) { - pp_netapp_log(0, "SCSI error"); - dump_cdb(cdb, sizeof(cdb)); - process_sg_error(&io_hdr); - goto out; - } - - if (results[4] != 0x0a || results[5] != 0x98 || - results[6] != 0x0a ||results[7] != 0x01) { - dump_cdb(cdb, sizeof(cdb)); - pp_netapp_log(0, "GVA return wrong format "); - pp_netapp_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x", - results[4], results[5], results[6], results[7]); - goto out; - } - ret = 0; - out: - return(ret); -} - -/* - * Retuns: - * -1: Unable to obtain proxy info - * 0: Device _not_ proxy path - * 1: Device _is_ proxy path - */ -static int get_proxy(const char *dev, int fd) -{ - unsigned char results[256]; - unsigned char sb[128]; - unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0, - sizeof(sb), 0}; - struct sg_io_hdr io_hdr; - int ret = -1; - - memset(&results, 0, sizeof (results)); - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (cdb); - io_hdr.mx_sb_len = sizeof (sb); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = sizeof (results); - io_hdr.dxferp = results; - io_hdr.cmdp = cdb; - io_hdr.sbp = sb; - io_hdr.timeout = SG_TIMEOUT; - io_hdr.pack_id = 0; - if (ioctl(fd, SG_IO, &io_hdr) < 0) { - pp_netapp_log(0, "ioctl sending inquiry command failed, " - "errno=%d", errno); - dump_cdb(cdb, sizeof(cdb)); - goto out; - } - if (io_hdr.info & SG_INFO_OK_MASK) { - pp_netapp_log(0, "SCSI error"); - dump_cdb(cdb, sizeof(cdb)); - process_sg_error(&io_hdr); - goto out; - } - - if (results[1] != 0xc1 || results[8] != 0x0a || - results[9] != 0x98 || results[10] != 0x0a || - results[11] != 0x0 || results[12] != 0xc1 || - results[13] != 0x0) { - pp_netapp_log(0,"proxy info page in unknown format - "); - pp_netapp_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x " - "0x%02x 0x%02x", - results[8], results[9], results[10], - results[11], results[12], results[13]); - dump_cdb(cdb, sizeof(cdb)); - goto out; - } - ret = (results[19] & 0x02) >> 1; - - out: - return(ret); -} - -/* - * Returns priority of device based on device info. - * - * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol - * 3: iSCSI HBA - * 2: iSCSI software - * 1: FCP proxy - */ -static int netapp_prio(const char *dev, int fd) -{ - unsigned char results[RESULTS_MAX]; - int results_size=RESULTS_MAX; - int rc; - int is_proxy; - int is_iscsi_software; - int is_iscsi_hardware; - int tot_len; - - is_iscsi_software = is_iscsi_hardware = is_proxy = 0; - - memset(&results, 0, sizeof (results)); - rc = send_gva(dev, fd, 0x41, results, &results_size); - if (rc == 0) { - tot_len = results[0] << 24 | results[1] << 16 | - results[2] << 8 | results[3]; - if (tot_len <= 8) { - goto try_fcp_proxy; - } - if (results[8] != 0x41) { - pp_netapp_log(0, "GVA page 0x41 error - " - "results[8] = 0x%x", results[8]); - goto try_fcp_proxy; - } - if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) || - (strncmp((char *)&results[12], "iswt", 4) == 0)) { - is_iscsi_software = 1; - goto prio_select; - } - else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) { - is_iscsi_hardware = 1; - goto prio_select; - } - } - - try_fcp_proxy: - rc = get_proxy(dev, fd); - if (rc >= 0) { - is_proxy = rc; - } - - prio_select: - if (is_iscsi_hardware) { - return 3; - } else if (is_iscsi_software) { - return 2; - } else { - if (is_proxy) { - return 1; - } else { - /* Either non-proxy, or couldn't get proxy info */ - return 4; - } - } -} - -int getprio (struct path * pp) -{ - return netapp_prio(pp->dev, pp->fd); -} --- multipath-tools-0.4.8/libmultipath/prioritizers/netapp.h +++ multipath-tools-0.4.8/libmultipath/prioritizers/netapp.h @@ -1,7 +0,0 @@ -#ifndef _NETAPP_H -#define _NETAPP_H - -#define PRIO_NETAPP "netapp" -int prio_netapp(struct path * pp); - -#endif --- multipath-tools-0.4.8/libmultipath/prioritizers/ontap.c +++ multipath-tools-0.4.8/libmultipath/prioritizers/ontap.c @@ -0,0 +1,243 @@ +/* + * Copyright 2005 Network Appliance, Inc., All Rights Reserved + * Author: David Wysochanski available at davidw@netapp.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License v2 for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define INQUIRY_CMD 0x12 +#define INQUIRY_CMDLEN 6 +#define DEFAULT_PRIOVAL 10 +#define RESULTS_MAX 256 +#define SG_TIMEOUT 30000 + +#define pp_ontap_log(prio, fmt, args...) \ + condlog(prio, "%s: ontap prio: " fmt, dev, ##args) + +static void dump_cdb(unsigned char *cdb, int size) +{ + int i; + char buf[10*5+1]; + char * p = &buf[0]; + + condlog(0, "- SCSI CDB: "); + for (i=0; imasked_status, + io_hdr->host_status, io_hdr->driver_status); + if (io_hdr->sb_len_wr > 0) { + condlog(0, "- SCSI sense data: "); + for (i=0; isb_len_wr; i++) { + p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ", + io_hdr->sbp[i]); + } + condlog(0, "%s", buf); + } +} + +/* + * Returns: + * -1: error, errno set + * 0: success + */ +static int send_gva(const char *dev, int fd, unsigned char pg, + unsigned char *results, int *results_size) +{ + unsigned char sb[128]; + unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa, + pg, sizeof(sb), 0, 0}; + struct sg_io_hdr io_hdr; + int ret = -1; + + memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = sizeof (cdb); + io_hdr.mx_sb_len = sizeof (sb); + io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; + io_hdr.dxfer_len = *results_size; + io_hdr.dxferp = results; + io_hdr.cmdp = cdb; + io_hdr.sbp = sb; + io_hdr.timeout = SG_TIMEOUT; + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_ontap_log(0, "SG_IO ioctl failed, errno=%d", errno); + dump_cdb(cdb, sizeof(cdb)); + goto out; + } + if (io_hdr.info & SG_INFO_OK_MASK) { + pp_ontap_log(0, "SCSI error"); + dump_cdb(cdb, sizeof(cdb)); + process_sg_error(&io_hdr); + goto out; + } + + if (results[4] != 0x0a || results[5] != 0x98 || + results[6] != 0x0a ||results[7] != 0x01) { + dump_cdb(cdb, sizeof(cdb)); + pp_ontap_log(0, "GVA return wrong format "); + pp_ontap_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x", + results[4], results[5], results[6], results[7]); + goto out; + } + ret = 0; + out: + return(ret); +} + +/* + * Retuns: + * -1: Unable to obtain proxy info + * 0: Device _not_ proxy path + * 1: Device _is_ proxy path + */ +static int get_proxy(const char *dev, int fd) +{ + unsigned char results[256]; + unsigned char sb[128]; + unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0, + sizeof(sb), 0}; + struct sg_io_hdr io_hdr; + int ret = -1; + + memset(&results, 0, sizeof (results)); + memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = sizeof (cdb); + io_hdr.mx_sb_len = sizeof (sb); + io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; + io_hdr.dxfer_len = sizeof (results); + io_hdr.dxferp = results; + io_hdr.cmdp = cdb; + io_hdr.sbp = sb; + io_hdr.timeout = SG_TIMEOUT; + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_ontap_log(0, "ioctl sending inquiry command failed, " + "errno=%d", errno); + dump_cdb(cdb, sizeof(cdb)); + goto out; + } + if (io_hdr.info & SG_INFO_OK_MASK) { + pp_ontap_log(0, "SCSI error"); + dump_cdb(cdb, sizeof(cdb)); + process_sg_error(&io_hdr); + goto out; + } + + if (results[1] != 0xc1 || results[8] != 0x0a || + results[9] != 0x98 || results[10] != 0x0a || + results[11] != 0x0 || results[12] != 0xc1 || + results[13] != 0x0) { + pp_ontap_log(0,"proxy info page in unknown format - "); + pp_ontap_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x " + "0x%02x 0x%02x", + results[8], results[9], results[10], + results[11], results[12], results[13]); + dump_cdb(cdb, sizeof(cdb)); + goto out; + } + ret = (results[19] & 0x02) >> 1; + + out: + return(ret); +} + +/* + * Returns priority of device based on device info. + * + * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol + * 3: iSCSI HBA + * 2: iSCSI software + * 1: FCP proxy + */ +static int ontap_prio(const char *dev, int fd) +{ + unsigned char results[RESULTS_MAX]; + int results_size=RESULTS_MAX; + int rc; + int is_proxy; + int is_iscsi_software; + int is_iscsi_hardware; + int tot_len; + + is_iscsi_software = is_iscsi_hardware = is_proxy = 0; + + memset(&results, 0, sizeof (results)); + rc = send_gva(dev, fd, 0x41, results, &results_size); + if (rc == 0) { + tot_len = results[0] << 24 | results[1] << 16 | + results[2] << 8 | results[3]; + if (tot_len <= 8) { + goto try_fcp_proxy; + } + if (results[8] != 0x41) { + pp_ontap_log(0, "GVA page 0x41 error - " + "results[8] = 0x%x", results[8]); + goto try_fcp_proxy; + } + if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) || + (strncmp((char *)&results[12], "iswt", 4) == 0)) { + is_iscsi_software = 1; + goto prio_select; + } + else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) { + is_iscsi_hardware = 1; + goto prio_select; + } + } + + try_fcp_proxy: + rc = get_proxy(dev, fd); + if (rc >= 0) { + is_proxy = rc; + } + + prio_select: + if (is_iscsi_hardware) { + return 3; + } else if (is_iscsi_software) { + return 2; + } else { + if (is_proxy) { + return 1; + } else { + /* Either non-proxy, or couldn't get proxy info */ + return 4; + } + } +} + +int getprio (struct path * pp) +{ + return ontap_prio(pp->dev, pp->fd); +} --- multipath-tools-0.4.8/libmultipath/prioritizers/ontap.h +++ multipath-tools-0.4.8/libmultipath/prioritizers/ontap.h @@ -0,0 +1,7 @@ +#ifndef _ONTAP_H +#define _ONTAP_H + +#define PRIO_ONTAP "ontap" +int prio_ontap(struct path * pp); + +#endif --- multipath-tools-0.4.8/libmultipath/prioritizers/rdac.c +++ multipath-tools-0.4.8/libmultipath/prioritizers/rdac.c @@ -39,9 +39,9 @@ pp_rdac_log(0, "inquiry command indicates error"); goto out; } - + if (/* Verify the code page - right page & page identifier */ - sense_buffer[1] != 0xc9 || + sense_buffer[1] != 0xc9 || sense_buffer[3] != 0x2c || sense_buffer[4] != 'v' || sense_buffer[5] != 'a' || @@ -49,24 +49,24 @@ pp_rdac_log(0, "volume access control page in unknown format"); goto out; } - + if ( /* Current Volume Path Bit */ ( sense_buffer[8] & 0x01) == 0x01 ) { - /* + /* * This volume was owned by the controller receiving * the inquiry command. */ - ret |= 0x01; + ret |= 0x02; } /* Volume Preferred Path Priority */ switch ( sense_buffer[9] & 0x0F ) { case 0x01: - /* + /* * Access to this volume is most preferred through * this path and other paths with this value. */ - ret |= 0x02; + ret |= 0x04; break; case 0x02: /* @@ -74,12 +74,13 @@ * as a secondary path. Typically this path would be used * for fail-over situations. */ - /* Fallthrough */ + ret |= 0x01; + break; default: /* Reserved values */ break; } - + out: return(ret); } --- multipath-tools-0.4.8/libmultipath/regex.c +++ multipath-tools-0.4.8/libmultipath/regex.c @@ -116,7 +116,7 @@ /* True if `size1' is non-NULL and PTR is pointing anywhere inside `string1' or just past its end. This works if PTR is NULL, which is a good thing. */ -#define FIRST_STRING_P(ptr) \ +#define FIRST_STRING_P(ptr) \ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) /* (Re)Allocate N items of type T using malloc, or fail. */ @@ -188,7 +188,7 @@ #define EXTRACT_NUMBER_AND_INCR(destination, source) \ do { \ EXTRACT_NUMBER (destination, source); \ - (source) += 2; \ + (source) += 2; \ } while (0) #undef assert @@ -267,14 +267,14 @@ #define PATFETCH(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ - if (translate) c = translate[c]; \ + if (translate) c = translate[c]; \ } while (0) /* Fetch the next character in the uncompiled pattern, with no translation. */ #define PATFETCH_RAW(c) \ do {if (p == pend) return REG_EEND; \ - c = (unsigned char) *p++; \ + c = (unsigned char) *p++; \ } while (0) /* Go backwards one character in the pattern. */ @@ -354,27 +354,27 @@ correct places in the new one. If extending the buffer results in it being larger than MAX_BUF_SIZE, then flag memory exhausted. */ #define EXTEND_BUFFER() \ - do { \ + do { \ unsigned char *old_buffer = bufp->buffer; \ - if (bufp->allocated == MAX_BUF_SIZE) \ + if (bufp->allocated == MAX_BUF_SIZE) \ return REG_ESIZE; \ bufp->allocated <<= 1; \ if (bufp->allocated > MAX_BUF_SIZE) \ - bufp->allocated = MAX_BUF_SIZE; \ + bufp->allocated = MAX_BUF_SIZE; \ bufp->buffer = (unsigned char *) REALLOC(bufp->buffer, bufp->allocated);\ if (bufp->buffer == NULL) \ return REG_ESPACE; \ /* If the buffer moved, move all the pointers into it. */ \ if (old_buffer != bufp->buffer) \ { \ - b = (b - old_buffer) + bufp->buffer; \ - begalt = (begalt - old_buffer) + bufp->buffer; \ - if (fixup_alt_jump) \ - fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ - if (laststart) \ - laststart = (laststart - old_buffer) + bufp->buffer; \ - if (pending_exact) \ - pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_alt_jump) \ + fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ } \ } while (0) @@ -428,20 +428,20 @@ /* Get the next unsigned number in the uncompiled pattern. */ -#define GET_UNSIGNED_NUMBER(num) \ +#define GET_UNSIGNED_NUMBER(num) \ { if (p != pend) \ { \ - PATFETCH (c); \ - while (ISDIGIT (c)) \ - { \ - if (num < 0) \ - num = 0; \ - num = num * 10 + c - '0'; \ - if (p == pend) \ - break; \ - PATFETCH (c); \ - } \ - } \ + PATFETCH (c); \ + while (ISDIGIT (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ } #define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ @@ -1524,14 +1524,14 @@ ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ ? 0 \ : ((fail_stack).stack = (fail_stack_elt_t *) \ - REGEX_REALLOCATE ((fail_stack).stack, \ - (fail_stack).size * sizeof (fail_stack_elt_t), \ - ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + REGEX_REALLOCATE ((fail_stack).stack, \ + (fail_stack).size * sizeof (fail_stack_elt_t), \ + ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ \ (fail_stack).stack == NULL \ ? 0 \ - : ((fail_stack).size <<= 1, \ - 1))) + : ((fail_stack).size <<= 1, \ + 1))) /* Push PATTERN_OP on FAIL_STACK. @@ -1577,7 +1577,7 @@ is wide enough to hold a value of something to which pointer can \ be assigned */ \ s_reg_t this_reg; \ - \ + \ DEBUG_STATEMENT (failure_id++); \ DEBUG_STATEMENT (nfailure_points_pushed++); \ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ @@ -1663,7 +1663,7 @@ /* We actually push this many items. */ #define NUM_FAILURE_ITEMS \ - ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + NUM_NONREG_ITEMS) /* How many items can still be added to the stack without overflowing it. */ @@ -2255,13 +2255,13 @@ /* Call before fetching a character with *d. This switches over to string2 if necessary. */ #define PREFETCH() \ - while (d == dend) \ + while (d == dend) \ { \ /* End of string2 => fail. */ \ - if (dend == end_match_2) \ - goto fail; \ - /* End of string1 => advance to string2. */ \ - d = string2; \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ dend = end_match_2; \ } @@ -2278,7 +2278,7 @@ string2, look at the last character in string1. */ #define WORDCHAR_P(d) \ (SYNTAX ((d) == end1 ? *string2 \ - : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ == Sword) /* Test if the character before D and the one at D differ with respect --- multipath-tools-0.4.8/libmultipath/structs.c +++ multipath-tools-0.4.8/libmultipath/structs.c @@ -22,7 +22,7 @@ alloc_path (void) { struct path * pp; - + pp = (struct path *)MALLOC(sizeof(struct path)); if (pp) { @@ -243,7 +243,7 @@ { int i; struct multipath * mpp; - + if (!mpvec) return NULL; @@ -262,7 +262,7 @@ { int i; struct multipath * mpp; - + if (!mpvec) return NULL; @@ -279,7 +279,7 @@ int i; int len; struct multipath * mpp; - + if (!mpvec) return NULL; @@ -287,7 +287,7 @@ if (!len) return NULL; - + vector_foreach_slot (mpvec, mpp, i) { if (strlen(mpp->alias) == len && !strncmp(mpp->alias, alias, len)) @@ -315,7 +315,7 @@ if (!pathvec) return NULL; - + vector_foreach_slot (pathvec, pp, i) if (!strcmp_chomp(pp->dev, dev)) return pp; --- multipath-tools-0.4.8/libmultipath/structs_vec.c +++ multipath-tools-0.4.8/libmultipath/structs_vec.c @@ -280,13 +280,13 @@ retry: if (dm_get_info(mpp->alias, &mpp->dmi)) { /* Error accessing table */ - condlog(3, "%s: cannot access table", mpp->alias); + condlog(3, "%s: cannot access table", mpp->alias); goto out; } if (!dm_map_present(mpp->alias)) { /* Table has been removed */ - condlog(3, "%s: table does not exist", mpp->alias); + condlog(3, "%s: table does not exist", mpp->alias); goto out; } --- multipath-tools-0.4.8/libmultipath/switchgroup.c +++ multipath-tools-0.4.8/libmultipath/switchgroup.c @@ -35,7 +35,7 @@ if (!mpp->pg) return 1; - + vector_foreach_slot (mpp->pg, pgp, i) { if (!pgp->paths) continue; --- multipath-tools-0.4.8/libmultipath/uevent.c +++ multipath-tools-0.4.8/libmultipath/uevent.c @@ -157,7 +157,7 @@ } /* enable receiving of the sender credentials */ - setsockopt(sock, SOL_SOCKET, SO_PASSCRED, + setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on)); } else { --- multipath-tools-0.4.8/libmultipath/util.c +++ multipath-tools-0.4.8/libmultipath/util.c @@ -14,7 +14,7 @@ { int i; char s1[PARAMS_SIZE],s2[PARAMS_SIZE]; - + if(!str1 || !str2) return 1; @@ -67,7 +67,7 @@ char * p; int len; int skip = 0; - + if (word) *word = NULL; --- multipath-tools-0.4.8/libmultipath/uxsock.c +++ multipath-tools-0.4.8/libmultipath/uxsock.c @@ -26,17 +26,17 @@ int ux_socket_connect(const char *name) { int fd; - struct sockaddr_un addr; + struct sockaddr_un addr; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, name, sizeof(addr.sun_path)); + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, name, sizeof(addr.sun_path)); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) { return -1; } - + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { close(fd); return -1; @@ -47,12 +47,13 @@ /* * create a unix domain socket and start listening on it - * return a file descriptor open on the socket + * return a file descriptor open on the socket */ int ux_socket_listen(const char *name) { int fd; - struct sockaddr_un addr; + struct sockaddr_un addr; + /* get rid of any old socket */ unlink(name); @@ -60,16 +61,16 @@ fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) return -1; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, name, sizeof(addr.sun_path)); + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, name, sizeof(addr.sun_path)); - if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { close(fd); return -1; - } + } - if (listen(fd, 10) == -1) { + if (listen(fd, 10) == -1) { close(fd); return -1; } --- multipath-tools-0.4.8/libmultipath/vector.c +++ multipath-tools-0.4.8/libmultipath/vector.c @@ -1,10 +1,10 @@ -/* +/* * Part: Vector structure manipulation. - * + * * Version: $Id: vector.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $ - * + * * Author: Alexandre Cassen, - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -23,7 +23,7 @@ #include #include "vector.h" -/* +/* * Initialize vector struct. * allocated 'size' slot elements then return vector. */ @@ -54,7 +54,7 @@ vector_insert_slot(vector v, int slot, void *value) { int i; - + if (!vector_alloc_slot(v)) return NULL; --- multipath-tools-0.4.8/libmultipath/waiter.c +++ multipath-tools-0.4.8/libmultipath/waiter.c @@ -58,7 +58,7 @@ void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs) { struct event_thread *wp = (struct event_thread *)mpp->waiter; - + if (!wp) { condlog(3, "%s: no waiter thread", mpp->alias); return; @@ -113,7 +113,7 @@ } dm_task_no_open_count(waiter->dmt); - + /* accept wait interruption */ set = unblock_signals(); @@ -154,7 +154,7 @@ lock_cleanup_pop(waiter->vecs->lock); if (r) { - condlog(2, "%s: event checker exit", + condlog(2, "%s: event checker exit", waiter->mapname); return -1; /* stop the thread */ } --- multipath-tools-0.4.8/multipath.conf.annotated +++ multipath-tools-0.4.8/multipath.conf.annotated @@ -134,6 +134,15 @@ # # default : no # user_friendly_names no # +# # +# # name : bindings_file +# # scope : multipath +# # desc : The location of the bindings file that is used with +# # the user_friendly_names option. +# # values : +# # default : "/var/lib/multipath/bindings" +# bindings_file "/etc/multipath_bindings" +# #} # ## --- multipath-tools-0.4.8/multipath/Makefile +++ multipath-tools-0.4.8/multipath/Makefile @@ -16,24 +16,27 @@ $(EXEC): $(OBJS) $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) - $(GZIP) $(EXEC).8 > $(EXEC).8.gz - $(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz install: $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir) + $(INSTALL_PROGRAM) -m 755 multipath.init.suse $(DESTDIR)$(rcdir)/boot.multipath $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d - $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/ + $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/71-multipath.rules $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) - $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir) $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) - $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(man5dir) + $(INSTALL_PROGRAM) -d $(DESTDIR)/lib/mkinitrd/scripts + $(INSTALL_PROGRAM) -m 755 boot-multipath.sh $(DESTDIR)/lib/mkinitrd/scripts + $(INSTALL_PROGRAM) -m 755 setup-multipath.sh $(DESTDIR)/lib/mkinitrd/scripts uninstall: rm $(DESTDIR)/etc/udev/rules.d/multipath.rules rm $(DESTDIR)$(bindir)/$(EXEC) - rm $(DESTDIR)$(mandir)/$(EXEC).8.gz - rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz + rm -f $(DESTDIR)/lib/mkinitrd/scripts/boot-multipath.sh + rm -f $(DESTDIR)/lib/mkinitrd/scripts/setup-multipath.sh clean: - rm -f core *.o $(EXEC) *.gz + rm -f core *.o $(EXEC) --- multipath-tools-0.4.8/multipath/boot-multipath.sh +++ multipath-tools-0.4.8/multipath/boot-multipath.sh @@ -0,0 +1,39 @@ +#!/bin/bash +#%stage: block +#%depends: dm +#%provides: dmroot +#%programs: /sbin/multipath /lib/multipath/* +#%if: "$root_mpath" +#%modules: dm-multipath dm-round-robin dm-emc dm-hp_sw dm-rdac +# +##### Multipath +## +## If the root device can be accessed using multiple device paths, +## this initializes and waits for them +## +## Command line parameters +## ----------------------- +## +## root_mpath=1 use multipath +## mpath_status=off do not use multipath +## + +load_modules + +# check for multipath parameter in /proc/cmdline +mpath_status=$(get_param multipath) + +mpath_list=$(sed -n '/multipath/p' /proc/modules) +if [ -z "$mpath_list" ] ; then + mpath_status=off +fi +if [ "$mpath_status" != "off" ] ; then + # We are waiting for a device-mapper device + root_major=$(sed -n 's/\(.*\) device-mapper/\1/p' /proc/devices) + # Rescan for multipath + echo -n "Setup multipath devices: " + /sbin/multipath -v0 + wait_for_events + echo 'ok.' +fi + --- multipath-tools-0.4.8/multipath/main.c +++ multipath-tools-0.4.8/multipath/main.c @@ -79,6 +79,7 @@ fprintf (stderr, " %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname); fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); fprintf (stderr, " %s -F [-v lvl]\n", progname); + fprintf (stderr, " %s -t\n", progname); fprintf (stderr, " %s -h\n", progname); fprintf (stderr, "\n" @@ -89,6 +90,7 @@ " -f flush a multipath device map\n" \ " -F flush all multipath device maps\n" \ " -d dry run, do not create or update devmaps\n" \ + " -t dump internal hardware table\n" \ " -r force devmap reload\n" \ " -p policy failover|multibus|group_by_serial|group_by_prio\n" \ " -b fil bindings file location\n" \ @@ -241,14 +243,14 @@ else dev = conf->dev; } - + /* * if we have a blacklisted device parameter, exit early */ - if (dev && + if (dev && (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0)) goto out; - + /* * scope limiting must be translated into a wwid * failing the translation is fatal (by policy) @@ -315,6 +317,55 @@ return r; } +static int +dump_config (void) +{ + char * c; + char * reply; + unsigned int maxlen = 256; + int again = 1; + + reply = MALLOC(maxlen); + + while (again) { + if (!reply) + return 1; + c = reply; + c += snprint_defaults(c, reply + maxlen - c); + again = ((c - reply) == maxlen); + if (again) { + reply = REALLOC(reply, maxlen *= 2); + continue; + } + c += snprint_blacklist(c, reply + maxlen - c); + again = ((c - reply) == maxlen); + if (again) { + reply = REALLOC(reply, maxlen *= 2); + continue; + } + c += snprint_blacklist_except(c, reply + maxlen - c); + again = ((c - reply) == maxlen); + if (again) { + reply = REALLOC(reply, maxlen *= 2); + continue; + } + c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable); + again = ((c - reply) == maxlen); + if (again) { + reply = REALLOC(reply, maxlen *= 2); + continue; + } + c += snprint_mptable(c, reply + maxlen - c, conf->mptable); + again = ((c - reply) == maxlen); + if (again) + reply = REALLOC(reply, maxlen *= 2); + } + + printf("%s", reply); + FREE(reply); + return 0; +} + int main (int argc, char *argv[]) { @@ -346,7 +397,7 @@ condlog(0, "multipath tools need sysfs mounted"); exit(1); } - while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:r")) != EOF ) { + while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:rt")) != EOF ) { switch(arg) { case 1: printf("optarg : %s\n",optarg); break; @@ -387,16 +438,19 @@ if (conf->pgpolicy_flag == -1) { printf("'%s' is not a valid policy\n", optarg); usage(argv[0]); - } + } break; case 'r': conf->force_reload = 1; break; + case 't': + dump_config(); + goto out; case 'h': usage(argv[0]); case ':': fprintf(stderr, "Missing option arguement\n"); - usage(argv[0]); + usage(argv[0]); case '?': fprintf(stderr, "Unknown switch: %s\n", optarg); usage(argv[0]); --- multipath-tools-0.4.8/multipath/multipath.8 +++ multipath-tools-0.4.8/multipath/multipath.8 @@ -6,7 +6,7 @@ .RB [\| \-v\ \c .IR verbosity \|] .RB [\| \-d \|] -.RB [\| \-h | \-l | \-ll | \-f | \-F \|] +.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F \|] .RB [\| \-p\ \c .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] .RB [\| device \|] @@ -47,6 +47,9 @@ .B \-F flush all unused multipath device maps .TP +.B \-t +print internal hardware table to stdout +.TP .BI \-p " policy" force maps to specified policy: .RS 1.2i @@ -76,6 +79,9 @@ .I device may alternatively be a multipath mapname .SH "SEE ALSO" +.BR multipathd (8), +.BR multipath.conf (5), +.BR kpartx (8), .BR udev (8), .BR dmsetup (8) .BR hotplug (8) --- multipath-tools-0.4.8/multipath/multipath.conf.5 +++ multipath-tools-0.4.8/multipath/multipath.conf.5 @@ -147,13 +147,24 @@ .RE .TP .B features -Specify any device-mapper features to be used. The most common of -these features is -.I "1 queue_if_no_path" -Note that this can also be set via the +Specify any device-mapper features to be used. Syntax is +.I num list +where +.I num +is the number of features in +.I list. +Possible values for the feature list are +.RS +.TP 12 +.B queue_if_no_path +Queue IO if no path is active; identical to the .I no_path_retry keyword. .TP +.B no_partitions +Disable automatic partitions generation via kpartx. +.RE +.TP .B path_checker The default method used to determine the paths' state. Possible values are @@ -225,6 +236,10 @@ be overriden by any specific aliases in the \fImultipaths\fR section. Default is .I no +.TP +.B bindings_file +The full pathname of the binding file to be used when the user_friendly_names option is set. Defaults to +.I /var/lib/multipath/bindings . .SH "blacklist section" The --- multipath-tools-0.4.8/multipath/multipath.init.suse +++ multipath-tools-0.4.8/multipath/multipath.init.suse @@ -0,0 +1,137 @@ +#! /bin/sh +# Copyright (c) 2005 SuSE GmbH Nuernberg, Germany. +# +# Author: Hannes Reinecke +# +# init.d/boot.multipath +# +### BEGIN INIT INFO +# Provides: boot.multipath +# Required-Start: boot.device-mapper boot.udev +# Required-Stop: boot.device-mapper boot.udev +# Default-Start: B +# Default-Stop: +# Short-Description: Create multipath device targets +# Description: Setup initial multipath device-mapper targets +### END INIT INFO + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +PROGRAM=/sbin/multipath + +# Set the maximum number of open files +MAX_OPEN_FDS=4096 + +test -x $PROGRAM || exit 5 + +# Shell functions sourced from /etc/rc.status: +# rc_check check and set local and overall rc status +# rc_status check and set local and overall rc status +# rc_status -v ditto but be verbose in local rc status +# rc_status -v -r ditto and clear the local rc status +# rc_failed set local and overall rc status to failed +# rc_reset clear local rc status (overall remains) +# rc_exit exit appropriate to overall rc status +. /etc/rc.status + +# First reset status of this service +rc_reset + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - misc error +# 2 - invalid or excess args +# 3 - unimplemented feature (e.g. reload) +# 4 - insufficient privilege +# 5 - program not installed +# 6 - program not configured +# 7 - program is not running +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signalling is not supported) are +# considered a success. + +case "$1" in + start) + echo -n "Creating multipath targets:" + # Check whether multipath daemon is already running + if /sbin/multipathd -k"list paths" > /dev/null 2>&1 ; then + echo -n " (multipathd running)" + rc_status -v + rc_exit + fi + + # Load prerequisite module + modprobe dm-multipath + + # Be a chicken and flush all existing maps + $PROGRAM -F + + # Clear /dev/disk/by-name/ prior to start-up; multipath will + # recreate them. + rm -f /dev/disk/by-name/* 2>&1 >/dev/null + + # Set the maximum number of open files + if [ -n "$MAX_OPEN_FDS" ] ; then + ulimit -n $MAX_OPEN_FDS + fi + + # Start the program directly as checkproc doesn't work here + $PROGRAM -v 0 + + # Create all partitions which might have been missing + for map in $(/sbin/dmsetup ls --target multipath | sed '/No devices/d' | sort -n +2 | sed -n 's/.*, \(.*\))/\1/p' ) ; do + wait=5 + while [ $wait -gt 0 ] ; do + [ -e /dev/dm-$map ] && break + wait=$((wait - 1)) + sleep 1; + done + if [ $wait -le 0 ] ; then + echo -n "timeout waiting for devices" + rc_failed 1 + break; + fi + /sbin/kpartx -a -p _part /dev/dm-$map + done + + # Remember status and be verbose + rc_status -v + sleep 1 + ;; + stop) + echo -n "Removing multipath targets:" + + # Remove all partition mappings + if /sbin/dmsetup ls | sed '/No devices/d' | grep -q -- -part; then + /sbin/dmsetup ls --target multipath --exec "/sbin/kpartx -d -p _part" 2> /dev/null + fi + + # Flush all existing maps + $PROGRAM -F + + rc_failed 0 + rc_status -v + ;; + status) + echo -n "Checking multipath targets: " + # Display active multipath tables + tblnum=$(/sbin/dmsetup ls --target multipath | sed '/No devices/d' | wc --lines) + if [ "$tblnum" ] && [ $tblnum -gt 0 ] ; then + echo -n "($tblnum multipath devices) " + rc_failed 0 + else + rc_failed 3 + fi + rc_status -v + ;; + reload) + $0 stop + $0 start + ;; + *) + echo "Usage: $0 {start|stop|status}" + exit 1 + ;; +esac +rc_exit --- multipath-tools-0.4.8/multipath/setup-multipath.sh +++ multipath-tools-0.4.8/multipath/setup-multipath.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +#%stage: devicemapper +#%provides: dmroot +# +# force multipath and dm usage if multipath was forced +if use_script multipath; then + root_mpath=1 + root_dm=1 +fi + +if [ -x /sbin/multipath -a -x /sbin/dmsetup ] ; then + for bd in $blockdev ; do + update_blockdev $bd + if [ $blockdriver = device-mapper ]; then + dm_uuid=$(dmsetup info -c --noheadings -o uuid -j $blockmajor -m $blockminor) + dm_creator=${dm_uuid%-*} + if [ "$dm_creator" = "mpath" ]; then + tmp_root_dm=1 # multipath needs dm + root_mpath=1 + fi + fi + done +fi + +if use_script multipath; then + if [ -f /etc/multipath.conf ] ; then + cp -a /etc/multipath.conf $tmp_mnt/etc + fi + if [ -f /var/lib/multipath/bindings ] ; then + mkdir -p /var/lib/multipath + cp -a /var/lib/multipath/bindings $tmp_mnt/var/lib/multipath + fi + if [ -e /etc/udev/rules.d/71-multipath.rules ]; then + cp /etc/udev/rules.d/71-multipath.rules $tmp_mnt/etc/udev/rules.d + fi + if [ -e /etc/udev/rules.d/72-multipath-compat.rules ]; then + cp /etc/udev/rules.d/72-multipath-compat.rules $tmp_mnt/etc/udev/rules.d + fi + if [ -d /lib/multipath ]; then + mkdir $tmp_mnt/lib/multipath + fi +fi + +save_var root_mpath --- multipath-tools-0.4.8/multipathd/Makefile +++ multipath-tools-0.4.8/multipathd/Makefile @@ -29,20 +29,19 @@ $(EXEC): $(OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o $(EXEC) $(OBJS) - $(GZIP) $(EXEC).8 > $(EXEC).8.gz install: $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir) + $(INSTALL_PROGRAM) -m 755 multipathd.init.suse $(DESTDIR)$(rcdir)/multipathd $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) - $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir) uninstall: rm -f $(DESTDIR)$(bindir)/$(EXEC) rm -f $(DESTDIR)$(rcdir)/$(EXEC) - rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz clean: - rm -f core *.o $(EXEC) *.gz + rm -f core *.o $(EXEC) --- multipath-tools-0.4.8/multipathd/main.c +++ multipath-tools-0.4.8/multipathd/main.c @@ -944,19 +944,25 @@ enable_group(pp); } else if (newstate == PATH_UP || newstate == PATH_GHOST) { - LOG_MSG(4, checker_message(&pp->checker)); - /* - * double the next check delay. - * max at conf->max_checkint - */ - if (pp->checkint < (conf->max_checkint / 2)) - pp->checkint = 2 * pp->checkint; - else - pp->checkint = conf->max_checkint; + if (pp->dmstate == PSTATE_FAILED || + pp->dmstate == PSTATE_UNDEF) { + /* Clear IO errors */ + reinstate_path(pp, 0); + } else { + LOG_MSG(4, checker_message(&pp->checker)); + /* + * double the next check delay. + * max at conf->max_checkint + */ + if (pp->checkint < (conf->max_checkint / 2)) + pp->checkint = 2 * pp->checkint; + else + pp->checkint = conf->max_checkint; - pp->tick = pp->checkint; - condlog(4, "%s: delay next check %is", + pp->tick = pp->checkint; + condlog(4, "%s: delay next check %is", pp->dev_t, pp->tick); + } } else if (newstate == PATH_DOWN) LOG_MSG(2, checker_message(&pp->checker)); @@ -1341,9 +1347,7 @@ /* * exit path */ - lock(vecs->lock); remove_maps_and_stop_waiters(vecs); - free_pathvec(vecs->pathvec, FREE_PATHS); pthread_cancel(check_thr); pthread_cancel(uevent_thr); @@ -1357,6 +1361,9 @@ handlers = NULL; free_polls(); + lock(vecs->lock); + free_pathvec(vecs->pathvec, FREE_PATHS); + vecs->pathvec = NULL; unlock(vecs->lock); pthread_mutex_destroy(vecs->lock); FREE(vecs->lock); @@ -1421,15 +1428,28 @@ } close(STDIN_FILENO); - dup(in_fd); + if (dup(in_fd) < 0) { + fprintf(stderr, "cannot duplicate /dev/null for input" + ": %s\n", strerror(errno)); + _exit(0); + } close(STDOUT_FILENO); - dup(out_fd); + if (dup(out_fd) < 0) { + fprintf(stderr, "cannot duplicate /dev/console for output" + ": %s\n", strerror(errno)); + _exit(0); + } close(STDERR_FILENO); - dup(out_fd); - + if (dup(out_fd) < 0) { + fprintf(stderr, "cannot duplicate /dev/console for error" + ": %s\n", strerror(errno)); + _exit(0); + } close(in_fd); close(out_fd); - chdir("/"); + if (chdir("/") < 0) + fprintf(stderr, "cannot chdir to '/', continuing\n"); + umask(0); return 0; } @@ -1451,7 +1471,9 @@ } /* make sure we don't lock any path */ - chdir("/"); + if (chdir("/") < 0) + fprintf(stderr, "couldn't chdir to '/', continuing\n"); + umask(umask(077) | 022); conf = alloc_config(); --- multipath-tools-0.4.8/multipathd/multipathd.init.suse +++ multipath-tools-0.4.8/multipathd/multipathd.init.suse @@ -12,10 +12,11 @@ ### BEGIN INIT INFO # Provides: multipathd # Required-Start: $syslog -# Required-Stop: +# Required-Stop: $syslog # Default-Start: 3 5 # Default-Stop: 0 1 2 4 6 -# Description: Starts multipath daemon +# Short-Description: Starts multipath daemon +# Description: Starts the multipath daemon ### END INIT INFO PATH=/bin:/usr/bin:/sbin:/usr/sbin --- multipath-tools-0.4.8/multipathd/uxlsnr.c +++ multipath-tools-0.4.8/multipathd/uxlsnr.c @@ -168,5 +168,6 @@ } } + close(ux_sock); return NULL; }