1
0
multipath-tools/multipath-tools-sles11-alpha1-update

3619 lines
89 KiB
Plaintext

--- 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 <<EOF
+ACTION=="add", KERNEL=="sd*[!0-9]", ENV{ID_VENDOR}=="ATA", ENV{ID_ATA_COMPAT}=="$atalink", RUN+="/bin/bash -c 'echo 0 $blksize linear \$major:\$minor 0 | /sbin/dmsetup create ata-\$env{ID_ATA_COMPAT} -u linear-ata-\$env{ID_ATA_COMPAT}'"
+EOF
+fi
+if [ "$scsilink" ] ; then
+ # Remove existing rules
+ echo "/$scsilink/d
+w
+q
+" | ed $RULE > /dev/null 2>&1
+ [ "$remove_only" = 1 ] && exit 0
+ # And create a new one
+ cat >> $RULE <<EOF
+ACTION=="add", KERNEL=="sd*[!0-9]", ENV{ID_BUS}=="scsi", ENV{ID_SERIAL}=="$scsilink", RUN+="/bin/bash -c 'echo 0 $blksize linear \$major:\$minor 0 | /sbin/dmsetup create \$env{ID_BUS}-\$env{ID_SERIAL} -u linear-\$env{ID_BUS}-\$env{ID_SERIAL}'"
+EOF
+fi
--- multipath-tools-0.4.8/kpartx/boot-kpartx.sh
+++ multipath-tools-0.4.8/kpartx/boot-kpartx.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+#%stage: block
+#%depends: dmroot
+#%if: "$root_kpartx"
+#%programs: /sbin/kpartx /lib/udev/kpartx_id
--- multipath-tools-0.4.8/kpartx/devmapper.c
+++ multipath-tools-0.4.8/kpartx/devmapper.c
@@ -13,6 +13,7 @@
#define UUID_PREFIX "part%d-"
#define MAX_PREFIX_LEN 8
+#define PARAMS_SIZE 1024
extern int
dm_prereq (char * str, int x, int y, int z)
@@ -251,3 +252,63 @@
return r;
}
+int
+dm_get_map(int major, int minor, char * outparams)
+{
+ int r = 1;
+ struct dm_task *dmt;
+ void *next = NULL;
+ uint64_t start, length;
+ char *target_type = NULL;
+ char *params = NULL;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+ return 1;
+
+ dm_task_set_major(dmt, major);
+ dm_task_set_minor(dmt, minor);
+ dm_task_no_open_count(dmt);
+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ /* Fetch 1st target */
+ next = dm_get_next_target(dmt, next, &start, &length,
+ &target_type, &params);
+
+ if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
+ r = 0;
+out:
+ dm_task_destroy(dmt);
+ return r;
+}
+
+#define FEATURE_NO_PART "no_partitions"
+
+int
+dm_no_partitions(int major, int minor)
+{
+ char params[PARAMS_SIZE], *ptr;
+ int i, num_features;
+
+ if (dm_get_map(major, minor, params))
+ return 0;
+
+ ptr = params;
+ num_features = strtoul(params, &ptr, 10);
+ if ((ptr == params) || num_features == 0) {
+ /* No features found, return success */
+ return 0;
+ }
+ for (i = 0; (i < num_features); i++) {
+ if (!ptr || ptr > 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; j<n; j++) {
+ for (j = 0, c = 0; j < n; j++) {
if (slices[j].size == 0)
continue;
@@ -474,6 +479,7 @@
d = c;
while (c) {
for (j = 0; j < n; j++) {
+ uint64_t start;
int k = slices[j].container - 1;
if (slices[j].size == 0)
@@ -484,7 +490,7 @@
continue;
/* Skip all simple slices */
- if (k < 0)
+ if (slices[j].container == 0)
continue;
/* Check container slice */
@@ -499,10 +505,11 @@
}
strip_slash(partname);
+ start = slices[j].start - slices[k].start;
if (safe_sprintf(params, "%d:%d %" PRIu64,
slices[k].major,
slices[k].minor,
- slices[j].start)) {
+ start)) {
fprintf(stderr, "params too small\n");
exit(1);
}
--- multipath-tools-0.4.8/kpartx/kpartx.rules
+++ multipath-tools-0.4.8/kpartx/kpartx.rules
@@ -9,7 +9,7 @@
ENV{DM_TABLE_STATE}!="LIVE", GOTO="kpartx_end"
-ENV{DM_UUID}=="?*", IMPORT{program}=="/lib/udev/kpartx_id %M %m $env{DM_UUID}"
+ENV{DM_UUID}=="?*", IMPORT{program}=="kpartx_id %M %m $env{DM_UUID}"
OPTIONS="link_priority=50"
@@ -18,7 +18,11 @@
SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
# Create persistent links for dmraid tables
-ENV{DM_UUID}=="mpath-*", \
+ENV{DM_UUID}=="dmraid-*", \
+ SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
+
+# Create persistent links for linear tables
+ENV{DM_UUID}=="linear-*", \
SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
# Create persistent links for partitions
@@ -27,9 +31,11 @@
# Create dm tables for partitions
ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="mpath-*", \
- RUN+="/sbin/kpartx -a -p -part /dev/$kernel"
+ RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="dmraid-*", \
- RUN+="/sbin/kpartx -a -p -part /dev/$kernel"
+ RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
+ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="linear-*", \
+ RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
LABEL="kpartx_end"
--- multipath-tools-0.4.8/kpartx/kpartx_id
+++ multipath-tools-0.4.8/kpartx/kpartx_id
@@ -50,7 +50,7 @@
fi
# Set the name of the table. We're only interested in dmraid,
-# multipath, and kpartx tables; everything else is ignored.
+# multipath, linear, and kpartx tables; everything else is ignored.
if [ "$dmtbl" = "part" ] ; then
# The name of the kpartx table is the name of the parent table
dmname=$($DMSETUP info -c --noheadings -o name -u $dmuuid)
@@ -61,6 +61,10 @@
mpath-*)
dmdeps=$($DMSETUP deps -u $dmuuid)
;;
+ linear-*)
+ dmtbl=linear
+ dmuuid=${dmuuid#*-}
+ ;;
esac
elif [ "$dmtbl" = "mpath" ] ; then
dmname=$tblname
@@ -72,8 +76,8 @@
[ -n "$dmpart" ] && echo "DM_PART=$dmpart"
-# Figure out the type of the map. For non-multipath maps it's
-# always 'raid'.
+# Figure out the type of the map. For non-multipath non-linear
+# maps it's always 'raid'.
if [ -n "$dmdeps" ] ; then
case "$dmdeps" in
*\(94,*)
@@ -86,6 +90,9 @@
echo "DM_TYPE=scsi"
;;
esac
+elif [ "$dmtbl" = linear ]; then
+ echo "DM_TYPE=${dmuuid%%-*}"
+ echo "DM_NAME=${dmuuid#*-}"
else
echo "DM_TYPE=raid"
fi
--- multipath-tools-0.4.8/kpartx/setup-kpartx.sh
+++ multipath-tools-0.4.8/kpartx/setup-kpartx.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+#%stage: partitions
+#
+if [ -x /sbin/dmsetup ]; then
+ kpartx_blockdev=
+
+ # always activate kpartx when using dm block
+ [ "$DM_BLOCK" ] && root_kpartx=1
+ # always activate kpartx for multipathing
+ use_script multipath && root_kpartx=1
+ 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)
+ case $dm_uuid in
+ part*)
+ dm_uuid="${dm_uuid#*-}"
+ kpartx_blockdev="$kpartx_blockdev $(majorminor2blockdev $(dmsetup info -u $dm_uuid --noheadings -c -o major,minor))"
+ root_kpartx=1
+ ;;
+ *)
+ kpartx_blockdev="$kpartx_blockdev $bd"
+ ;;
+ esac
+ else
+ kpartx_blockdev="$kpartx_blockdev $bd"
+ fi
+ done
+
+ blockdev="$kpartx_blockdev"
+fi
+
+if use_script kpartx; then
+ cp /etc/udev/rules.d/70-kpartx.rules $tmp_mnt/etc/udev/rules.d
+fi
--- multipath-tools-0.4.8/libmultipath/Makefile
+++ multipath-tools-0.4.8/libmultipath/Makefile
@@ -25,9 +25,8 @@
$(LIBS): $(OBJS)
$(CC) $(SHARED_FLAGS) $(CFLAGS) -o $@ $(OBJS)
-install:
- $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(libdir)
- $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir)/$(LIBS)
+install: $(LIBS)
+ $(INSTALL_PROGRAM) -D $(LIBS) $(DESTDIR)$(libdir)/$(LIBS)
uninstall:
rm -f $(DESTDIR)$(libdir)/$(LIBS)
--- multipath-tools-0.4.8/libmultipath/alias.c
+++ multipath-tools-0.4.8/libmultipath/alias.c
@@ -86,7 +86,7 @@
sigset_t set, oldset;
struct flock lock;
int err;
-
+
memset(&lock, 0, sizeof(lock));
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
@@ -149,7 +149,7 @@
}
if (*can_write && lock_bindings_file(fd) < 0)
goto fail;
-
+
memset(&s, 0, sizeof(s));
if (fstat(fd, &s) < 0){
condlog(0, "Cannot stat bindings file : %s", strerror(errno));
@@ -171,7 +171,7 @@
fsync(fd);
condlog(3, "Initialized new bindings file [%s]", file);
}
-
+
return fd;
fail:
--- multipath-tools-0.4.8/libmultipath/blacklist.c
+++ multipath-tools-0.4.8/libmultipath/blacklist.c
@@ -16,7 +16,7 @@
store_ble (vector blist, char * str, int origin)
{
struct blentry * ble;
-
+
if (!str)
return 0;
@@ -61,12 +61,12 @@
vector_set_slot(blist, ble);
return 0;
}
-
+
extern int
set_ble_device (vector blist, char * vendor, char * product, int origin)
{
struct blentry_device * ble;
-
+
if (!blist)
return 1;
@@ -142,14 +142,14 @@
int
_blacklist_exceptions (vector elist, char * str)
{
- int i;
- struct blentry * ele;
+ int i;
+ struct blentry * ele;
- vector_foreach_slot (elist, ele, i) {
- if (!regexec(&ele->regex, 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, <acassen@linux-vs.org>
- *
+ *
* 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <assert.h>
-
-#include <sg_include.h>
-#include <debug.h>
-#include <prio.h>
-
-#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; i<size; i++) {
- p += snprintf(p, 10*(size-i), "0x%02x ", cdb[i]);
- }
- condlog(0, "%s", buf);
-}
-
-static void process_sg_error(struct sg_io_hdr *io_hdr)
-{
- int i;
- char buf[128*5+1];
- char * p = &buf[0];
-
- condlog(0, "- masked_status=0x%02x, host_status=0x%02x, "
- "driver_status=0x%02x", io_hdr->masked_status,
- io_hdr->host_status, io_hdr->driver_status);
- if (io_hdr->sb_len_wr > 0) {
- condlog(0, "- SCSI sense data: ");
- for (i=0; i<io_hdr->sb_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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <sg_include.h>
+#include <debug.h>
+#include <prio.h>
+
+#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; i<size; i++) {
+ p += snprintf(p, 10*(size-i), "0x%02x ", cdb[i]);
+ }
+ condlog(0, "%s", buf);
+}
+
+static void process_sg_error(struct sg_io_hdr *io_hdr)
+{
+ int i;
+ char buf[128*5+1];
+ char * p = &buf[0];
+
+ condlog(0, "- masked_status=0x%02x, host_status=0x%02x, "
+ "driver_status=0x%02x", io_hdr->masked_status,
+ io_hdr->host_status, io_hdr->driver_status);
+ if (io_hdr->sb_len_wr > 0) {
+ condlog(0, "- SCSI sense data: ");
+ for (i=0; i<io_hdr->sb_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, <acassen@linux-vs.org>
- *
+ *
* 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 <stdlib.h>
#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 : <full_pathname>
+# # 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 <feedback@suse.de>
+#
+# 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;
}