Imported Upstream version 0.6.1 upstream/0.6.1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 14 Jan 2022 04:50:15 +0000 (13:50 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 14 Jan 2022 04:50:15 +0000 (13:50 +0900)
42 files changed:
ChangeLog
README
TODO [deleted file]
kpartx/Makefile
kpartx/dasd.c
kpartx/dasd.h
kpartx/kpartx.rules
kpartx/kpartx_id
kpartx/lopart.c
libmpathpersist/Makefile
libmultipath/callout.c
libmultipath/config.h
libmultipath/configure.c
libmultipath/configure.h
libmultipath/defaults.h
libmultipath/devmapper.c
libmultipath/devmapper.h
libmultipath/dict.c
libmultipath/discovery.c
libmultipath/dmparser.c
libmultipath/hwtable.c
libmultipath/lock.h
libmultipath/print.c
libmultipath/structs.c
libmultipath/structs_vec.c
libmultipath/structs_vec.h
libmultipath/uevent.c
libmultipath/version.h
multipath.conf.annotated [deleted file]
multipath.conf.defaults [deleted file]
multipath.conf.synthetic [deleted file]
multipath/11-dm-mpath.rules
multipath/main.c
multipath/multipath.conf.5
multipathd/cli.c
multipathd/cli.h
multipathd/cli_handlers.c
multipathd/cli_handlers.h
multipathd/main.c
multipathd/main.h
multipathd/multipathd.service
multipathd/uxlsnr.c

index 73026b3..4b547bb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,6 @@
 Change logs are at :
 
 - pre-0.4.5
-  http://christophe.varoqui.free.fr/wiki/wakka.php?wiki=ChangeLog
+  http://web.archive.org/web/20070309224034/http://christophe.varoqui.free.fr/wiki/wakka.php?wiki=ChangeLog
 - post-0.4.5
-  http://www.kernel.org/git/gitweb.cgi?p=linux/storage/multipath-tools/.git;a=log
+  http://git.opensvc.com/?p=multipath-tools/.git;a=log
diff --git a/README b/README
index b0b9dfa..1914e38 100644 (file)
--- a/README
+++ b/README
@@ -1 +1,14 @@
-Things to read
+multipath-tools for Linux <http://christophe.varoqui.free.fr/>
+
+This package provides the following binaries to drive the
+Device Mapper multipathing driver:
+
+multipath - Device mapper target autoconfig.
+multipathd - Multipath daemon.
+mpathpersist - Manages SCSI persistent reservations on dm multipath devices.
+kpartxrtx - Create device maps from partition tables.
+
+To get latest code: git clone http://git.opensvc.com/multipath-tools/.git
+
+Mailing list: http://www.redhat.com/mailman/listinfo/dm-devel
+Gitweb: http://git.opensvc.com/?p=multipath-tools/.git
diff --git a/TODO b/TODO
deleted file mode 100644 (file)
index 690ea03..0000000
--- a/TODO
+++ /dev/null
@@ -1 +0,0 @@
-Things to do
index 4ba38ba..501b277 100644 (file)
@@ -28,8 +28,8 @@ install: $(EXEC) $(EXEC).8
        $(INSTALL_PROGRAM) -m 755 $(EXEC) $(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) -d $(DESTDIR)$(libudevdir)/rules.d
+       $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)$(libudevdir)/rules.d/66-kpartx.rules
        $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
        $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
 
@@ -37,6 +37,8 @@ uninstall:
        rm -f $(DESTDIR)$(bindir)/$(EXEC)
        rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
        rm -f $(DESTDIR)$(libudevdir)/kpartx_id
+       rm -f $(DESTDIR)$(libudevdir)/rules.d/66-kpartx.rules
+       rm -f $(DESTDIR)$(libudevdir)/rules.d/67-kpartx-compat.rules
 
 clean:
        rm -f core *.o $(EXEC) *.gz
index 1fcf778..14c35b1 100644 (file)
@@ -46,6 +46,21 @@ unsigned long long sectors512(unsigned long long sectors, int blocksize)
        return sectors * (blocksize >> 9);
 }
 
+/*
+ * Magic records per track calculation, copied from fdasd.c
+ */
+static unsigned int ceil_quot(unsigned int d1, unsigned int d2)
+{
+       return (d1 + (d2 - 1)) / d2;
+}
+
+unsigned int recs_per_track(unsigned int dl)
+{
+       int dn = ceil_quot(dl + 6, 232) + 1;
+       return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
+}
+
+
 typedef unsigned int __attribute__((__may_alias__)) label_ints_t;
 
 /*
@@ -124,19 +139,31 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
        }
 
        if (ioctl(fd_dasd, BIODASDINFO, (unsigned long)&info) != 0) {
-               goto out;
+               info.label_block = 2;
+               info.FBA_layout = 0;
+               memcpy(info.type, "ECKD", sizeof(info.type));
        }
 
-       if (ioctl(fd_dasd, HDIO_GETGEO, (unsigned long)&geo) != 0) {
+       if (ioctl(fd_dasd, BLKSSZGET, &blocksize) != 0)
                goto out;
-       }
 
        if (ioctl(fd_dasd, BLKGETSIZE64, &disksize) != 0)
                goto out;
-       disksize >>= 9;
 
-       if (ioctl(fd_dasd, BLKSSZGET, &blocksize) != 0)
-               goto out;
+       if (ioctl(fd_dasd, HDIO_GETGEO, (unsigned long)&geo) != 0) {
+               unsigned int cyl;
+
+               geo.heads = 15;
+               geo.sectors = recs_per_track(blocksize);
+               cyl = disksize / (blocksize * geo.heads * geo.sectors);
+               if (cyl < LV_COMPAT_CYL)
+                       geo.cylinders = cyl;
+               else
+                       geo.cylinders = LV_COMPAT_CYL;
+               geo.start = 0;
+       }
+
+       disksize >>= 9;
 
        if (blocksize < 512 || blocksize > 4096)
                goto out;
index 42f94db..6fa64e6 100644 (file)
@@ -164,6 +164,7 @@ typedef struct dasd_information_t {
 #define BLKGETSIZE _IO(0x12,96)
 #define BLKSSZGET _IO(0x12,104)
 #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* device size in bytes (u64 *arg)*/
+#define LV_COMPAT_CYL 0xFFFE
 
 /*
  * Only compile this on S/390. Doesn't make any sense
index 022361f..f6a3706 100644 (file)
@@ -14,19 +14,14 @@ ENV{DM_UUID}=="?*", IMPORT{program}=="kpartx_id %M %m $env{DM_UUID}"
 
 OPTIONS="link_priority=50"
 
-# Create persistent links for multipath tables
-ENV{DM_UUID}=="mpath-*", \
+ENV{DM_UUID}=="?*", ENV{DM_TYPE}=="?*" \
        SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
-ENV{DM_MPATH}=="?*", ENV{DM_PART}!="?*", \
-       SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_MPATH}"
+
+# Create persistent links for multipath tables
 ENV{DM_WWN}=="?*", ENV{DM_PART}!="?*", \
        SYMLINK+="disk/by-id/wwn-$env{DM_WWN}"
 
 # Create persistent links for partitions
-ENV{DM_PART}=="?*", \
-        SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}-part$env{DM_PART}"
-ENV{DM_MPATH}=="?*", ENV{DM_PART}=="?*", \
-       SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_MPATH}-part$env{DM_PART}"
 ENV{DM_WWN}=="?*", ENV{DM_PART}=="?*", \
        SYMLINK+="disk/by-id/wwn-$env{DM_WWN}-part$env{DM_PART}"
 
index 517b856..df0e6b9 100644 (file)
@@ -52,12 +52,8 @@ fi
 # Set the name of the table. We're only interested in dmraid,
 # multipath, 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)
-    echo "DM_NAME=$dmname"
-    if [ "$dmname" != ${dmuuid#mpath-} ] ; then
-       echo "DM_MPATH=${dmuuid#mpath-}"
-    fi
+    echo "DM_MPATH=$dmname"
     # We need the dependencies of the parent table to figure out
     # the type if the parent is a multipath table
     case "$dmuuid" in
@@ -66,14 +62,9 @@ if [ "$dmtbl" = "part" ] ; then
            ;;
     esac
 elif [ "$dmtbl" = "mpath" ] ; then
-    if [ -n "$DM_NAME" -a "$DM_NAME" != "$dmuuid" ] ; then
-       echo "DM_MPATH=$dmuuid"
-    fi
     dmname="$dmuuid"
     # We need the dependencies of the table to figure out the type
     dmdeps=$($DMSETUP deps -u $UUID)
-elif [ "$dmtbl" = "dmraid" ] ; then
-    dmname=$tblname
 fi
 
 [ -n "$dmpart" ] && echo "DM_PART=$dmpart"
index 26f3011..ffde6d9 100644 (file)
@@ -25,8 +25,9 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/types.h>
+#include <dirent.h>
 #include <sysmacros.h>
-#include <asm/posix_types.h>
 #include <linux/loop.h>
 
 #include "lopart.h"
@@ -98,78 +99,71 @@ is_loop_device (const char *device)
 extern char *
 find_loop_by_file (const char * filename)
 {
-       char dev[64];
-       char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
-       int i, j, fd;
+       DIR *dir;
+       struct dirent *dent;
+       char dev[64], *found = NULL;
+       int fd;
        struct stat statbuf;
        struct loop_info loopinfo;
-       dev_t file_dev;
-       ino_t file_ino;
 
-       if (stat (filename, &statbuf) != 0) {
+       dir = opendir("/dev");
+       if (!dir)
                return NULL;
-       }
-       file_dev = statbuf.st_dev;
-       file_ino = statbuf.st_ino;
-
-       for (j = 0; j < SIZE(loop_formats); j++) {
-
-               for (i = 0; i < 256; i++) {
-                       sprintf (dev, loop_formats[j], i);
-
-                       if (stat (dev, &statbuf) != 0 ||
-                           !S_ISBLK(statbuf.st_mode))
-                               continue;
-
-                       fd = open (dev, O_RDONLY);
 
-                       if (fd < 0)
-                               break;
+       while ((dent = readdir(dir)) != NULL) {
+               if (strncmp(dent->d_name,"loop",4))
+                       continue;
+               if (!strcmp(dent->d_name, "loop-control"))
+                       continue;
+               sprintf(dev, "/dev/%s", dent->d_name);
 
-                       if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
-                               close (fd);
-                               continue;
-                       }
+               if (stat (dev, &statbuf) != 0 ||
+                   !S_ISBLK(statbuf.st_mode))
+                       continue;
 
-                       if (loopinfo.lo_device == file_dev && loopinfo.lo_inode == file_ino) {
-                               close (fd);
-                               return xstrdup(dev); /*found */
-                       }
+               fd = open (dev, O_RDONLY);
+               if (fd < 0)
+                       break;
 
+               if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
                        close (fd);
                        continue;
                }
+
+               if (0 == strcmp(filename, loopinfo.lo_name)) {
+                       close (fd);
+                       found = xstrdup(dev);
+                       break;
+               }
+
+               close (fd);
        }
-       return NULL;
+       closedir(dir);
+       return found;
 }
 
 extern char *
 find_unused_loop_device (void)
 {
-       /* Just creating a device, say in /tmp, is probably a bad idea -
-          people might have problems with backup or so.
-          So, we just try /dev/loop[0-7]. */
-
-       char dev[20];
-       char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
-       int i, j, fd, first = 0, somedev = 0, someloop = 0, loop_known = 0;
+       char dev[20], *next_loop_dev = NULL;;
+       int fd, next_loop = 0, somedev = 0, someloop = 0, loop_known = 0;
        struct stat statbuf;
        struct loop_info loopinfo;
        FILE *procdev;
 
-       if (stat("/dev/loop-control", &statbuf) == 0 &&
-           S_ISCHR(statbuf.st_mode)) {
-               fd = open("/dev/loop-control", O_RDWR);
-               if (fd >= 0)
-                       first = ioctl(fd, LOOP_CTL_GET_FREE);
-               close(fd);
-               if (first < 0)
-                       first = 0;
-       }
-       for (j = 0; j < SIZE(loop_formats); j++) {
+       while (next_loop_dev == NULL) {
+               if (stat("/dev/loop-control", &statbuf) == 0 &&
+                   S_ISCHR(statbuf.st_mode)) {
+                       fd = open("/dev/loop-control", O_RDWR);
+                       if (fd < 0)
+                               return NULL;
+                       next_loop = ioctl(fd, LOOP_CTL_GET_FREE);
+                       if (next_loop < 0)
+                               return NULL;
+                       close(fd);
+               }
 
-           for(i = first; i < 256; i++) {
-               sprintf(dev, loop_formats[j], i);
+               sprintf(dev, "/dev/loop%d", next_loop);
 
                if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
                        somedev++;
@@ -182,18 +176,19 @@ find_unused_loop_device (void)
 
                                else if (errno == ENXIO) {
                                        close (fd);
-                                       return xstrdup(dev);/* probably free */
+                                       next_loop_dev = xstrdup(dev);
                                }
 
                                close (fd);
                        }
-                       
+
                        /* continue trying as long as devices exist */
                        continue;
                }
                break;
-           }
        }
+       if (next_loop_dev)
+               return next_loop_dev;
 
        /* Nothing found. Why not? */
        if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
@@ -216,12 +211,10 @@ find_unused_loop_device (void)
                fprintf(stderr, "mount: could not find any device /dev/loop#");
 
        else if (!someloop) {
-
            if (loop_known == 1)
                fprintf(stderr,
                    "mount: Could not find any loop device.\n"
                    "       Maybe /dev/loop# has a wrong major number?");
-           
            else if (loop_known == -1)
                fprintf(stderr,
                    "mount: Could not find any loop device, and, according to %s,\n"
@@ -237,7 +230,6 @@ find_unused_loop_device (void)
 
        } else
                fprintf(stderr, "mount: could not find any free loop device");
-       
        return 0;
 }
 
index e49cdb9..59db73a 100644 (file)
@@ -40,8 +40,8 @@ install: $(LIBS)
 
 uninstall:
        rm -f $(DESTDIR)$(syslibdir)/$(LIBS)
-       rm $(DESTDIR)$(man3dir)/mpath_persistent_reserve_in.3.gz        
-       rm $(DESTDIR)$(man3dir)/mpath_persistent_reserve_out.3.gz       
+       rm $(DESTDIR)$(man3dir)/mpath_persistent_reserve_in.3.gz
+       rm $(DESTDIR)$(man3dir)/mpath_persistent_reserve_out.3.gz
 
 clean:
        rm -f core *.a *.o 
index 4cbbd06..d671b0c 100644 (file)
@@ -201,8 +201,10 @@ apply_format (char * string, char * cmd, struct path * pp)
        }
        pos++;
 
-       if (!*pos)
+       if (!*pos) {
+               condlog(3, "formatted callout = %s", dst);
                return 0;
+       }
 
        len = strlen(pos) + 1;
        myfree -= len;
@@ -211,6 +213,6 @@ apply_format (char * string, char * cmd, struct path * pp)
                return 1;
 
        snprintf(p, len, "%s", pos);
-       condlog(3, "reformated callout = %s", dst);
+       condlog(3, "reformatted callout = %s", dst);
        return 0;
 }
index e9828ea..466e31e 100644 (file)
@@ -135,6 +135,7 @@ struct config {
        int delay_watch_checks;
        int delay_wait_checks;
        int uxsock_timeout;
+       int strict_timing;
        int retrigger_tries;
        int retrigger_delay;
        int ignore_new_devs;
index 30c7259..a4a2c44 100644 (file)
@@ -398,7 +398,7 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
                        strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
                        mpp->action = ACT_RENAME;
                        if (force_reload)
-                               mpp->action = ACT_RENAME2;
+                               mpp->action = ACT_FORCERENAME;
                        return;
                }
                mpp->action = ACT_CREATE;
@@ -546,7 +546,7 @@ lock_multipath (struct multipath * mpp, int lock)
                if (!pgp->paths)
                        continue;
                vector_foreach_slot(pgp->paths, pp, j) {
-                       if (lock && flock(pp->fd, LOCK_EX | LOCK_NB) &&
+                       if (lock && flock(pp->fd, LOCK_SH | LOCK_NB) &&
                            errno == EWOULDBLOCK)
                                goto fail;
                        else if (!lock)
@@ -625,29 +625,21 @@ domap (struct multipath * mpp, char * params)
                break;
 
        case ACT_RELOAD:
-               r = dm_addmap_reload(mpp, params);
-               if (r)
-                       r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias,
-                                                0, MPATH_UDEV_RELOAD_FLAG);
+               r = dm_addmap_reload(mpp, params, 0);
                break;
 
        case ACT_RESIZE:
-               r = dm_addmap_reload(mpp, params);
-               if (r)
-                       r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, 0);
+               r = dm_addmap_reload(mpp, params, 1);
                break;
 
        case ACT_RENAME:
                r = dm_rename(mpp->alias_old, mpp->alias);
                break;
 
-       case ACT_RENAME2:
+       case ACT_FORCERENAME:
                r = dm_rename(mpp->alias_old, mpp->alias);
-               if (r) {
-                       r = dm_addmap_reload(mpp, params);
-                       if (r)
-                               r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, 0, MPATH_UDEV_RELOAD_FLAG);
-               }
+               if (r)
+                       r = dm_addmap_reload(mpp, params, 0);
                break;
 
        default:
@@ -967,7 +959,8 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
                                return ret;
                        }
                }
-               if (pp->udev && filter_property(conf, pp->udev) > 0)
+               if (pp->udev && pp->uid_attribute &&
+                   filter_property(conf, pp->udev) > 0)
                        return 2;
 
                refwwid = pp->wwid;
@@ -976,7 +969,11 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
 
        if (dev_type == DEV_DEVT) {
                strchop(dev);
-               pp = find_path_by_devt(pathvec, dev);
+               if (devt2devname(buff, FILE_NAME_SIZE, dev)) {
+                       condlog(0, "%s: cannot find block device\n", dev);
+                       return 1;
+               }
+               pp = find_path_by_dev(pathvec, buff);
                if (!pp) {
                        struct udev_device *udevice = udev_device_new_from_devnum(conf->udev, 'b', parse_devt(dev));
 
@@ -994,7 +991,8 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
                                return ret;
                        }
                }
-               if (pp->udev && filter_property(conf, pp->udev) > 0)
+               if (pp->udev && pp->uid_attribute &&
+                   filter_property(conf, pp->udev) > 0)
                        return 2;
 
                refwwid = pp->wwid;
@@ -1017,7 +1015,8 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
                                        dev);
                        return ret;
                }
-               if (pp->udev && filter_property(conf, pp->udev) > 0)
+               if (pp->udev && pp->uid_attribute &&
+                   filter_property(conf, pp->udev) > 0)
                        return 2;
 
                refwwid = pp->wwid;
index c014b55..f357d9a 100644 (file)
@@ -18,7 +18,7 @@ enum actions {
        ACT_RENAME,
        ACT_CREATE,
        ACT_RESIZE,
-       ACT_RENAME2,
+       ACT_FORCERENAME,
 };
 
 #define FLUSH_ONE 1
index bce8bcc..96f5a2c 100644 (file)
@@ -15,6 +15,7 @@
 #define DEFAULT_REASSIGN_MAPS  0
 #define DEFAULT_FIND_MULTIPATHS        0
 #define DEFAULT_FAST_IO_FAIL   5
+#define DEFAULT_DEV_LOSS_TMO   600
 #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF
 #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF
 #define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF
index 36c1a20..6d1a5d6 100644 (file)
@@ -230,10 +230,11 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t
        if (do_deferred(deferred_remove))
                dm_task_deferred_remove(dmt);
 #endif
-       if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) {
-               dm_udev_complete(cookie);
+       if (udev_wait_flag &&
+           !dm_task_set_cookie(dmt, &cookie,
+                               DM_UDEV_DISABLE_LIBRARY_FALLBACK | udev_flags))
                goto out;
-       }
+
        r = dm_task_run (dmt);
 
        if (udev_wait_flag) {
@@ -248,13 +249,13 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t
 }
 
 extern int
-dm_simplecmd_flush (int task, const char *name, int needsync, uint16_t udev_flags) {
-       return dm_simplecmd(task, name, 0, needsync, udev_flags, 0);
+dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags) {
+       return dm_simplecmd(task, name, 0, 1, udev_flags, 0);
 }
 
 extern int
-dm_simplecmd_noflush (int task, const char *name, int needsync, uint16_t udev_flags) {
-       return dm_simplecmd(task, name, 1, needsync, udev_flags, 0);
+dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) {
+       return dm_simplecmd(task, name, 1, 1, udev_flags, 0);
 }
 
 static int
@@ -263,9 +264,9 @@ dm_device_remove (const char *name, int needsync, int deferred_remove) {
                            deferred_remove);
 }
 
-extern int
-dm_addmap (int task, const char *target, struct multipath *mpp, char * params,
-          int use_uuid, int ro) {
+static int
+dm_addmap (int task, const char *target, struct multipath *mpp,
+          char * params, int ro) {
        int r = 0;
        struct dm_task *dmt;
        char *prefixed_uuid = NULL;
@@ -283,16 +284,23 @@ dm_addmap (int task, const char *target, struct multipath *mpp, char * params,
        if (ro)
                dm_task_set_ro(dmt);
 
-       if (use_uuid && strlen(mpp->wwid) > 0){
-               prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(mpp->wwid) + 1);
-               if (!prefixed_uuid) {
-                       condlog(0, "cannot create prefixed uuid : %s",
-                               strerror(errno));
-                       goto addout;
+       if (task == DM_DEVICE_CREATE) {
+               if (strlen(mpp->wwid) > 0) {
+                       prefixed_uuid = MALLOC(UUID_PREFIX_LEN +
+                                              strlen(mpp->wwid) + 1);
+                       if (!prefixed_uuid) {
+                               condlog(0, "cannot create prefixed uuid : %s",
+                                       strerror(errno));
+                               goto addout;
+                       }
+                       sprintf(prefixed_uuid, UUID_PREFIX "%s", mpp->wwid);
+                       if (!dm_task_set_uuid(dmt, prefixed_uuid))
+                               goto freeout;
                }
-               sprintf(prefixed_uuid, UUID_PREFIX "%s", mpp->wwid);
-               if (!dm_task_set_uuid(dmt, prefixed_uuid))
-                       goto freeout;
+               dm_task_skip_lockfs(dmt);
+#ifdef LIBDM_API_FLUSH
+               dm_task_no_flush(dmt);
+#endif
        }
 
        if (mpp->attribute_flags & (1 << ATTR_MODE) &&
@@ -304,16 +312,17 @@ dm_addmap (int task, const char *target, struct multipath *mpp, char * params,
        if (mpp->attribute_flags & (1 << ATTR_GID) &&
            !dm_task_set_gid(dmt, mpp->gid))
                goto freeout;
-       condlog(4, "%s: addmap [0 %llu %s %s]", mpp->alias, mpp->size,
+       condlog(4, "%s: %s [0 %llu %s %s]", mpp->alias,
+               task == DM_DEVICE_RELOAD ? "reload" : "addmap", mpp->size,
                target, params);
 
        dm_task_no_open_count(dmt);
 
        if (task == DM_DEVICE_CREATE &&
-           !dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) {
-               dm_udev_complete(cookie);
+           !dm_task_set_cookie(dmt, &cookie,
+                               DM_UDEV_DISABLE_LIBRARY_FALLBACK))
                goto freeout;
-       }
+
        r = dm_task_run (dmt);
 
        if (task == DM_DEVICE_CREATE) {
@@ -339,8 +348,7 @@ dm_addmap_create (struct multipath *mpp, char * params) {
        for (ro = 0; ro <= 1; ro++) {
                int err;
 
-               if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH,
-                             mpp, params, 1, ro))
+               if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro))
                        return 1;
                /*
                 * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
@@ -364,12 +372,28 @@ dm_addmap_create (struct multipath *mpp, char * params) {
 #define ADDMAP_RO 1
 
 extern int
-dm_addmap_reload (struct multipath *mpp, char *params) {
-       if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW))
-               return 1;
-       if (errno != EROFS)
-               return 0;
-       return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO);
+dm_addmap_reload (struct multipath *mpp, char *params, int flush)
+{
+       int r;
+       uint16_t udev_flags = flush ? 0 : MPATH_UDEV_RELOAD_FLAG;
+
+       /*
+        * DM_DEVICE_RELOAD cannot wait on a cookie, as
+        * the cookie will only ever be released after an
+        * DM_DEVICE_RESUME. So call DM_DEVICE_RESUME
+        * after each successful call to DM_DEVICE_RELOAD.
+        */
+       r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, ADDMAP_RW);
+       if (!r) {
+               if (errno != EROFS)
+                       return 0;
+               r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp,
+                             params, ADDMAP_RO);
+       }
+       if (r)
+               r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, flush,
+                                1, udev_flags, 0);
+       return r;
 }
 
 extern int
@@ -833,14 +857,14 @@ dm_suspend_and_flush_map (const char * mapname)
        if (s)
                queue_if_no_path = 0;
        else
-               s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 1, 0);
+               s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0);
 
        if (!dm_flush_map(mapname)) {
                condlog(4, "multipath map %s removed", mapname);
                return 0;
        }
        condlog(2, "failed to remove multipath map %s", mapname);
-       dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 1, 0);
+       dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 0);
        if (queue_if_no_path)
                s = dm_queue_if_no_path((char *)mapname, 1);
        return 1;
@@ -1402,7 +1426,8 @@ dm_rename (const char * old, char * new)
 
        dm_task_no_open_count(dmt);
 
-       if (!dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
+       if (!dm_task_set_cookie(dmt, &cookie,
+                               DM_UDEV_DISABLE_LIBRARY_FALLBACK))
                goto out;
        r = dm_task_run(dmt);
 
@@ -1478,7 +1503,8 @@ int dm_reassign_table(const char *name, char *old, char *new)
                        condlog(3, "%s: failed to reassign targets", name);
                        goto out_reload;
                }
-               dm_simplecmd_noflush(DM_DEVICE_RESUME, name, 1, MPATH_UDEV_RELOAD_FLAG);
+               dm_simplecmd_noflush(DM_DEVICE_RESUME, name,
+                                    MPATH_UDEV_RELOAD_FLAG);
        }
        r = 1;
 
index 0d27723..b5df369 100644 (file)
 void dm_init(void);
 int dm_prereq (void);
 int dm_drv_version (unsigned int * version, char * str);
-int dm_simplecmd_flush (int, const char *, int, uint16_t);
-int dm_simplecmd_noflush (int, const char *, int, uint16_t);
+int dm_simplecmd_flush (int, const char *, uint16_t);
+int dm_simplecmd_noflush (int, const char *, uint16_t);
 int dm_addmap_create (struct multipath *mpp, char *params);
-int dm_addmap_reload (struct multipath *mpp, char *params);
+int dm_addmap_reload (struct multipath *mpp, char *params, int flush);
 int dm_map_present (const char *);
 int dm_get_map(const char *, unsigned long long *, char *);
 int dm_get_status(char *, char *);
index 89d42a1..7f912ec 100644 (file)
@@ -399,6 +399,9 @@ declare_def_snprint(retrigger_delay, print_int)
 declare_def_handler(uev_wait_timeout, set_int)
 declare_def_snprint(uev_wait_timeout, print_int)
 
+declare_def_handler(strict_timing, set_yes_no)
+declare_def_snprint(strict_timing, print_yes_no)
+
 static int
 def_config_dir_handler(vector strvec)
 {
@@ -1365,6 +1368,7 @@ init_keywords(void)
        install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler);
        install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio);
        install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
+       install_keyword("strict_timing", &def_strict_timing_handler, &snprint_def_strict_timing);
        install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove);
        install_keyword("partition_delimiter", &def_partition_delim_handler, &snprint_def_partition_delim);
        install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir);
index bd65354..db82b00 100644 (file)
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <unistd.h>
+#include <limits.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
@@ -147,6 +148,7 @@ path_discovery (vector pathvec, struct config * conf, int flag)
                return -ENOMEM;
 
        udev_enumerate_add_match_subsystem(udev_iter, "block");
+       udev_enumerate_add_match_is_initialized(udev_iter);
        udev_enumerate_scan_devices(udev_iter);
 
        udev_list_entry_foreach(entry,
@@ -237,8 +239,8 @@ sysfs_get_timeout(struct path *pp, unsigned int *timeout)
        const char *attr = NULL;
        const char *subsys;
        struct udev_device *parent;
-       int r;
-       unsigned int t;
+       char *eptr;
+       unsigned long t;
 
        if (!pp->udev || pp->bus != SYSFS_BUS_SCSI)
                return -ENOSYS;
@@ -256,14 +258,17 @@ sysfs_get_timeout(struct path *pp, unsigned int *timeout)
                return -ENXIO;
        }
 
-       r = sscanf(attr, "%u\n", &t);
-
-       if (r != 1) {
+       t = strtoul(attr, &eptr, 0);
+       if (attr == eptr || t == ULONG_MAX) {
                condlog(3, "%s: Cannot parse timeout attribute '%s'",
                        pp->dev, attr);
                return -EINVAL;
        }
-
+       if (t > UINT_MAX) {
+               condlog(3, "%s: Overflow in timeout value '%s'",
+                       pp->dev, attr);
+               return -ERANGE;
+       }
        *timeout = t;
 
        return 0;
@@ -482,7 +487,7 @@ static void
 sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
 {
        struct udev_device *rport_dev = NULL;
-       char value[16];
+       char value[16], *eptr;
        char rport_id[32];
        unsigned long long tmo = 0;
        int ret;
@@ -500,6 +505,22 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
                pp->sg_id.channel, pp->sg_id.scsi_id, rport_id);
 
        /*
+        * read the current dev_loss_tmo value from sysfs
+        */
+       ret = sysfs_attr_get_value(rport_dev, "dev_loss_tmo", value, 16);
+       if (ret <= 0) {
+               condlog(0, "%s: failed to read dev_loss_tmo value, "
+                       "error %d", rport_id, -ret);
+               goto out;
+       }
+       tmo = strtoull(value, &eptr, 0);
+       if (value == eptr || tmo == ULLONG_MAX) {
+               condlog(0, "%s: Cannot parse dev_loss_tmo "
+                       "attribute '%s'", rport_id, value);
+               goto out;
+       }
+
+       /*
         * This is tricky.
         * dev_loss_tmo will be limited to 600 if fast_io_fail
         * is _not_ set.
@@ -510,44 +531,31 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
         * then set fast_io_fail, and _then_ set dev_loss_tmo
         * to the correct value.
         */
-       memset(value, 0, 16);
        if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET &&
            mpp->fast_io_fail != MP_FAST_IO_FAIL_ZERO &&
            mpp->fast_io_fail != MP_FAST_IO_FAIL_OFF) {
                /* Check if we need to temporarily increase dev_loss_tmo */
-               ret = sysfs_attr_get_value(rport_dev, "dev_loss_tmo",
-                                          value, 16);
-               if (ret <= 0) {
-                       condlog(0, "%s: failed to read dev_loss_tmo value, "
-                               "error %d", rport_id, -ret);
-                       goto out;
-               }
-               if (sscanf(value, "%llu\n", &tmo) != 1) {
-                       condlog(0, "%s: Cannot parse dev_loss_tmo "
-                               "attribute '%s'", rport_id, value);
-                       goto out;
-               }
                if (mpp->fast_io_fail >= tmo) {
+                       /* Increase dev_loss_tmo temporarily */
                        snprintf(value, 16, "%u", mpp->fast_io_fail + 1);
+                       ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
+                                                  value, strlen(value));
+                       if (ret <= 0) {
+                               if (ret == -EBUSY)
+                                       condlog(3, "%s: rport blocked",
+                                               rport_id);
+                               else
+                                       condlog(0, "%s: failed to set "
+                                               "dev_loss_tmo to %s, error %d",
+                                               rport_id, value, -ret);
+                               goto out;
+                       }
                }
-       } else if (mpp->dev_loss > 600) {
-               condlog(3, "%s: limiting dev_loss_tmo to 600, since "
-                       "fast_io_fail is not set", rport_id);
-               snprintf(value, 16, "%u", 600);
-       } else {
-               snprintf(value, 16, "%u", mpp->dev_loss);
-       }
-       if (strlen(value)) {
-               ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
-                                          value, strlen(value));
-               if (ret <= 0) {
-                       if (ret == -EBUSY)
-                               condlog(3, "%s: rport blocked", rport_id);
-                       else
-                               condlog(0, "%s: failed to set dev_loss_tmo to %s, error %d",
-                                       rport_id, value, -ret);
-                       goto out;
-               }
+       } else if (mpp->dev_loss > DEFAULT_DEV_LOSS_TMO) {
+               condlog(3, "%s: limiting dev_loss_tmo to %d, since "
+                       "fast_io_fail is not set",
+                       rport_id, DEFAULT_DEV_LOSS_TMO);
+               mpp->dev_loss = DEFAULT_DEV_LOSS_TMO;
        }
        if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
                if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
@@ -566,7 +574,7 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
                                        rport_id, value, -ret);
                }
        }
-       if (tmo > 0) {
+       if (mpp->dev_loss > 0) {
                snprintf(value, 16, "%u", mpp->dev_loss);
                ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
                                           value, strlen(value));
@@ -668,11 +676,11 @@ sysfs_set_scsi_tmo (struct multipath *mpp)
                        no_path_retry_tmo = MAX_DEV_LOSS_TMO;
                if (no_path_retry_tmo > dev_loss_tmo)
                        dev_loss_tmo = no_path_retry_tmo;
-               condlog(3, "%s: update dev_loss_tmo to %d",
+               condlog(3, "%s: update dev_loss_tmo to %u",
                        mpp->alias, dev_loss_tmo);
        } else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE) {
                dev_loss_tmo = MAX_DEV_LOSS_TMO;
-               condlog(3, "%s: update dev_loss_tmo to %d",
+               condlog(3, "%s: update dev_loss_tmo to %u",
                        mpp->alias, dev_loss_tmo);
        }
        mpp->dev_loss = dev_loss_tmo;
@@ -1095,7 +1103,7 @@ scsi_sysfs_pathinfo (struct path * pp)
 
        condlog(3, "%s: product = %s", pp->dev, pp->product_id);
 
-       if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE) <= 0)
+       if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE) < 0)
                return 1;
 
        condlog(3, "%s: rev = %s", pp->dev, pp->rev);
@@ -1506,7 +1514,7 @@ get_vpd_uid(struct path * pp)
 }
 
 static int
-get_uid (struct path * pp)
+get_uid (struct path * pp, int path_state)
 {
        char *c;
        const char *origin = "unknown";
@@ -1526,13 +1534,14 @@ get_uid (struct path * pp)
 
                /* Use 'getuid' callout, deprecated */
                condlog(1, "%s: using deprecated getuid callout", pp->dev);
-               if (apply_format(pp->getuid, &buff[0], pp)) {
+               if (path_state != PATH_UP) {
+                       condlog(3, "%s: path inaccessible", pp->dev);
+                       len = -EWOULDBLOCK;
+               } else if (apply_format(pp->getuid, &buff[0], pp)) {
                        condlog(0, "error formatting uid callout command");
-                       memset(pp->wwid, 0, WWID_SIZE);
                        len = -EINVAL;
                } else if (execute_program(buff, pp->wwid, WWID_SIZE)) {
                        condlog(3, "error calling out %s", buff);
-                       memset(pp->wwid, 0, WWID_SIZE);
                        len = -EIO;
                } else
                        len = strlen(pp->wwid);
@@ -1552,7 +1561,7 @@ get_uid (struct path * pp)
                        len = get_vpd_uid(pp);
                        origin = "sysfs";
                        pp->uid_attribute = NULL;
-                       if (len < 0) {
+                       if (len < 0 && path_state == PATH_UP) {
                                condlog(1, "%s: failed to get sysfs uid: %s",
                                        pp->dev, strerror(-len));
                                len = get_vpd_sgio(pp->fd, 0x83, pp->wwid,
@@ -1590,6 +1599,16 @@ pathinfo (struct path *pp, vector hwtable, int mask)
        condlog(3, "%s: mask = 0x%x", pp->dev, mask);
 
        /*
+        * Sanity check: we need the device number to
+        * avoid inconsistent information in
+        * find_path_by_dev()/find_path_by_devt()
+        */
+       if (!strlen(pp->dev_t) && !(mask & DI_SYSFS)) {
+               condlog(1, "%s: empty device number", pp->dev);
+               mask |= DI_SYSFS;
+       }
+
+       /*
         * fetch info available in sysfs
         */
        if (mask & DI_SYSFS && sysfs_pathinfo(pp))
@@ -1652,7 +1671,7 @@ pathinfo (struct path *pp, vector hwtable, int mask)
        }
 
        if ((mask & DI_WWID) && !strlen(pp->wwid)) {
-               get_uid(pp);
+               get_uid(pp, path_state);
                if (!strlen(pp->wwid)) {
                        pp->initialized = INIT_MISSING_UDEV;
                        pp->tick = conf->retrigger_delay;
index 2209b2d..289be89 100644 (file)
@@ -320,14 +320,23 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp)
                FREE(word);
 
                for (j = 0; j < num_paths; j++) {
+                       char devname[FILE_NAME_SIZE];
+
                        pp = NULL;
                        p += get_word(p, &word);
 
                        if (!word)
                                goto out;
 
+                       if (devt2devname(devname, FILE_NAME_SIZE, word)) {
+                               condlog(2, "%s: cannot find block device",
+                                       word);
+                               FREE(word);
+                               continue;
+                       }
+
                        if (pathvec)
-                               pp = find_path_by_devt(pathvec, word);
+                               pp = find_path_by_dev(pathvec, devname);
 
                        if (!pp) {
                                pp = alloc_path();
@@ -336,10 +345,17 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp)
                                        goto out1;
 
                                strncpy(pp->dev_t, word, BLK_DEV_SIZE);
-
+                               strncpy(pp->dev, devname, FILE_NAME_SIZE);
+                               if (strlen(mpp->wwid)) {
+                                       strncpy(pp->wwid, mpp->wwid, WWID_SIZE);
+                               }
                                /* Only call this in multipath client mode */
                                if (!conf->daemon && store_path(pathvec, pp))
                                        goto out1;
+                       } else {
+                               if (!strlen(pp->wwid) &&
+                                   strlen(mpp->wwid))
+                                       strncpy(pp->wwid, mpp->wwid, WWID_SIZE);
                        }
                        FREE(word);
 
index a4ae053..d05791d 100644 (file)
@@ -175,6 +175,21 @@ static struct hwentry default_hw[] = {
                .prio_name     = PRIO_ALUA,
                .prio_args     = NULL,
        },
+       {
+               /* HP MSA 1040/2040 product family */
+               .vendor        = "HP",
+               .product       = "MSA (1|2)040 SA(N|S)",
+               .features      = DEFAULT_FEATURES,
+               .hwhandler     = DEFAULT_HWHANDLER,
+               .pgpolicy      = GROUP_BY_PRIO,
+               .pgfailback    = -FAILBACK_IMMEDIATE,
+               .rr_weight     = RR_WEIGHT_NONE,
+               .no_path_retry = 18,
+               .minio         = 100,
+               .checker_name  = TUR,
+               .prio_name     = PRIO_ALUA,
+               .prio_args     = NULL,
+       },
 
        {
                /* HP SVSP */
@@ -1141,6 +1156,20 @@ static struct hwentry default_hw[] = {
                .prio_args     = NULL,
        },
        {
+               .vendor        = "(LIO-ORG|SUSE)",
+               .product       = "RBD",
+               .features      = DEFAULT_FEATURES,
+               .hwhandler     = "1 alua",
+               .pgpolicy      = GROUP_BY_PRIO,
+               .pgfailback    = -FAILBACK_IMMEDIATE,
+               .rr_weight     = RR_WEIGHT_NONE,
+               .no_path_retry = 12,
+               .checker_name  = TUR,
+               .minio         = 100,
+               .prio_name     = PRIO_ALUA,
+               .prio_args     = NULL,
+       },
+       {
                .vendor        = "DataCore",
                .product       = "SANmelody",
                .features      = DEFAULT_FEATURES,
index 04ef78d..97af0f4 100644 (file)
@@ -21,11 +21,11 @@ struct mutex_lock {
        a.depth--; pthread_mutex_unlock(a.mutex)
 #define lock_cleanup_pop(a) \
                fprintf(stderr, "%s:%s(%i) unlock %p depth: %d (%ld)\n", __FILE__, __FUNCTION__, __LINE__, a.mutex, a.depth, pthread_self()); \
-       pthread_cleanup_pop(1);
+       pthread_cleanup_pop(1)
 #else
 #define lock(a) a.depth++; pthread_mutex_lock(a.mutex)
 #define unlock(a) a.depth--; pthread_mutex_unlock(a.mutex)
-#define lock_cleanup_pop(a) pthread_cleanup_pop(1);
+#define lock_cleanup_pop(a) pthread_cleanup_pop(1)
 #endif
 
 void cleanup_lock (void * data);
index 76bda93..7fec6e9 100644 (file)
@@ -174,12 +174,14 @@ snprint_queueing (char * buff, size_t len, struct multipath * mpp)
        else if (mpp->no_path_retry == NO_PATH_RETRY_UNDEF)
                return snprintf(buff, len, "-");
        else if (mpp->no_path_retry > 0) {
-               if (mpp->retry_tick)
+               if (mpp->retry_tick > 0)
                        return snprintf(buff, len, "%i sec",
                                        mpp->retry_tick);
-               else
+               else if (mpp->retry_tick == 0 && mpp->nr_active > 0)
                        return snprintf(buff, len, "%i chk",
                                        mpp->no_path_retry);
+               else
+                       return snprintf(buff, len, "off");
        }
        return 0;
 }
index 0538327..502d98e 100644 (file)
@@ -94,6 +94,7 @@ alloc_path (void)
                pp->sg_id.channel = -1;
                pp->sg_id.scsi_id = -1;
                pp->sg_id.lun = -1;
+               pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
                pp->fd = -1;
                pp->priority = PRIO_UNDEF;
        }
@@ -282,6 +283,20 @@ free_multipathvec (vector mpvec, enum free_path_mode free_paths)
 int
 store_path (vector pathvec, struct path * pp)
 {
+       int err = 0;
+
+       if (!strlen(pp->dev_t)) {
+               condlog(2, "%s: Empty device number", pp->dev);
+               err++;
+       }
+       if (!strlen(pp->dev)) {
+               condlog(2, "%s: Empty device name", pp->dev_t);
+               err++;
+       }
+
+       if (err > 1)
+               return 1;
+
        if (!vector_alloc_slot(pathvec))
                return 1;
 
@@ -403,7 +418,7 @@ find_path_by_dev (vector pathvec, char * dev)
                if (!strcmp(pp->dev, dev))
                        return pp;
 
-       condlog(3, "%s: not found in pathvec", dev);
+       condlog(4, "%s: dev not found in pathvec", dev);
        return NULL;
 }
 
@@ -420,7 +435,7 @@ find_path_by_devt (vector pathvec, char * dev_t)
                if (!strcmp(pp->dev_t, dev_t))
                        return pp;
 
-       condlog(3, "%s: not found in pathvec", dev_t);
+       condlog(4, "%s: dev_t not found in pathvec", dev_t);
        return NULL;
 }
 
index d9a731a..7d46d42 100644 (file)
@@ -46,7 +46,7 @@ update_mpp_paths(struct multipath * mpp, vector pathvec)
 }
 
 extern int
-adopt_paths (vector pathvec, struct multipath * mpp, int get_info)
+adopt_paths (vector pathvec, struct multipath * mpp)
 {
        int i;
        struct path * pp;
@@ -69,8 +69,8 @@ adopt_paths (vector pathvec, struct multipath * mpp, int get_info)
                        if (!find_path_by_dev(mpp->paths, pp->dev) &&
                            store_path(mpp->paths, pp))
                                        return 1;
-                       if (get_info && pathinfo(pp, conf->hwtable,
-                                                DI_PRIO | DI_CHECKER))
+                       if (pathinfo(pp, conf->hwtable,
+                                    DI_PRIO | DI_CHECKER))
                                return 1;
                }
        }
@@ -422,7 +422,7 @@ add_map_without_path (struct vectors * vecs, char * alias)
        if (setup_multipath(vecs, mpp))
                return NULL; /* mpp freed in setup_multipath */
 
-       if (adopt_paths(vecs->pathvec, mpp, 1))
+       if (adopt_paths(vecs->pathvec, mpp))
                goto out;
 
        if (!vector_alloc_slot(vecs->mpvec))
@@ -474,7 +474,7 @@ add_map_with_path (struct vectors * vecs,
                goto out;
        mpp->size = pp->size;
 
-       if (adopt_paths(vecs->pathvec, mpp, 1))
+       if (adopt_paths(vecs->pathvec, mpp))
                goto out;
 
        if (add_vec) {
index eb8e672..2e06beb 100644 (file)
@@ -15,7 +15,7 @@ struct vectors {
 
 void set_no_path_retry(struct multipath *mpp);
 
-int adopt_paths (vector pathvec, struct multipath * mpp, int get_info);
+int adopt_paths (vector pathvec, struct multipath * mpp);
 void orphan_paths (vector pathvec, struct multipath * mpp);
 void orphan_path (struct path * pp, const char *reason);
 
index 478c6ce..fbe9c44 100644 (file)
@@ -529,8 +529,6 @@ int uevent_listen(struct udev *udev)
        }
 
        pthread_sigmask(SIG_SETMASK, NULL, &mask);
-       sigdelset(&mask, SIGHUP);
-       sigdelset(&mask, SIGUSR1);
        events = 0;
        while (1) {
                struct uevent *uev;
@@ -561,9 +559,11 @@ int uevent_listen(struct udev *udev)
                        continue;
                }
                if (fdcount < 0) {
-                       if (errno != EINTR)
-                               condlog(0, "error receiving "
-                                       "uevent message: %m");
+                       if (errno == EINTR)
+                               continue;
+
+                       condlog(0, "error receiving "
+                               "uevent message: %m");
                        err = -errno;
                        break;
                }
index d8c5e6e..afad174 100644 (file)
@@ -20,8 +20,8 @@
 #ifndef _VERSION_H
 #define _VERSION_H
 
-#define VERSION_CODE 0x000600
-#define DATE_CODE    0x120410
+#define VERSION_CODE 0x000601
+#define DATE_CODE    0x050a10
 
 #define PROG    "multipath-tools"
 
diff --git a/multipath.conf.annotated b/multipath.conf.annotated
deleted file mode 100644 (file)
index 0be034d..0000000
+++ /dev/null
@@ -1,749 +0,0 @@
-##
-## This is a template multipath-tools configuration file
-## Uncomment the lines relevent to your environment
-##
-#
-##
-## name  : defaults
-## desc  : multipath-tools default settings
-##
-#defaults {
-#      #
-#      # name    : polling_interval
-#      # scope   : multipathd
-#      # desc    : interval between two path checks in seconds. For
-#      #           properly functioning paths, the interval between checks
-#      #           will gradually increase to (4 * polling_interval).
-#      # values  : n > 0
-#      # default : 5
-#      #
-#      polling_interval 10
-#
-#      #
-#      # name    : path_selector
-#      # scope   : multipath & multipathd
-#      # desc    : the default path selector algorithm to use
-#      #           these algorithms are offered by the kernel multipath target
-#      # values  : "round-robin 0"  = Loop through every path in the path group,
-#      #                              sending the same amount of IO to each.
-#      #           "queue-length 0" = Send the next bunch of IO down the path
-#      #                              with the least amount of outstanding IO.
-#      #           "service-time 0" = Choose the path for the next bunch of IO
-#      #                              based on the amount of outstanding IO to
-#      #                              the path and its relative throughput.
-#      # default : "service-time 0"
-#      #
-#      path_selector   "service-time 0"
-#
-#      #
-#      # name    : path_grouping_policy
-#      # scope   : multipath & multipathd
-#      # desc    : the default path grouping policy to apply to unspecified
-#      #           multipaths
-#      # values  : failover           = 1 path per priority group
-#      #           multibus           = all valid paths in 1 priority group
-#      #           group_by_serial    = 1 priority group per detected serial
-#      #                                number
-#      #           group_by_prio      = 1 priority group per path priority
-#      #                                value
-#      #           group_by_node_name = 1 priority group per target node name
-#      # default : failover
-#      #
-#      path_grouping_policy    multibus
-#
-#      #
-#      # name    : uid_attribute
-#      # scope   : multipath & multipathd
-#      # desc    : the default udev attribute from which the path
-#      #           identifier should be generated.
-#      # default : ID_SERIAL
-#      #
-#      uid_attribute   "ID_SERIAL"
-#
-#      #
-#      # name    : getuid_callout
-#      # scope   : multipath & multipathd
-#      # desc    : the default program and args to callout to obtain a unique 
-#      #           path identifier. This parameter is deprecated.
-#      #           This parameter is deprecated, superseded by uid_attribute
-#      # default : /lib/udev/scsi_id --whitelisted --device=/dev/%n
-#      #
-#      getuid_callout  "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
-#
-#      #
-#      # name    : prio
-#      # scope   : multipath & multipathd
-#      # desc    : the default function to call to obtain a path 
-#      #           priority value. The ALUA bits in SPC-3 provide an
-#      #           exploitable prio value for example.
-#      # default : const
-#      #
-#      prio    "alua"
-#
-#      #
-#      # name    : prio_args
-#      # scope   : multipath & multipathd
-#      # desc    : The arguments string passed to the prio function
-#      #           Most prio functions do not need arguments. The
-#      #           datacore prioritizer need one.
-#      # default : (null)
-#      #
-#      prio_args       "timeout=1000 preferredsds=foo"
-#
-#      #
-#      # name    : features
-#      # scope   : multipath & multipathd
-#      # desc    : The default extra features of multipath devices.
-#      #           Syntax is "num[ feature_0 feature_1 ...]", where `num' is the
-#      #           number of features in the following (possibly empty) list of
-#      #           features.
-#      # values  : queue_if_no_path = Queue IO if no path is active; consider
-#      #                              using the `no_path_retry' keyword instead.
-#      #           no_partitions    = Disable automatic partitions generation via
-#      #                              kpartx.
-#      # default : "0"
-#      #
-#      features        "0"
-#      features        "1 queue_if_no_path"
-#      features        "1 no_partitions"
-#      features        "2 queue_if_no_path no_partitions"
-#
-#      #
-#      # name    : path_checker, checker
-#      # scope   : multipath & multipathd
-#      # desc    : the default method used to determine the paths' state
-#      # values  : readsector0|tur|emc_clariion|hp_sw|directio|rdac|cciss_tur
-#      # default : directio
-#      #
-#      path_checker    directio
-#
-#      #
-#      # name    : rr_min_io
-#      # scope   : multipath & multipathd
-#      # desc    : the number of IO to route to a path before switching
-#      #           to the next in the same path group for the bio-based
-#      #           multipath implementation. This parameter is used for
-#      #           kernels version up to 2.6.31; newer kernel version
-#      #           use the parameter rr_min_io_rq
-#      # default : 1000
-#      #
-#      rr_min_io       1000
-#
-#      #
-#      # name    : rr_min_io_rq
-#      # scope   : multipath & multipathd
-#      # desc    : the number of IO to route to a path before switching
-#      #           to the next in the same path group for the request-based
-#      #           multipath implementation. This parameter is used for
-#      #           kernels versions later than 2.6.31.
-#      # default : 1
-#      #
-#      rr_min_io_rq    1
-#
-#      #
-#      # name    : flush_on_last_del
-#      # scope   : multipathd
-#      # desc    : If set to "yes", multipathd will disable queueing when the
-#      #           last path to a device has been deleted.
-#      # values  : yes|no
-#      # default : no
-#      #
-#      flush_on_last_del       yes
-#
-#      #
-#      # name    : max_fds
-#      # scope   : multipathd
-#      # desc    : Sets the maximum number of open file descriptors for the
-#      #           multipathd process.
-#      # values  : max|n > 0
-#      # default : None
-#      #
-#      max_fds         8192
-#
-#      #
-#      # name    : rr_weight
-#      # scope   : multipath & multipathd
-#      # desc    : if set to priorities the multipath configurator will assign
-#      #           path weights as "path prio * rr_min_io"
-#      # values  : priorities|uniform
-#      # default : uniform
-#      #
-#      rr_weight       priorities
-#
-#      #
-#      # name    : failback
-#      # scope   : multipathd
-#      # desc    : tell the daemon to manage path group failback, or not to.
-#      #           0 means immediate failback, values >0 means deffered
-#      #           failback expressed in seconds.
-#      # values  : manual|immediate|n > 0
-#      # default : manual
-#      #
-#      failback        immediate
-#
-#      #
-#      # name    : no_path_retry
-#      # scope   : multipath & multipathd
-#      # desc    : tell the number of retries until disable queueing, or
-#      #           "fail" means immediate failure (no queueing),
-#      #           "queue" means never stop queueing
-#      # values  : queue|fail|n (>0)
-#      # default : (null)
-#      #
-#      no_path_retry  queue
-#
-#      #
-#      # name    : queue_without_daemon
-#      # scope   : multipathd
-#      # desc    : If set to "no", multipathd will disable queueing for all
-#      #           devices when it is shut down.
-#      # values  : yes|no
-#      # default : yes
-#      queue_without_daemon    no
-#
-#      #
-#      # name    : user_friendly_names
-#      # scope   : multipath & multipathd
-#      # desc    : If set to "yes", using the bindings file
-#      #           /etc/multipath/bindings to assign a persistent and
-#      #           unique alias to the multipath, in the form of mpath<n>.
-#      #           If set to "no" use the WWID as the alias. In either case
-#      #           this be will be overriden by any specific aliases in this
-#      #           file.
-#      # values  : yes|no
-#      # default : no
-#      user_friendly_names no
-#
-#      #
-#      # name    : mode
-#      # scope   : multipath & multipathd
-#      # desc    : The mode to use for the multipath device nodes, in octal.
-#      # values  : 0000 - 0777
-#      # default : determined by the process
-#      mode 0644
-#
-#      #
-#      # name    : uid
-#      # scope   : multipath & multipathd
-#      # desc    : The user id to use for the multipath device nodes. You
-#      #           may use either the numeric or symbolic uid
-#      # values  : <user_id>
-#      # default : determined by the process
-#      uid 0
-#
-#      #
-#      # name    : gid
-#      # scope   : multipath & multipathd
-#      # desc    : The group id to user for the multipath device nodes. You
-#      #           may use either the numeric or symbolic gid
-#      # values  : <group_id>
-#      # default : determined by the process
-#      gid disk
-#
-#      #
-#      # name    : checker_timeout
-#      # scope   : multipath & multipathd
-#      # desc    : The timeout to use for path checkers and prioritizers
-#      #           that issue scsi commands with an explicit timeout, in
-#      #           seconds.
-#      # values  : n > 0
-#      # default : taken from /sys/block/sd<x>/device/timeout
-#      checker_timeout 60
-#
-#      #
-#      # name    : fast_io_fail_tmo
-#      # scope   : multipath & multipathd
-#      # desc    : The number of seconds the scsi layer will wait after a
-#      #           problem has been detected on a FC remote port before failing
-#      #           IO to devices on that remote port.
-#      # values  : off | n >= 0 (smaller than dev_loss_tmo)
-#      # default : determined by the OS
-#      fast_io_fail_tmo 5
-#
-#      #
-#      # name    : dev_loss_tmo
-#      # scope   : multipath & multipathd
-#      # desc    : The number of seconds the scsi layer will wait after a
-#      #           problem has been detected on a FC remote port before
-#      #           removing it from the system.
-#      # values  : infinity | n > 0
-#      # default : determined by the OS
-#      dev_loss_tmo 600
-#
-#      #
-#      # 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"
-#
-#      #
-#      # name    : wwids_file
-#      # scope   : multipath
-#      # desc    : The location of the wwids file multipath uses to
-#       #           keep track of the created multipath devices.
-#      # values  : <full_pathname>
-#      # default : "/var/lib/multipath/wwids"
-#      wwids_file "/etc/multipath/wwids"
-#
-#      #
-#      # name    : reservation_key
-#      # scope   : multipath
-#      # desc    : Service action reservation key used by mpathpersist.
-#      # values  : <key>
-#      # default : (null)
-#      reservation_key "mpathkey"
-#
-#      #
-#      # name    : force_sync
-#      # scope   : multipathd
-#      # desc    : If set to yes, multipath will run all of the checkers in
-#      #           sync mode, even if the checker has an async mode.
-#      # values  : yes|no
-#      # default : no
-#      force_sync yes
-#
-#      #
-#      # name    : config_dir
-#      # scope   : multipath & multipathd
-#      # desc    : If not set to an empty string, multipath will search
-#      #           this directory alphabetically for files ending in ".conf"
-#      #           and it will read configuration information from these
-#      #           files, just as if it was in /etc/multipath.conf
-#      # values  : "" or a fully qualified pathname
-#      # default : "/etc/multipath/conf.d"
-#
-#      #
-#      # name    : delay_watch_checks
-#      # scope   : multipathd
-#      # desc    : If set to a value greater than 0, multipathd will watch
-#      #           paths that have recently become valid for this many
-#      #           checks.  If they fail again while they are being watched,
-#      #           when they next become valid, they will not be used until
-#      #           they have stayed up for delay_wait_checks checks.
-#      # values  : no|<n> > 0
-#      # default : no
-#      delay_watch_checks 12
-#
-#      #
-#      # name    : delay_wait_checks
-#      # scope   : multipathd
-#      # desc    : If set to a value greater than 0, when a device that has
-#      #           recently come back online fails again within
-#      #           delay_watch_checks checks, the next time it comes back
-#      #           online, it will marked and delayed, and not used until
-#      #           it has passed delay_wait_checks checks.
-#      # values  : no|<n> > 0
-#      # default : no
-#      delay_wait_checks 12
-#}
-#      
-##
-## name    : blacklist
-## scope   : multipath & multipathd
-## desc    : list of device names to discard as not multipath candidates
-##           Devices can be identified by their device node name "devnode",
-##           their WWID "wwid", or their vender and product strings
-##           "device"
-## default : fd, hd, md, dm, sr, scd, st, ram, raw, loop, dcssblk
-##
-#blacklist {
-#       wwid 26353900f02796769
-#      devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
-#      devnode "^hd[a-z]"
-#      devnode "^dcssblk[0-9]*"
-#       device {
-#               vendor DEC.*
-#               product MSA[15]00
-#       }
-#}
-##
-## name    : blacklist_exceptions
-## scope   : multipath & multipathd
-## desc    : list of device names to be treated as multipath candidates
-##           even if they are on the blacklist.
-##           Note: blacklist exceptions are only valid in the same class.
-##           It is not possible to blacklist devices using the devnode keyword
-##           and to exclude some devices of them using the wwid keyword.
-## default : -
-##
-#blacklist_exceptions {
-#       devnode "^dasd[c-d]+[0-9]*"
-#       wwid    "IBM.75000000092461.4d00.34"
-#       wwid    "IBM.75000000092461.4d00.35"
-#       wwid    "IBM.75000000092461.4d00.36"
-#}
-#
-##
-## name    : multipaths
-## scope   : multipath & multipathd
-## desc    : list of multipaths finest-grained settings
-##
-#multipaths {
-#      #
-#      # name  : multipath
-#      # scope : multipath & multipathd
-#      # desc  : container for settings that apply to one specific multipath
-#      #
-#      multipath {
-#              #
-#              # name  : wwid
-#              # scope : multipath & multipathd
-#              # desc  : index of the container
-#              #
-#              wwid                    3600508b4000156d700012000000b0000
-#
-#              #
-#              # name    : alias
-#              # scope   : multipath & multipathd
-#              # desc    : symbolic name for the multipath. If you are using
-#              #           user_friendly_names, do not set the alias to
-#              #           mpath<n>. This may conflict with an automatically
-#              #           assigned user friendly name, and give you
-#              #           incorrect device node names.
-#              #
-#              alias                   yellow
-#
-#              #
-#              # name    : path_grouping_policy
-#              # scope   : multipath & multipathd
-#              # desc    : path grouping policy to apply to this multipath
-#              # values  : failover, multibus, group_by_serial
-#              # values  : failover           = 1 path per priority group
-#              #           multibus           = all valid paths in 1 priority
-#              #                                group
-#              #           group_by_serial    = 1 priority group per detected
-#              #                                serial number
-#              #           group_by_prio      = 1 priority group per path
-#              #                                priority value
-#              #           group_by_node_name = 1 priority group per target
-#              #                                node name
-#              #
-#              path_grouping_policy    failover
-#
-#              #
-#              # name    : path_selector
-#              # scope   : multipath & multipathd
-#              # desc    : the path selector algorithm to use for this mpath
-#              #           these algo are offered by the kernel mpath target
-#              # values  : "round-robin 0"
-#              #
-#              path_selector           "round-robin 0"
-#
-#              #
-#              # name    : failback
-#              # scope   : multipathd
-#              # desc    : tell the daemon to manage path group failback, or
-#              #           not to. 0 means immediate failback, values >0 means
-#              #           deffered failback expressed in seconds.
-#              # values  : manual|immediate|n > 0
-#              #
-#              failback                manual
-#
-#              #
-#              # name    : rr_weight
-#              # scope   : multipath & multipathd
-#              # desc    : if set to priorities the multipath configurator will
-#              #           assign path weights as "path prio * rr_min_io"
-#              # values  : priorities|uniform
-#              #
-#              rr_weight       priorities
-#
-#              #
-#              # name    : no_path_retry
-#              # scope   : multipath & multipathd
-#              # desc    : tell the number of retries until disable queueing,
-#              #           or "fail" means immediate failure (no queueing),
-#              #           "queue" means never stop queueing
-#              # values  : queue|fail|n (>0)
-#              #
-#              no_path_retry  queue
-#
-#              #
-#              # name    : rr_min_io
-#              # scope   : multipath & multipathd
-#              # desc    : the number of IO to route to a path before switching
-#              #           to the next in the same path group
-#              #
-#              rr_min_io       100
-#
-#              #
-#              # name    : flush_on_last_del
-#              # scope   : multipathd
-#              # desc    : If set to "yes", multipathd will disable queueing
-#              #           when the last path to a device has been deleted.
-#              # values  : yes|no
-#              # default : no
-#              #
-#              flush_on_last_del       yes
-#
-#              #
-#              # name    : mode
-#              # scope   : multipath & multipathd
-#              # desc    : The mode to use for the multipath device nodes, in
-#              #           octal.
-#              # values  : 0000 - 0777
-#              # default : determined by the process
-#              mode 0644
-#
-#              #
-#              # name    : uid
-#              # scope   : multipath & multipathd
-#              # desc    : The user id to use for the multipath device nodes.
-#              #           You may use either the numeric or symbolic uid
-#              # values  : <user_id>
-#              # default : determined by the process
-#              uid 0
-#
-#              #
-#              # name    : gid
-#              # scope   : multipath & multipathd
-#              # desc    : The group id to user for the multipath device nodes.
-#              #           You may use either the numeric or symbolic gid
-#              # values  : <group_id>
-#              # default : determined by the process
-#              gid 0
-#
-#              #
-#              # name    : delay_watch_checks
-#              # scope   : multipathd
-#              # desc    : If set to a value greater than 0, multipathd will
-#              #           watch paths that have recently become valid for
-#              #           this many checks.  If they fail again while they
-#              #           are being watched, when they next become valid,
-#              #           they will not be used until they have stayed up for
-#              #           delay_wait_checks checks.
-#              # values  : no|<n> > 0
-#              delay_watch_checks 12
-#
-#              #
-#              # name    : delay_wait_checks
-#              # scope   : multipathd
-#              # desc    : If set to a value greater than 0, when a device
-#              #           that has recently come back online fails again
-#              #           within delay_watch_checks checks, the next time it
-#              #           comes online, it will marked and delayed, and not
-#              #           used until it has passed delay_wait_checks checks.
-#              # values  : no|<n> > 0
-#              delay_wait_checks 12
-#      }
-#      multipath {
-#              wwid    1DEC_____321816758474
-#              alias   red
-#              rr_weight               priorities
-#      }
-#}
-#
-##
-## name  : devices
-## scope : multipath & multipathd
-## desc  : list of per storage controller settings
-##       overrides default settings (device_maps block)
-##        overriden by per multipath settings (multipaths block)
-##       and the overrides settings (overrides block)
-##
-#devices {
-#      #
-#      # name  : device
-#      # scope : multipath & multipathd
-#      # desc  : settings for this specific storage controller
-#      #
-#      device {
-#              #
-#              # name  : vendor, product
-#              # scope : multipath & multipathd
-#              # desc  : index for the block
-#              #
-#              vendor                  "COMPAQ  "
-#              product                 "HSV110 (C)COMPAQ"
-#
-#              #
-#              # name    : path_grouping_policy
-#              # scope   : multipath & multipathd
-#              # desc    : path grouping policy to apply to this multipath
-#              # values  : failover, multibus, group_by_serial
-#              # values  : failover           = 1 path per priority group
-#              #           multibus           = all valid paths in 1 priority
-#              #                                group
-#              #           group_by_serial    = 1 priority group per detected
-#              #                                serial number
-#              #           group_by_prio      = 1 priority group per path
-#              #                                priority value
-#              #           group_by_node_name = 1 priority group per target
-#              #                                node name
-#              #
-#              path_grouping_policy    failover
-#
-#              #
-#              # name    : getuid_callout
-#              # scope   : multipath & multipathd
-#              # desc    : the program and args to callout to obtain a unique 
-#              #           path identifier. Absolute path required
-#              #
-#              getuid_callout          "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
-#
-#              #
-#              # name    : prio
-#              # scope   : multipath & multipathd
-#              # desc    : the function to call to obtain a path 
-#              #           weight. Weights are summed for each path group to
-#              #           determine the next PG to use case of failure.
-#              # default : no callout, all paths equals
-#              #
-#              prio          "hp_sw"
-#
-#              #
-#              # name    : prio_args
-#              # scope   : multipath & multipathd
-#              # desc    : The arguments string passed to the prio function
-#              #           Most prio functions do not need arguments. The
-#              #           datacore prioritizer need one.
-#              # default : (null)
-#              #
-#              prio_args       "timeout=1000 preferredsds=foo"
-#
-#              # name    : path_checker, checker
-#              # scope   : multipathd & multipathd
-#              # desc    : path checking algorithm to use to check path state
-#              # values  : readsector0|tur|emc_clariion|hp_sw|directio|rdac|
-#              #           cciss_tur
-#              #
-#              path_checker            directio
-#
-#              # as already described
-#              path_selector           "service-time 0"
-#
-#              # as already described
-#              features        "0"
-#
-#              #
-#              # name    : hardware_handler
-#              # scope   : multipath & multipathd
-#              # desc    : If set, it specifies a module that will be used to
-#              #           perform hardware specific actions when switching
-#              #           path groups or handling IO errors
-#              # values  : "0"|"1 emc"
-#              # default : "0"
-#              #
-#              hardware_handler "1 emc"
-#
-#              #
-#              # name    : failback
-#              # scope   : multipathd
-#              # desc    : tell the daemon to manage path group failback, or
-#              #           not to. 0 means immediate failback, values >0 means
-#              #           deffered failback expressed in seconds.
-#              # values  : manual|immediate|n > 0
-#              #
-#              failback                30
-#
-#              #
-#              # name    : rr_weight
-#              # scope   : multipath & multipathd
-#              # desc    : if set to priorities the multipath configurator will
-#              #           assign path weights as "path prio * rr_min_io"
-#              # values  : priorities|uniform
-#              #
-#              rr_weight       priorities
-#
-#              #
-#              # name    : no_path_retry
-#              # scope   : multipath & multipathd
-#              # desc    : tell the number of retries until disable queueing,
-#              #           or "fail" means immediate failure (no queueing),
-#              #           "queue" means never stop queueing
-#              # values  : queue|fail|n (>0)
-#              #
-#              no_path_retry  queue
-#
-#              #
-#              # name    : rr_min_io
-#              # scope   : multipath & multipathd
-#              # desc    : the number of IO to route to a path before switching
-#              #           to the next in the same path group
-#              #
-#              rr_min_io       100
-#
-#              #
-#              # name    : flush_on_last_del
-#              # scope   : multipathd
-#              # desc    : If set to "yes", multipathd will disable queueing
-#              #           when the last path to a device has been deleted.
-#              # values  : yes|no
-#              #
-#              flush_on_last_del       yes
-#
-#              #
-#              # name    : product_blacklist
-#              # scope   : multipath & multipathd
-#              # desc    : product strings to blacklist for this vendor
-#              #
-#              product_blacklist       LUN_Z
-#
-#              #
-#              # name    : fast_io_fail_tmo
-#              # scope   : multipath & multipathd
-#              # desc    : The number of seconds the scsi layer will wait after
-#              #           a problem has been detected on a FC remote port
-#              #           before failing IO to devices on that remote port.
-#              # values  : off | n >= 0 (smaller than dev_loss_tmo)
-#              fast_io_fail_tmo 5
-#
-#              #
-#              # name    : dev_loss_tmo
-#              # scope   : multipath & multipathd
-#              # desc    : The number of seconds the scsi layer will wait after
-#              #           a problem has been detected on a FC remote port
-#              #           before removing it from the system.
-#              # values  : n > 0
-#              dev_loss_tmo 600
-#
-#              #
-#              # name    : delay_watch_checks
-#              # scope   : multipathd
-#              # desc    : If set to a value greater than 0, multipathd will
-#              #           watch paths that have recently become valid for
-#              #           this many checks.  If they fail again while they
-#              #           are being watched, when they next become valid,
-#              #           they will not be used until they have stayed up for
-#              #           delay_wait_checks checks.
-#              # values  : no|<n> > 0
-#              delay_watch_checks 12
-#
-#              #
-#              # name    : delay_wait_checks
-#              # scope   : multipathd
-#              # desc    : If set to a value greater than 0, when a device
-#              #           that has recently come back online fails again
-#              #           within delay_watch_checks checks, the next time it
-#              #           comes online, it will marked and delayed, and not
-#              #           used until it has passed delay_wait_checks checks.
-#              # values  : no|<n> > 0
-#              delay_wait_checks 12
-#
-#      }
-#      device {
-#              vendor                  "COMPAQ  "
-#              product                 "MSA1000         "
-#              path_grouping_policy    multibus
-#              path_checker            tur
-#              rr_weight               priorities
-#      }
-#}
-#
-##
-## name  : devices
-## scope : multipath & multipathd
-## desc  : list of settings to override all hadware settings for all devices
-##       overrides default settings (device_maps block)
-##       and per device type settings (devices block)
-##        overriden by per multipath settings (multipaths block)
-##
-#      attributes and values are identical to the device block
-#
-#overrides {
-#      dev_loss_tmo            60
-#      no_path_retry           fail
-#}
diff --git a/multipath.conf.defaults b/multipath.conf.defaults
deleted file mode 100644 (file)
index a4e68b1..0000000
+++ /dev/null
@@ -1,959 +0,0 @@
-# These are the compiled in default settings.  They will be used unless you
-# overwrite these values in your config file.
-#defaults {
-#      verbosity 2
-#      polling_interval 5
-#      path_selector "service-time 0"
-#      path_grouping_policy "failover"
-#      uid_attribute "ID_SERIAL"
-#      prio "const"
-#      prio_args ""
-#      features "0"
-#      path_checker "directio"
-#      alias_prefix "mpath"
-#      failback "manual"
-#      rr_min_io 1000
-#      rr_min_io_rq 1
-#      max_fds "max"
-#      rr_weight "uniform"
-#      queue_without_daemon "yes"
-#      flush_on_last_del "no"
-#      user_friendly_names "no"
-#      fast_io_fail_tmo 5
-#      bindings_file "/etc/multipath/bindings"
-#      wwids_file /etc/multipath/wwids
-#      log_checker_err always
-#      retain_attached_hw_handler no
-#      detect_prio no
-#      config_dir "/etc/multipath/conf.d"
-#      delay_watch_checks no
-#      delay_wait_checks no
-#      missing_uev_wait_timeout 30
-#}
-#blacklist {
-#      devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
-#      devnode "^(td|hd|vd)[a-z]"
-#      devnode "^dcssblk[0-9]*"
-#      devnode "^nvme.*"
-#      device {
-#              vendor "DGC"
-#              product "LUNZ"
-#      }
-#      device {
-#              vendor "EMC"
-#              product "LUNZ"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "Universal Xport"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "S/390.*"
-#      }
-#      device {
-#              vendor "DELL"
-#              product "Universal Xport"
-#      }
-#      device {
-#              vendor "SGI"
-#              product "Universal Xport"
-#      }
-#      device {
-#              vendor "STK"
-#              product "Universal Xport"
-#      }
-#      device {
-#              vendor "SUN"
-#              product "Universal Xport"
-#      }
-#      device {
-#              vendor "(LSI|ENGENIO)"
-#              product "Universal Xport"
-#      }
-#}
-#blacklist_exceptions {
-#      property "(SCSI_IDENT_.*|ID_WWN)"
-#}
-#devices {
-#      device {
-#              vendor "COMPELNT"
-#              product "Compellent Vol"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "APPLE*"
-#              product "Xserve RAID "
-#              path_grouping_policy "multibus"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "3PARdata"
-#              product "VV"
-#              path_grouping_policy "multibus"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "DEC"
-#              product "HSG80"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "hp_sw"
-#              features "1 queue_if_no_path"
-#              hardware_handler "1 hp_sw"
-#              prio "hp_sw"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "HP"
-#              product "A6189A"
-#              path_grouping_policy "multibus"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#              no_path_retry 12
-#      }
-#      device {
-#              vendor "(COMPAQ|HP)"
-#              product "(MSA|HSV)1.0.*"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "hp_sw"
-#              features "1 queue_if_no_path"
-#              hardware_handler "1 hp_sw"
-#              prio "hp_sw"
-#              rr_weight "uniform"
-#              no_path_retry 12
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "(COMPAQ|HP)"
-#              product "MSA VOLUME"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 12
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "(COMPAQ|HP)"
-#              product "HSV1[01]1|HSV2[01]0|HSV3[046]0|HSV4[05]0"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 12
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "HP"
-#              product "MSA2[02]12fc|MSA2012i"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 18
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "HP"
-#              product "MSA2012sa|MSA23(12|24)(fc|i|sa)|MSA2000s VOLUME"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 18
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "HP"
-#              product "HSVX700"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "1 alua"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 12
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "HP"
-#              product "LOGICAL VOLUME.*"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#              no_path_retry 12
-#      }
-#      device {
-#              vendor "HP"
-#              product "P2000 G3 FC|P2000G3 FC/iSCSI|P2000 G3 SAS|P2000 G3 iSCSI"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 18
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "DDN"
-#              product "SAN DataDirector"
-#              path_grouping_policy "multibus"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "EMC"
-#              product "SYMMETRIX"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#              no_path_retry 6
-#      }
-#      device {
-#              vendor "DGC"
-#              product ".*"
-#              product_blacklist "LUNZ"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "emc_clariion"
-#              features "1 queue_if_no_path"
-#              hardware_handler "1 emc"
-#              prio "emc"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 60
-#              retain_attached_hw_handler yes
-#              detect_prio yes
-#      }
-#      device {
-#              vendor "EMC"
-#              product "Invista"
-#              product_blacklist "LUNZ"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#              no_path_retry 5
-#      }
-#      device {
-#              vendor "FSC"
-#              product "CentricStor"
-#              path_grouping_policy "group_by_serial"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "FUJITSU"
-#              product "ETERNUS_DX(L|M|400|8000)"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 10
-#      }
-#      device {
-#              vendor "(HITACHI|HP)"
-#              product "OPEN-.*"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "HITACHI"
-#              product "DF.*"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "hds"
-#              failback "immediate"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "ProFibre 4000R"
-#              path_grouping_policy "multibus"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1722-600"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "1 queue_if_no_path"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 300
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1724"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "1 queue_if_no_path"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 300
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1726"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "1 queue_if_no_path"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 300
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1742"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1745|^1746"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 15
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1814"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1815"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1818"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^3526"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^3542"
-#              path_grouping_policy "group_by_serial"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^2105800"
-#              path_grouping_policy "group_by_serial"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^2105F20"
-#              path_grouping_policy "group_by_serial"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^1750500"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^2107900"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^2145"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "S/390 DASD ECKD"
-#              product_blacklist "S/390.*"
-#              path_grouping_policy "multibus"
-#              uid_attribute "ID_UID"
-#              path_checker "directio"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "S/390 DASD FBA"
-#              product_blacklist "S/390.*"
-#              path_grouping_policy "multibus"
-#              uid_attribute "ID_UID"
-#              path_checker "directio"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "^IPR.*"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "1 alua"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "IBM"
-#              product "1820N00"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "IBM"
-#              product "2810XIV"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "const"
-#              failback 15
-#              rr_weight "uniform"
-#              rr_min_io 15
-#      }
-#      device {
-#              vendor "AIX"
-#              product "VDASD"
-#              path_grouping_policy "multibus"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 60
-#      }
-#      device {
-#              vendor "IBM"
-#              product "3303      NVDISK"
-#              path_grouping_policy "failover"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 60
-#      }
-#      device {
-#              vendor "AIX"
-#              product "NVDISK"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "1 alua"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 60
-#      }
-#      device {
-#              vendor "DELL"
-#              product "MD3000"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 15
-#      }
-#      device {
-#              vendor "DELL"
-#              product "MD3000i"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 15
-#      }
-#      device {
-#              vendor "DELL"
-#              product "MD32xx"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 15
-#      }
-#      device {
-#              vendor "DELL"
-#              product "MD32xxi"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 15
-#      }
-#      device {
-#              vendor "DELL"
-#              product "MD36xxi"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 15
-#      }
-#      device {
-#              vendor "DELL"
-#              product "MD36xxf"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 15
-#      }
-#      device {
-#              vendor "NETAPP"
-#              product "LUN.*"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "3 queue_if_no_path pg_init_retries 50"
-#              hardware_handler "0"
-#              prio "ontap"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              rr_min_io 128
-#              flush_on_last_del "yes"
-#              dev_loss_tmo "infinity"
-#              retain_attached_hw_handler "yes"
-#              detect_prio "yes"
-#      }
-#      device {
-#              vendor "NEXENTA"
-#              product "COMSTAR"
-#              path_grouping_policy "group_by_serial"
-#              path_checker "directio"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "const"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 30
-#              rr_min_io 128
-#      }
-#      device {
-#              vendor "IBM"
-#              product "Nseries.*"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "directio"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "ontap"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              rr_min_io 128
-#      }
-#      device {
-#              vendor "Pillar"
-#              product "Axiom.*"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "alua"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "SGI"
-#              product "TP9[13]00"
-#              path_grouping_policy "multibus"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "SGI"
-#              product "TP9[45]00"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "SGI"
-#              product "IS.*"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 15
-#      }
-#      device {
-#              vendor "NEC"
-#              product "DISK ARRAY"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "1 alua"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "STK"
-#              product "OPENstorage D280"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "SUN"
-#              product "(StorEdge 3510|T4)"
-#              path_grouping_policy "multibus"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "SUN"
-#              product "STK6580_6780"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "EUROLOGC"
-#              product "FC2502"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "directio"
-#              features "0"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#      }
-#      device {
-#              vendor "PIVOT3"
-#              product "RAIGE VOLUME"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              features "1 queue_if_no_path"
-#              hardware_handler "0"
-#              prio "const"
-#              rr_weight "uniform"
-#              rr_min_io 100
-#      }
-#      device {
-#              vendor "SUN"
-#              product "CSM200_R"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "SUN"
-#              product "LCSM100_[IEFS]"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "SUN"
-#              product "SUN_6180"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#              rr_min_io 1000
-#              rr_min_io_rq 1
-#      }
-#      device {
-#              vendor "(NETAPP|LSI|ENGENIO)"
-#              product "INF-01-00"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "2 pg_init_retries 50"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry 30
-#              detect_prio "yes"
-#              retain_attached_hw_handler "yes"
-#      }
-#      device {
-#              vendor "STK"
-#              product "FLEXLINE 380"
-#              product_blacklist "Universal Xport"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "rdac"
-#              features "0"
-#              hardware_handler "1 rdac"
-#              prio "rdac"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "Intel"
-#              product "Multi-Flex"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "1 alua"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "DataCore"
-#              product "SANmelody"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "DataCore"
-#              product "Virtual Disk"
-#              path_grouping_policy "group_by_prio"
-#              path_checker "tur"
-#              features "0"
-#              hardware_handler "0"
-#              prio "alua"
-#              failback "immediate"
-#              rr_weight "uniform"
-#              no_path_retry "queue"
-#      }
-#      device {
-#              vendor "PURE"
-#              path_selector "queue-length 0"
-#              path_grouping_policy "multibus"
-#              path_checker "tur"
-#              fast_io_fail_tmo 10
-#              user_friendly_names "no"
-#              no_path_retry 0
-#              features 0
-#              dev_loss_tmo 60
-#      }
-#}
-#multipaths {
-#}
-#overrides {
-#}
diff --git a/multipath.conf.synthetic b/multipath.conf.synthetic
deleted file mode 100644 (file)
index f7b9b8a..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-##
-## This is a template multipath-tools configuration file
-## Uncomment the lines relevent to your environment
-##
-#defaults {
-#      udev_dir                /dev
-#      polling_interval        10
-#      path_selector           "round-robin 0"
-#      path_grouping_policy    multibus
-#      getuid_callout          "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
-#      prio                    const
-#      path_checker            directio
-#      rr_min_io               100
-#      flush_on_last_del       no
-#      max_fds                 8192
-#      rr_weight               priorities
-#      failback                immediate
-#      no_path_retry           fail
-#      queue_without_daemon    no
-#      user_friendly_names     no
-#      mode                    644
-#      uid                     0
-#      gid                     disk
-#}
-#blacklist {
-#       wwid 26353900f02796769
-#      devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
-#      devnode "^hd[a-z][[0-9]*]"
-#      device {
-#              vendor DEC.*
-#              product MSA[15]00
-#      }
-#}
-#blacklist_exceptions {
-#       devnode "^dasd[c-d]+[0-9]*"
-#       wwid    "IBM.75000000092461.4d00.34"
-#}
-#multipaths {
-#      multipath {
-#              wwid                    3600508b4000156d700012000000b0000
-#              alias                   yellow
-#              path_grouping_policy    multibus
-#              path_selector           "round-robin 0"
-#              failback                manual
-#              rr_weight               priorities
-#              no_path_retry           5
-#              rr_min_io               100
-#      }
-#      multipath {
-#              wwid                    1DEC_____321816758474
-#              alias                   red
-#      }
-#}
-#devices {
-#      device {
-#              vendor                  "COMPAQ  "
-#              product                 "HSV110 (C)COMPAQ"
-#              path_grouping_policy    multibus
-#              getuid_callout          "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
-#              path_checker            directio
-#              path_selector           "round-robin 0"
-#              hardware_handler        "0"
-#              failback                15
-#              rr_weight               priorities
-#              no_path_retry           queue
-#              rr_min_io               100
-#              product_blacklist       LUNZ
-#      }
-#      device {
-#              vendor                  "COMPAQ  "
-#              product                 "MSA1000         "
-#              path_grouping_policy    multibus
-#      }
-#}
-#overrides {
-#      no_path_retry                   fail
-#}
index 2e7076d..5559af3 100644 (file)
@@ -7,11 +7,11 @@ ENV{DM_UUID}!="mpath-?*", GOTO="mpath_end"
 # We'd like to avoid this, especially within udev processing.
 ENV{DM_NR_VALID_PATHS}!="?*", IMPORT{db}="DM_NR_VALID_PATHS"
 ENV{DM_NR_VALID_PATHS}!="0", GOTO="mpath_blkid_end"
-IMPORT{db}="ID_FS_TYPE"
-IMPORT{db}="ID_FS_USAGE"
-IMPORT{db}="ID_FS_UUID"
-IMPORT{db}="ID_FS_UUID_ENC"
-IMPORT{db}="ID_FS_VERSION"
+ENV{ID_FS_TYPE}!="?*", IMPORT{db}="ID_FS_TYPE"
+ENV{ID_FS_USAGE}!="?*", IMPORT{db}="ID_FS_USAGE"
+ENV{ID_FS_UUID}!="?*", IMPORT{db}="ID_FS_UUID"
+ENV{ID_FS_ENC}!="?*", IMPORT{db}="ID_FS_UUID_ENC"
+ENV{ID_FS_VERSION}!="?*", IMPORT{db}="ID_FS_VERSION"
 LABEL="mpath_blkid_end"
 
 # Also skip all foreign rules if no path is available.
index d14a913..c33f689 100644 (file)
@@ -284,7 +284,7 @@ configure (void)
                int failed = get_refwwid(conf->dev, conf->dev_type, pathvec,
                                         &refwwid);
                if (!refwwid) {
-                       condlog(3, "%s: failed to get wwid", conf->dev);
+                       condlog(4, "%s: failed to get wwid", conf->dev);
                        if (failed == 2 && conf->cmd == CMD_VALID_PATH)
                                printf("%s is not a valid multipath device path\n", conf->dev);
                        else
index 0d4df0f..2ff88c4 100644 (file)
@@ -394,7 +394,7 @@ retry interval
 if a number of retries is given with \fIno_path_retry\fR and the
 overall retry interval is longer than the specified \fIdev_loss_tmo\fR value.
 The linux kernel will cap this value to \fI300\fR if \fBfast_io_fail_tmo\fR
-is not set.
+is not set. Default is 600.
 .TP
 .B queue_without_daemon
 If set to
@@ -498,6 +498,20 @@ used until it has passed
 checks. Default is
 .I no
 .TP
+.B strict_timinig
+If set to
+.I yes
+, multipathd will start a new path checker loop after exactly one second,
+so that each path check will occur at exactly
+.I polling_interval
+seconds. On busy systems path checks might take longer than one second;
+here the missing ticks will be accounted for on the next round.
+A warning will be printed if path checks take longer than
+.I polling_interval
+seconds.
+Default is
+.I no
+.TP
 .B uxsock_timeout
 CLI receive timeout in milliseconds. For larger systems CLI commands
 might timeout before the multipathd lock is released and the CLI command
index 6a5c6db..d991cd0 100644 (file)
@@ -1,8 +1,13 @@
 /*
  * Copyright (c) 2005 Christophe Varoqui
  */
+#include <sys/time.h>
+#include <errno.h>
+#include <pthread.h>
 #include <memory.h>
 #include <vector.h>
+#include <structs.h>
+#include <structs_vec.h>
 #include <parser.h>
 #include <util.h>
 #include <version.h>
@@ -99,6 +104,19 @@ set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *))
        if (!h)
                return 1;
        h->fn = fn;
+       h->locked = 1;
+       return 0;
+}
+
+int
+set_unlocked_handler_callback (unsigned long fp,int (*fn)(void *, char **, int *, void *))
+{
+       struct handler * h = find_handler(fp);
+
+       if (!h)
+               return 1;
+       h->fn = fn;
+       h->locked = 0;
        return 0;
 }
 
@@ -224,10 +242,14 @@ find_key (const char * str)
        return foundkw;
 }
 
-#define E_SYNTAX       1
-#define E_NOPARM       2
-#define E_NOMEM                3
-
+/*
+ * get_cmdvec
+ *
+ * returns:
+ * ENOMEM: not enough memory to allocate command
+ * EAGAIN: command not found
+ * EINVAL: argument missing for command
+ */
 static int
 get_cmdvec (char * cmd, vector *v)
 {
@@ -241,13 +263,13 @@ get_cmdvec (char * cmd, vector *v)
 
        strvec = alloc_strvec(cmd);
        if (!strvec)
-               return E_NOMEM;
+               return ENOMEM;
 
        cmdvec = vector_alloc();
 
        if (!cmdvec) {
                free_strvec(strvec);
-               return E_NOMEM;
+               return ENOMEM;
        }
 
        vector_foreach_slot(strvec, buff, i) {
@@ -260,17 +282,17 @@ get_cmdvec (char * cmd, vector *v)
                }
                kw = find_key(buff);
                if (!kw) {
-                       r = E_SYNTAX;
+                       r = EAGAIN;
                        goto out;
                }
                cmdkw = alloc_key();
                if (!cmdkw) {
-                       r = E_NOMEM;
+                       r = ENOMEM;
                        goto out;
                }
                if (!vector_alloc_slot(cmdvec)) {
                        FREE(cmdkw);
-                       r = E_NOMEM;
+                       r = ENOMEM;
                        goto out;
                }
                vector_set_slot(cmdvec, cmdkw);
@@ -280,7 +302,7 @@ get_cmdvec (char * cmd, vector *v)
                        get_param = 1;
        }
        if (get_param) {
-               r = E_NOPARM;
+               r = EINVAL;
                goto out;
        }
        *v = cmdvec;
@@ -340,13 +362,29 @@ genhelp_sprint_aliases (char * reply, int maxlen, vector keys,
 }
 
 static int
-do_genhelp(char *reply, int maxlen) {
+do_genhelp(char *reply, int maxlen, const char *cmd, int error) {
        int len = 0;
        int i, j;
        uint64_t fp;
        struct handler * h;
        struct key * kw;
 
+       switch(error) {
+       case ENOMEM:
+               len += snprintf(reply + len, maxlen - len,
+                               "%s: Not enough memory\n", cmd);
+               break;
+       case EAGAIN:
+               len += snprintf(reply + len, maxlen - len,
+                               "%s: not found\n", cmd);
+               break;
+       case EINVAL:
+               len += snprintf(reply + len, maxlen - len,
+                               "%s: Missing argument\n", cmd);
+               break;
+       }
+       if (len >= maxlen)
+               goto out;
        len += snprintf(reply + len, maxlen - len, VERSION_STRING);
        if (len >= maxlen)
                goto out;
@@ -388,7 +426,7 @@ out:
 
 
 static char *
-genhelp_handler (void)
+genhelp_handler (const char *cmd, int error)
 {
        char * reply;
        char * p = NULL;
@@ -401,7 +439,7 @@ genhelp_handler (void)
                if (!reply)
                        return NULL;
                p = reply;
-               p += do_genhelp(reply, maxlen);
+               p += do_genhelp(reply, maxlen, cmd, error);
                again = ((p - reply) >= maxlen);
                REALLOC_REPLY(reply, again, maxlen);
        }
@@ -409,16 +447,18 @@ genhelp_handler (void)
 }
 
 int
-parse_cmd (char * cmd, char ** reply, int * len, void * data)
+parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout )
 {
        int r;
        struct handler * h;
        vector cmdvec = NULL;
+       struct timespec tmo;
+       struct timeval now;
 
        r = get_cmdvec(cmd, &cmdvec);
 
        if (r) {
-               *reply = genhelp_handler();
+               *reply = genhelp_handler(cmd, r);
                *len = strlen(*reply) + 1;
                return 0;
        }
@@ -426,7 +466,7 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data)
        h = find_handler(fingerprint(cmdvec));
 
        if (!h || !h->fn) {
-               *reply = genhelp_handler();
+               *reply = genhelp_handler(cmd, EINVAL);
                *len = strlen(*reply) + 1;
                free_keys(cmdvec);
                return 0;
@@ -435,7 +475,30 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data)
        /*
         * execute handler
         */
-       r = h->fn(cmdvec, reply, len, data);
+       if (gettimeofday(&now, NULL) == 0) {
+               tmo.tv_sec = now.tv_sec + timeout;
+               tmo.tv_nsec = now.tv_usec * 1000;
+       } else {
+               tmo.tv_sec = 0;
+       }
+       if (h->locked) {
+               struct vectors * vecs = (struct vectors *)data;
+
+               pthread_cleanup_push(cleanup_lock, &vecs->lock);
+               if (tmo.tv_sec) {
+                       vecs->lock.depth++;
+                       r = pthread_mutex_timedlock(vecs->lock.mutex, &tmo);
+               } else {
+                       lock(vecs->lock);
+                       r = 0;
+               }
+               if (r == 0) {
+                       pthread_testcancel();
+                       r = h->fn(cmdvec, reply, len, data);
+               }
+               lock_cleanup_pop(vecs->lock);
+       } else
+               r = h->fn(cmdvec, reply, len, data);
        free_keys(cmdvec);
 
        return r;
@@ -476,6 +539,8 @@ cli_init (void) {
        add_handler(LIST+MAPS+TOPOLOGY, NULL);
        add_handler(LIST+TOPOLOGY, NULL);
        add_handler(LIST+MAP+TOPOLOGY, NULL);
+       add_handler(LIST+MAP+FMT, NULL);
+       add_handler(LIST+MAP+RAW+FMT, NULL);
        add_handler(LIST+CONFIG, NULL);
        add_handler(LIST+BLACKLIST, NULL);
        add_handler(LIST+DEVICES, NULL);
@@ -562,7 +627,7 @@ key_generator (const char * str, int state)
                /*
                 * If last keyword takes a param, don't even try to guess
                 */
-               if (r == E_NOPARM) {
+               if (r == EINVAL) {
                        has_param = 1;
                        return (strdup("(value)"));
                }
index 2aa19d5..84ca40f 100644 (file)
@@ -100,13 +100,15 @@ struct key {
 
 struct handler {
        uint64_t fingerprint;
+       int locked;
        int (*fn)(void *, char **, int *, void *);
 };
 
 int alloc_handlers (void);
 int add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *));
 int set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *));
-int parse_cmd (char * cmd, char ** reply, int * len, void *);
+int set_unlocked_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *));
+int parse_cmd (char * cmd, char ** reply, int * len, void *, int);
 int load_keys (void);
 char * get_keyparam (vector v, uint64_t code);
 void free_keys (vector vec);
index 168b872..8b3cb9d 100644 (file)
@@ -349,6 +349,33 @@ show_daemon (char ** r, int *len)
 }
 
 int
+show_map (char ** r, int *len, struct multipath * mpp, char * style,
+         int pretty)
+{
+       char * c;
+       char * reply;
+       unsigned int maxlen = INITIAL_REPLY_LEN;
+       int again = 1;
+
+       reply = MALLOC(maxlen);
+       while (again) {
+               if (!reply)
+                       return 1;
+
+               c = reply;
+               c += snprint_multipath(c, reply + maxlen - c, style,
+                                      mpp, pretty);
+
+               again = ((c - reply) == (maxlen - 1));
+
+               REALLOC_REPLY(reply, again, maxlen);
+       }
+       *r = reply;
+       *len = (int)(c - reply + 1);
+       return 0;
+}
+
+int
 show_maps (char ** r, int *len, struct vectors * vecs, char * style,
           int pretty)
 {
@@ -407,6 +434,46 @@ cli_list_maps_raw (void * v, char ** reply, int * len, void * data)
 }
 
 int
+cli_list_map_fmt (void * v, char ** reply, int * len, void * data)
+{
+       struct multipath * mpp;
+       struct vectors * vecs = (struct vectors *)data;
+       char * param = get_keyparam(v, MAP);
+       char * fmt = get_keyparam(v, FMT);
+
+       param = convert_dev(param, 0);
+       get_path_layout(vecs->pathvec, 0);
+       get_multipath_layout(vecs->mpvec, 1);
+       mpp = find_mp_by_str(vecs->mpvec, param);
+       if (!mpp)
+               return 1;
+
+       condlog(3, "list map %s fmt %s (operator)", param, fmt);
+
+       return show_map(reply, len, mpp, fmt, 1);
+}
+
+int
+cli_list_map_raw (void * v, char ** reply, int * len, void * data)
+{
+       struct multipath * mpp;
+       struct vectors * vecs = (struct vectors *)data;
+       char * param = get_keyparam(v, MAP);
+       char * fmt = get_keyparam(v, FMT);
+
+       param = convert_dev(param, 0);
+       get_path_layout(vecs->pathvec, 0);
+       get_multipath_layout(vecs->mpvec, 1);
+       mpp = find_mp_by_str(vecs->mpvec, param);
+       if (!mpp)
+               return 1;
+
+       condlog(3, "list map %s fmt %s (operator)", param, fmt);
+
+       return show_map(reply, len, mpp, fmt, 0);
+}
+
+int
 cli_list_maps (void * v, char ** reply, int * len, void * data)
 {
        struct vectors * vecs = (struct vectors *)data;
@@ -807,7 +874,7 @@ cli_disable_queueing(void *v, char **reply, int *len, void *data)
                return 1;
        }
 
-       mpp->retry_tick = 0;
+       mpp->retry_tick = -1;
        dm_queue_if_no_path(mpp->alias, 0);
        return 0;
 }
@@ -821,7 +888,7 @@ cli_disable_all_queueing(void *v, char **reply, int *len, void *data)
 
        condlog(2, "disable queueing (operator)");
        vector_foreach_slot(vecs->mpvec, mpp, i) {
-               mpp->retry_tick = 0;
+               mpp->retry_tick = -1;
                dm_queue_if_no_path(mpp->alias, 0);
        }
        return 0;
@@ -842,17 +909,13 @@ cli_switch_group(void * v, char ** reply, int * len, void * data)
 int
 cli_reconfigure(void * v, char ** reply, int * len, void * data)
 {
-       struct vectors * vecs = (struct vectors *)data;
-
-       if (need_to_delay_reconfig(vecs)) {
-               conf->delayed_reconfig = 1;
-               condlog(2, "delaying reconfigure (operator)");
-               return 0;
-       }
-
        condlog(2, "reconfigure (operator)");
 
-       return reconfigure(vecs);
+       if (set_config_state(DAEMON_CONFIGURE) == ETIMEDOUT) {
+               condlog(2, "timeout starting reconfiguration");
+               return 1;
+       }
+       return 0;
 }
 
 int
@@ -874,7 +937,7 @@ cli_suspend(void * v, char ** reply, int * len, void * data)
                return 1;
        }
 
-       r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0, 0);
+       r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0);
 
        condlog(2, "%s: suspend (operator)", param);
 
@@ -904,7 +967,7 @@ cli_resume(void * v, char ** reply, int * len, void * data)
                return 1;
        }
 
-       r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0, 0);
+       r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0);
 
        condlog(2, "%s: resume (operator)", param);
 
index 799f8da..5d51018 100644 (file)
@@ -7,6 +7,8 @@ int cli_list_daemon (void * v, char ** reply, int * len, void * data);
 int cli_list_maps (void * v, char ** reply, int * len, void * data);
 int cli_list_maps_fmt (void * v, char ** reply, int * len, void * data);
 int cli_list_maps_raw (void * v, char ** reply, int * len, void * data);
+int cli_list_map_fmt (void * v, char ** reply, int * len, void * data);
+int cli_list_map_raw (void * v, char ** reply, int * len, void * data);
 int cli_list_maps_status (void * v, char ** reply, int * len, void * data);
 int cli_list_maps_stats (void * v, char ** reply, int * len, void * data);
 int cli_list_map_topology (void * v, char ** reply, int * len, void * data);
index bbcfe0d..58e8854 100644 (file)
@@ -34,6 +34,8 @@
 static int use_watchdog;
 #endif
 
+int uxsock_timeout;
+
 /*
  * libmultipath
  */
@@ -95,10 +97,11 @@ struct mpath_event_param
 unsigned int mpath_mx_alloc_len;
 
 int logsink;
-enum daemon_status running_state;
+enum daemon_status running_state = DAEMON_INIT;
 pid_t daemon_pid;
+pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t config_cond = PTHREAD_COND_INITIALIZER;
 
-static sem_t exit_sem;
 /*
  * global copy of vecs for use in sig handlers
  */
@@ -106,6 +109,94 @@ struct vectors * gvecs;
 
 struct udev * udev;
 
+const char *
+daemon_status(void)
+{
+       switch (running_state) {
+       case DAEMON_INIT:
+               return "init";
+       case DAEMON_START:
+               return "startup";
+       case DAEMON_CONFIGURE:
+               return "configure";
+       case DAEMON_IDLE:
+               return "idle";
+       case DAEMON_RUNNING:
+               return "running";
+       case DAEMON_SHUTDOWN:
+               return "shutdown";
+       }
+       return NULL;
+}
+
+/*
+ * I love you too, systemd ...
+ */
+const char *
+sd_notify_status(void)
+{
+       switch (running_state) {
+       case DAEMON_INIT:
+               return "STATUS=init";
+       case DAEMON_START:
+               return "STATUS=startup";
+       case DAEMON_CONFIGURE:
+               return "STATUS=configure";
+       case DAEMON_IDLE:
+               return "STATUS=idle";
+       case DAEMON_RUNNING:
+               return "STATUS=running";
+       case DAEMON_SHUTDOWN:
+               return "STATUS=shutdown";
+       }
+       return NULL;
+}
+
+static void config_cleanup(void *arg)
+{
+       pthread_mutex_unlock(&config_lock);
+}
+
+void post_config_state(enum daemon_status state)
+{
+       pthread_mutex_lock(&config_lock);
+       if (state != running_state) {
+               running_state = state;
+               pthread_cond_broadcast(&config_cond);
+#ifdef USE_SYSTEMD
+               sd_notify(0, sd_notify_status());
+#endif
+       }
+       pthread_mutex_unlock(&config_lock);
+}
+
+int set_config_state(enum daemon_status state)
+{
+       int rc = 0;
+
+       pthread_cleanup_push(config_cleanup, NULL);
+       pthread_mutex_lock(&config_lock);
+       if (running_state != state) {
+               if (running_state != DAEMON_IDLE) {
+                       struct timespec ts;
+
+                       clock_gettime(CLOCK_REALTIME, &ts);
+                       ts.tv_sec += 1;
+                       rc = pthread_cond_timedwait(&config_cond,
+                                                   &config_lock, &ts);
+               }
+               if (!rc) {
+                       running_state = state;
+                       pthread_cond_broadcast(&config_cond);
+#ifdef USE_SYSTEMD
+                       sd_notify(0, sd_notify_status());
+#endif
+               }
+       }
+       pthread_cleanup_pop(1);
+       return rc;
+}
+
 static int
 need_switch_pathgroup (struct multipath * mpp, int refresh)
 {
@@ -124,6 +215,9 @@ need_switch_pathgroup (struct multipath * mpp, int refresh)
                        vector_foreach_slot (pgp->paths, pp, j)
                                pathinfo(pp, conf->hwtable, DI_PRIO);
 
+       if (!mpp->pg || VECTOR_SIZE(mpp->paths) == 0)
+               return 0;
+
        mpp->bestpg = select_path_group(mpp);
 
        if (mpp->bestpg != mpp->nextpg)
@@ -270,7 +364,7 @@ update_map (struct multipath *mpp, struct vectors *vecs)
 
 retry:
        condlog(4, "%s: updating new map", mpp->alias);
-       if (adopt_paths(vecs->pathvec, mpp, 1)) {
+       if (adopt_paths(vecs->pathvec, mpp)) {
                condlog(0, "%s: failed to adopt paths for new map update",
                        mpp->alias);
                retries = -1;
@@ -322,7 +416,11 @@ uev_add_map (struct uevent * uev, struct vectors * vecs)
                        return 1;
                }
        }
+       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+       lock(vecs->lock);
+       pthread_testcancel();
        rc = ev_add_map(uev->kernel, alias, vecs);
+       lock_cleanup_pop(vecs->lock);
        FREE(alias);
        return rc;
 }
@@ -347,7 +445,7 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
        if (mpp) {
                if (mpp->wait_for_udev > 1) {
                        if (update_map(mpp, vecs))
-                       /* setup multipathd removed the map */
+                               /* setup multipathd removed the map */
                                return 1;
                }
                if (mpp->wait_for_udev) {
@@ -355,7 +453,7 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
                        if (conf->delayed_reconfig &&
                            !need_to_delay_reconfig(vecs)) {
                                condlog(2, "reconfigure (delayed)");
-                               reconfigure(vecs);
+                               set_config_state(DAEMON_CONFIGURE);
                                return 0;
                        }
                }
@@ -418,6 +516,10 @@ uev_remove_map (struct uevent * uev, struct vectors * vecs)
                return 0;
        }
        minor = uevent_get_minor(uev);
+
+       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+       lock(vecs->lock);
+       pthread_testcancel();
        mpp = find_mp_by_minor(vecs->mpvec, minor);
 
        if (!mpp) {
@@ -434,10 +536,12 @@ uev_remove_map (struct uevent * uev, struct vectors * vecs)
        orphan_paths(vecs->pathvec, mpp);
        remove_map_and_stop_waiter(mpp, vecs, 1);
 out:
+       lock_cleanup_pop(vecs->lock);
        FREE(alias);
        return 0;
 }
 
+/* Called from CLI handler */
 int
 ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs)
 {
@@ -473,6 +577,9 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
                return 1;
        }
 
+       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+       lock(vecs->lock);
+       pthread_testcancel();
        pp = find_path_by_dev(vecs->pathvec, uev->kernel);
        if (pp) {
                int r;
@@ -500,8 +607,10 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
                                ret = 1;
                        }
                }
-               return ret;
        }
+       lock_cleanup_pop(vecs->lock);
+       if (pp)
+               return ret;
 
        /*
         * get path vital state
@@ -514,6 +623,9 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
                condlog(3, "%s: failed to get path info", uev->kernel);
                return 1;
        }
+       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+       lock(vecs->lock);
+       pthread_testcancel();
        ret = store_path(vecs->pathvec, pp);
        if (!ret) {
                pp->checkint = conf->checkint;
@@ -525,7 +637,7 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
                free_path(pp);
                ret = 1;
        }
-
+       lock_cleanup_pop(vecs->lock);
        return ret;
 }
 
@@ -560,7 +672,7 @@ ev_add_path (struct path * pp, struct vectors * vecs)
        pp->mpp = mpp;
 rescan:
        if (mpp) {
-               if (mpp->size != pp->size) {
+               if (pp->size && mpp->size != pp->size) {
                        condlog(0, "%s: failed to add new path %s, "
                                "device size mismatch",
                                mpp->alias, pp->dev);
@@ -573,7 +685,7 @@ rescan:
 
                condlog(4,"%s: adopting all paths for path %s",
                        mpp->alias, pp->dev);
-               if (adopt_paths(vecs->pathvec, mpp, 1))
+               if (adopt_paths(vecs->pathvec, mpp))
                        goto fail; /* leave path added to pathvec */
 
                verify_paths(mpp, vecs);
@@ -593,12 +705,12 @@ rescan:
                         */
                        start_waiter = 1;
                }
-               else
+               if (!start_waiter)
                        goto fail; /* leave path added to pathvec */
        }
 
-       /* persistent reseravtion check*/
-       mpath_pr_event_handle(pp);      
+       /* persistent reservation check*/
+       mpath_pr_event_handle(pp);
 
        /*
         * push the map to the device-mapper
@@ -626,7 +738,7 @@ retry:
                 * deal with asynchronous uevents :((
                 */
                if (mpp->action == ACT_RELOAD && retries-- > 0) {
-                       condlog(0, "%s: uev_add_path sleep", mpp->alias);
+                       condlog(0, "%s: ev_add_path sleep", mpp->alias);
                        sleep(1);
                        update_mpp_paths(mpp, vecs->pathvec);
                        goto rescan;
@@ -655,8 +767,7 @@ retry:
                condlog(2, "%s [%s]: path added to devmap %s",
                        pp->dev, pp->dev_t, mpp->alias);
                return 0;
-       }
-       else
+       } else
                goto fail;
 
 fail_map:
@@ -670,17 +781,22 @@ static int
 uev_remove_path (struct uevent *uev, struct vectors * vecs)
 {
        struct path *pp;
+       int ret;
 
        condlog(2, "%s: remove path (uevent)", uev->kernel);
+       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+       lock(vecs->lock);
+       pthread_testcancel();
        pp = find_path_by_dev(vecs->pathvec, uev->kernel);
-
+       if (pp)
+               ret = ev_remove_path(pp, vecs);
+       lock_cleanup_pop(vecs->lock);
        if (!pp) {
                /* Not an error; path might have been purged earlier */
                condlog(0, "%s: path already removed", uev->kernel);
                return 0;
        }
-
-       return ev_remove_path(pp, vecs);
+       return ret;
 }
 
 int
@@ -785,35 +901,50 @@ static int
 uev_update_path (struct uevent *uev, struct vectors * vecs)
 {
        int ro, retval = 0;
-       struct path * pp;
-
-       pp = find_path_by_dev(vecs->pathvec, uev->kernel);
-       if (!pp) {
-               condlog(0, "%s: spurious uevent, path not found",
-                       uev->kernel);
-               return 1;
-       }
-
-       if (pp->initialized == INIT_REQUESTED_UDEV)
-               return uev_add_path(uev, vecs);
 
        ro = uevent_get_disk_ro(uev);
 
        if (ro >= 0) {
+               struct path * pp;
+               struct multipath *mpp = NULL;
+
                condlog(2, "%s: update path write_protect to '%d' (uevent)",
                        uev->kernel, ro);
-               if (pp->mpp) {
-                       if (pp->mpp->wait_for_udev) {
-                               pp->mpp->wait_for_udev = 2;
-                               return 0;
+               pthread_cleanup_push(cleanup_lock, &vecs->lock);
+               lock(vecs->lock);
+               pthread_testcancel();
+               /*
+                * pthread_mutex_lock() and pthread_mutex_unlock()
+                * need to be at the same indentation level, hence
+                * this slightly convoluted codepath.
+                */
+               pp = find_path_by_dev(vecs->pathvec, uev->kernel);
+               if (pp) {
+                       if (pp->initialized == INIT_REQUESTED_UDEV) {
+                               retval = 2;
+                       } else {
+                               mpp = pp->mpp;
+                               if (mpp && mpp->wait_for_udev) {
+                                       mpp->wait_for_udev = 2;
+                                       mpp = NULL;
+                                       retval = 0;
+                               }
                        }
+                       if (mpp) {
+                               retval = reload_map(vecs, mpp, 0);
 
-                       retval = reload_map(vecs, pp->mpp, 0);
-
-                       condlog(2, "%s: map %s reloaded (retval %d)",
-                               uev->kernel, pp->mpp->alias, retval);
+                               condlog(2, "%s: map %s reloaded (retval %d)",
+                                       uev->kernel, mpp->alias, retval);
+                       }
                }
-
+               lock_cleanup_pop(vecs->lock);
+               if (!pp) {
+                       condlog(0, "%s: spurious uevent, path not found",
+                               uev->kernel);
+                       return 1;
+               }
+               if (retval == 2)
+                       return uev_add_path(uev, vecs);
        }
 
        return retval;
@@ -845,14 +976,13 @@ uxsock_trigger (char * str, char ** reply, int * len, void * trigger_data)
        *len = 0;
        vecs = (struct vectors *)trigger_data;
 
-       pthread_cleanup_push(cleanup_lock, &vecs->lock);
-       lock(vecs->lock);
-       pthread_testcancel();
-
-       r = parse_cmd(str, reply, len, vecs);
+       r = parse_cmd(str, reply, len, vecs, uxsock_timeout / 1000);
 
        if (r > 0) {
-               *reply = STRDUP("fail\n");
+               if (r == ETIMEDOUT)
+                       *reply = STRDUP("timeout\n");
+               else
+                       *reply = STRDUP("fail\n");
                *len = strlen(*reply) + 1;
                r = 1;
        }
@@ -863,7 +993,6 @@ uxsock_trigger (char * str, char ** reply, int * len, void * trigger_data)
        }
        /* else if (r < 0) leave *reply alone */
 
-       lock_cleanup_pop(vecs->lock);
        return r;
 }
 
@@ -900,9 +1029,15 @@ uev_trigger (struct uevent * uev, void * trigger_data)
        if (uev_discard(uev->devpath))
                return 0;
 
-       pthread_cleanup_push(cleanup_lock, &vecs->lock);
-       lock(vecs->lock);
-       pthread_testcancel();
+       pthread_cleanup_push(config_cleanup, NULL);
+       pthread_mutex_lock(&config_lock);
+       if (running_state != DAEMON_IDLE &&
+           running_state != DAEMON_RUNNING)
+               pthread_cond_wait(&config_cond, &config_lock);
+       pthread_cleanup_pop(1);
+
+       if (running_state == DAEMON_SHUTDOWN)
+               return 0;
 
        /*
         * device map event
@@ -942,7 +1077,6 @@ uev_trigger (struct uevent * uev, void * trigger_data)
        }
 
 out:
-       lock_cleanup_pop(vecs->lock);
        return r;
 }
 
@@ -968,16 +1102,18 @@ uevqloop (void * ap)
 static void *
 uxlsnrloop (void * ap)
 {
-       if (cli_init())
+       if (cli_init()) {
+               condlog(1, "Failed to init uxsock listener");
                return NULL;
+       }
 
        set_handler_callback(LIST+PATHS, cli_list_paths);
        set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt);
        set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw);
        set_handler_callback(LIST+PATH, cli_list_path);
        set_handler_callback(LIST+MAPS, cli_list_maps);
-       set_handler_callback(LIST+STATUS, cli_list_status);
-       set_handler_callback(LIST+DAEMON, cli_list_daemon);
+       set_unlocked_handler_callback(LIST+STATUS, cli_list_status);
+       set_unlocked_handler_callback(LIST+DAEMON, cli_list_daemon);
        set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status);
        set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats);
        set_handler_callback(LIST+MAPS+FMT, cli_list_maps_fmt);
@@ -985,8 +1121,10 @@ uxlsnrloop (void * ap)
        set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology);
        set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology);
        set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology);
-       set_handler_callback(LIST+CONFIG, cli_list_config);
-       set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
+       set_handler_callback(LIST+MAP+FMT, cli_list_map_fmt);
+       set_handler_callback(LIST+MAP+RAW+FMT, cli_list_map_fmt);
+       set_unlocked_handler_callback(LIST+CONFIG, cli_list_config);
+       set_unlocked_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
        set_handler_callback(LIST+DEVICES, cli_list_devices);
        set_handler_callback(LIST+WILDCARDS, cli_list_wildcards);
        set_handler_callback(ADD+PATH, cli_add_path);
@@ -994,7 +1132,7 @@ uxlsnrloop (void * ap)
        set_handler_callback(ADD+MAP, cli_add_map);
        set_handler_callback(DEL+MAP, cli_del_map);
        set_handler_callback(SWITCH+MAP+GROUP, cli_switch_group);
-       set_handler_callback(RECONFIGURE, cli_reconfigure);
+       set_unlocked_handler_callback(RECONFIGURE, cli_reconfigure);
        set_handler_callback(SUSPEND+MAP, cli_suspend);
        set_handler_callback(RESUME+MAP, cli_resume);
        set_handler_callback(RESIZE+MAP, cli_resize);
@@ -1006,8 +1144,8 @@ uxlsnrloop (void * ap)
        set_handler_callback(RESTOREQ+MAP, cli_restore_queueing);
        set_handler_callback(DISABLEQ+MAPS, cli_disable_all_queueing);
        set_handler_callback(RESTOREQ+MAPS, cli_restore_all_queueing);
-       set_handler_callback(QUIT, cli_quit);
-       set_handler_callback(SHUTDOWN, cli_shutdown);
+       set_unlocked_handler_callback(QUIT, cli_quit);
+       set_unlocked_handler_callback(SHUTDOWN, cli_shutdown);
        set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus);
        set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus);
        set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus);
@@ -1023,25 +1161,7 @@ uxlsnrloop (void * ap)
 void
 exit_daemon (void)
 {
-       sem_post(&exit_sem);
-}
-
-const char *
-daemon_status(void)
-{
-       switch (running_state) {
-       case DAEMON_INIT:
-               return "init";
-       case DAEMON_START:
-               return "startup";
-       case DAEMON_CONFIGURE:
-               return "configure";
-       case DAEMON_RUNNING:
-               return "running";
-       case DAEMON_SHUTDOWN:
-               return "shutdown";
-       }
-       return NULL;
+       post_config_state(DAEMON_SHUTDOWN);
 }
 
 static void
@@ -1170,7 +1290,7 @@ missing_uev_wait_tick(struct vectors *vecs)
        if (timed_out && conf->delayed_reconfig &&
            !need_to_delay_reconfig(vecs)) {
                condlog(2, "reconfigure (delayed)");
-               reconfigure(vecs);
+               set_config_state(DAEMON_CONFIGURE);
        }
 }
 
@@ -1200,7 +1320,7 @@ retry_count_tick(vector mpvec)
        unsigned int i;
 
        vector_foreach_slot (mpvec, mpp, i) {
-               if (mpp->retry_tick) {
+               if (mpp->retry_tick > 0) {
                        mpp->stat_total_queueing_time++;
                        condlog(4, "%s: Retrying.. No active path", mpp->alias);
                        if(--mpp->retry_tick == 0) {
@@ -1254,7 +1374,7 @@ int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh)
  * Returns '1' if the path has been checked, '0' otherwise
  */
 int
-check_path (struct vectors * vecs, struct path * pp)
+check_path (struct vectors * vecs, struct path * pp, int ticks)
 {
        int newstate;
        int new_path_up = 0;
@@ -1267,7 +1387,9 @@ check_path (struct vectors * vecs, struct path * pp)
             pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp)
                return 0;
 
-       if (pp->tick && --pp->tick)
+       if (pp->tick)
+               pp->tick -= (pp->tick > ticks) ? ticks : pp->tick;
+       if (pp->tick)
                return 0; /* don't check this path yet */
 
        if (!pp->mpp && pp->initialized == INIT_MISSING_UDEV &&
@@ -1279,7 +1401,7 @@ check_path (struct vectors * vecs, struct path * pp)
                sysfs_attr_set_value(pp->udev, "uevent", "change",
                                     strlen("change"));
                return 0;
-       } 
+       }
 
        /*
         * provision a next check soonest,
@@ -1509,6 +1631,8 @@ checkerloop (void *ap)
        struct path *pp;
        int count = 0;
        unsigned int i;
+       struct itimerval timer_tick_it;
+       struct timeval last_time;
 
        mlockall(MCL_CURRENT | MCL_FUTURE);
        vecs = (struct vectors *)ap;
@@ -1521,48 +1645,114 @@ checkerloop (void *ap)
                pp->checkint = conf->checkint;
        }
 
+       /* Tweak start time for initial path check */
+       if (gettimeofday(&last_time, NULL) != 0)
+               last_time.tv_sec = 0;
+       else
+               last_time.tv_sec -= 1;
+
        while (1) {
                struct timeval diff_time, start_time, end_time;
-               int num_paths = 0;
+               int num_paths = 0, ticks = 0, signo, strict_timing, rc = 0;
+               sigset_t mask;
 
                if (gettimeofday(&start_time, NULL) != 0)
                        start_time.tv_sec = 0;
-               pthread_cleanup_push(cleanup_lock, &vecs->lock);
-               lock(vecs->lock);
-               pthread_testcancel();
-               condlog(4, "tick");
+               if (start_time.tv_sec && last_time.tv_sec) {
+                       timersub(&start_time, &last_time, &diff_time);
+                       condlog(4, "tick (%lu.%06lu secs)",
+                               diff_time.tv_sec, diff_time.tv_usec);
+                       last_time.tv_sec = start_time.tv_sec;
+                       last_time.tv_usec = start_time.tv_usec;
+                       ticks = diff_time.tv_sec;
+               } else {
+                       ticks = 1;
+                       condlog(4, "tick (%d ticks)", ticks);
+               }
 #ifdef USE_SYSTEMD
                if (use_watchdog)
                        sd_notify(0, "WATCHDOG=1");
 #endif
+               rc = set_config_state(DAEMON_RUNNING);
+               if (rc == ETIMEDOUT) {
+                       condlog(4, "timeout waiting for DAEMON_IDLE");
+                       continue;
+               }
+               strict_timing = conf->strict_timing;
                if (vecs->pathvec) {
+                       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+                       lock(vecs->lock);
+                       pthread_testcancel();
                        vector_foreach_slot (vecs->pathvec, pp, i) {
-                               num_paths += check_path(vecs, pp);
+                               num_paths += check_path(vecs, pp, ticks);
                        }
+                       lock_cleanup_pop(vecs->lock);
                }
                if (vecs->mpvec) {
+                       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+                       lock(vecs->lock);
+                       pthread_testcancel();
                        defered_failback_tick(vecs->mpvec);
                        retry_count_tick(vecs->mpvec);
                        missing_uev_wait_tick(vecs);
+                       lock_cleanup_pop(vecs->lock);
                }
                if (count)
                        count--;
                else {
+                       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+                       lock(vecs->lock);
+                       pthread_testcancel();
                        condlog(4, "map garbage collection");
                        mpvec_garbage_collector(vecs);
                        count = MAPGCINT;
+                       lock_cleanup_pop(vecs->lock);
                }
 
-               lock_cleanup_pop(vecs->lock);
+               diff_time.tv_usec = 0;
                if (start_time.tv_sec &&
-                   gettimeofday(&end_time, NULL) == 0 &&
-                   num_paths) {
+                   gettimeofday(&end_time, NULL) == 0) {
                        timersub(&end_time, &start_time, &diff_time);
-                       condlog(3, "checked %d path%s in %lu.%06lu secs",
-                               num_paths, num_paths > 1 ? "s" : "",
-                               diff_time.tv_sec, diff_time.tv_usec);
+                       if (num_paths) {
+                               condlog(3, "checked %d path%s in %lu.%06lu secs",
+                                       num_paths, num_paths > 1 ? "s" : "",
+                                       diff_time.tv_sec, diff_time.tv_usec);
+                               if (diff_time.tv_sec > conf->max_checkint)
+                                       condlog(1, "path checkers took longer "
+                                               "than %lu seconds, consider "
+                                               "increasing max_polling_interval",
+                                               diff_time.tv_sec);
+                       }
+               }
+
+               post_config_state(DAEMON_IDLE);
+               if (!strict_timing)
+                       sleep(1);
+               else {
+                       timer_tick_it.it_interval.tv_sec = 0;
+                       timer_tick_it.it_interval.tv_usec = 0;
+                       if (diff_time.tv_usec) {
+                               timer_tick_it.it_value.tv_sec = 0;
+                               timer_tick_it.it_value.tv_usec =
+                                       (unsigned long)1000000 - diff_time.tv_usec;
+                       } else {
+                               timer_tick_it.it_value.tv_sec = 1;
+                               timer_tick_it.it_value.tv_usec = 0;
+                       }
+                       setitimer(ITIMER_REAL, &timer_tick_it, NULL);
+
+                       sigemptyset(&mask);
+                       sigaddset(&mask, SIGALRM);
+                       condlog(3, "waiting for %lu.%06lu secs",
+                               timer_tick_it.it_value.tv_sec,
+                               timer_tick_it.it_value.tv_usec);
+                       if (sigwait(&mask, &signo) != 0) {
+                               condlog(3, "sigwait failed with error %d",
+                                       errno);
+                               conf->strict_timing = 0;
+                               break;
+                       }
                }
-               sleep(1);
        }
        return NULL;
 }
@@ -1670,8 +1860,6 @@ reconfigure (struct vectors * vecs)
        struct config * old = conf;
        int retval = 1;
 
-       running_state = DAEMON_CONFIGURE;
-
        /*
         * free old map and path vectors ... they use old conf state
         */
@@ -1696,9 +1884,10 @@ reconfigure (struct vectors * vecs)
                configure(vecs, 1);
                free_config(old);
                retval = 0;
+       } else {
+               conf = old;
        }
-
-       running_state = DAEMON_RUNNING;
+       uxsock_timeout = conf->uxsock_timeout;
 
        return retval;
 }
@@ -1752,20 +1941,9 @@ signal_set(int signo, void (*func) (int))
 void
 handle_signals(void)
 {
-       if (reconfig_sig && running_state == DAEMON_RUNNING) {
-               pthread_cleanup_push(cleanup_lock,
-                               &gvecs->lock);
-               lock(gvecs->lock);
-               pthread_testcancel();
-               if (need_to_delay_reconfig(gvecs)) {
-                       conf->delayed_reconfig = 1;
-                       condlog(2, "delaying reconfigure (signal)");
-               }
-               else {
-                       condlog(2, "reconfigure (signal)");
-                       reconfigure(gvecs);
-               }
-               lock_cleanup_pop(gvecs->lock);
+       if (reconfig_sig) {
+               condlog(2, "reconfigure (signal)");
+               set_config_state(DAEMON_CONFIGURE);
        }
        if (log_reset_sig) {
                condlog(2, "reset log (signal)");
@@ -1810,6 +1988,7 @@ signal_init(void)
        sigaddset(&set, SIGHUP);
        sigaddset(&set, SIGUSR1);
        sigaddset(&set, SIGUSR2);
+       sigaddset(&set, SIGALRM);
        pthread_sigmask(SIG_BLOCK, &set, NULL);
 
        signal_set(SIGHUP, sighup);
@@ -1898,7 +2077,6 @@ child (void * param)
        char *envp;
 
        mlockall(MCL_CURRENT | MCL_FUTURE);
-       sem_init(&exit_sem, 0, 0);
        signal_init();
 
        udev = udev_new();
@@ -1919,17 +2097,16 @@ child (void * param)
                exit(1);
        }
 
-       running_state = DAEMON_START;
+       post_config_state(DAEMON_START);
 
-#ifdef USE_SYSTEMD
-       sd_notify(0, "STATUS=startup");
-#endif
        condlog(2, "--------start up--------");
        condlog(2, "read " DEFAULT_CONFIGFILE);
 
        if (load_config(DEFAULT_CONFIGFILE, udev))
                goto failed;
 
+       uxsock_timeout = conf->uxsock_timeout;
+
        dm_drv_version(conf->version, TGT_MPATH);
        if (init_checkers()) {
                condlog(0, "failed to initialize checkers");
@@ -1997,6 +2174,11 @@ child (void * param)
        }
 #endif
        /*
+        * Signal start of configuration
+        */
+       post_config_state(DAEMON_CONFIGURE);
+
+       /*
         * Start uevent listener early to catch events
         */
        if ((rc = pthread_create(&uevent_thr, &uevent_attr, ueventloop, udev))) {
@@ -2008,21 +2190,6 @@ child (void * param)
                condlog(0, "failed to create cli listener: %d", rc);
                goto failed;
        }
-       /*
-        * fetch and configure both paths and multipaths
-        */
-#ifdef USE_SYSTEMD
-       sd_notify(0, "STATUS=configure");
-#endif
-       running_state = DAEMON_CONFIGURE;
-
-       lock(vecs->lock);
-       if (configure(vecs, 1)) {
-               unlock(vecs->lock);
-               condlog(0, "failure during configuration");
-               goto failed;
-       }
-       unlock(vecs->lock);
 
        /*
         * start threads
@@ -2037,20 +2204,32 @@ child (void * param)
        }
        pthread_attr_destroy(&misc_attr);
 
-       running_state = DAEMON_RUNNING;
 #ifdef USE_SYSTEMD
-       sd_notify(0, "READY=1\nSTATUS=running");
+       sd_notify(0, "READY=1");
 #endif
 
-       /*
-        * exit path
-        */
-       while(sem_wait(&exit_sem) != 0); /* Do nothing */
+       while (running_state != DAEMON_SHUTDOWN) {
+               pthread_cleanup_push(config_cleanup, NULL);
+               pthread_mutex_lock(&config_lock);
+               if (running_state != DAEMON_CONFIGURE &&
+                   running_state != DAEMON_SHUTDOWN) {
+                       pthread_cond_wait(&config_cond, &config_lock);
+               }
+               pthread_cleanup_pop(1);
+               if (running_state == DAEMON_CONFIGURE) {
+                       pthread_cleanup_push(cleanup_lock, &vecs->lock);
+                       lock(vecs->lock);
+                       pthread_testcancel();
+                       if (!need_to_delay_reconfig(vecs)) {
+                               reconfigure(vecs);
+                       } else {
+                               conf->delayed_reconfig = 1;
+                       }
+                       lock_cleanup_pop(vecs->lock);
+                       post_config_state(DAEMON_IDLE);
+               }
+       }
 
-#ifdef USE_SYSTEMD
-       sd_notify(0, "STATUS=shutdown");
-#endif
-       running_state = DAEMON_SHUTDOWN;
        lock(vecs->lock);
        if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF)
                vector_foreach_slot(vecs->mpvec, mpp, i)
@@ -2183,7 +2362,6 @@ main (int argc, char *argv[])
        int foreground = 0;
 
        logsink = 1;
-       running_state = DAEMON_INIT;
        dm_init();
 
        if (getuid() != 0) {
@@ -2223,7 +2401,7 @@ main (int argc, char *argv[])
                case 'k':
                        if (load_config(DEFAULT_CONFIGFILE, udev_new()))
                                exit(1);
-                       uxclnt(optarg, conf->uxsock_timeout);
+                       uxclnt(optarg, uxsock_timeout + 100);
                        exit(0);
                case 'B':
                        conf->bindings_read_only = 1;
@@ -2232,7 +2410,9 @@ main (int argc, char *argv[])
                        conf->ignore_new_devs = 1;
                        break;
                default:
-                       ;
+                       fprintf(stderr, "Invalid argument '-%c'\n",
+                               optopt);
+                       exit(1);
                }
        }
        if (optind < argc) {
@@ -2242,6 +2422,7 @@ main (int argc, char *argv[])
 
                if (load_config(DEFAULT_CONFIGFILE, udev_new()))
                        exit(1);
+               memset(cmd, 0x0, CMDSIZE);
                while (optind < argc) {
                        if (strchr(argv[optind], ' '))
                                c += snprintf(c, s + CMDSIZE - c, "\"%s\" ", argv[optind]);
@@ -2250,7 +2431,7 @@ main (int argc, char *argv[])
                        optind++;
                }
                c += snprintf(c, s + CMDSIZE - c, "\n");
-               uxclnt(s, conf->uxsock_timeout);
+               uxclnt(s, uxsock_timeout + 100);
                exit(0);
        }
 
index 2f706d2..10b3a6d 100644 (file)
@@ -7,6 +7,7 @@ enum daemon_status {
     DAEMON_INIT,
     DAEMON_START,
     DAEMON_CONFIGURE,
+    DAEMON_IDLE,
     DAEMON_RUNNING,
     DAEMON_SHUTDOWN,
 };
@@ -15,6 +16,7 @@ struct prout_param_descriptor;
 struct prin_resp;
 
 extern pid_t daemon_pid;
+extern int uxsock_timeout;
 
 void exit_daemon(void);
 const char * daemon_status(void);
@@ -25,6 +27,7 @@ int ev_remove_path (struct path *, struct vectors *);
 int ev_add_map (char *, char *, struct vectors *);
 int ev_remove_map (char *, char *, int, struct vectors *);
 void sync_map_state (struct multipath *);
+int set_config_state(enum daemon_status);
 void * mpath_alloc_prin_response(int prin_sa);
 int prin_do_scsi_ioctl(char *, int rq_servact, struct prin_resp * resp,
        int noisy);
index d5f8606..e3d6f91 100644 (file)
@@ -1,8 +1,8 @@
 [Unit]
 Description=Device-Mapper Multipath Device Controller
 Before=iscsi.service iscsid.service lvm2-activation-early.service
-Before=local-fs-pre.target
-After=multipathd.socket
+Before=local-fs-pre.target systemd-udev-trigger.service
+After=multipathd.socket systemd-udevd.service
 DefaultDependencies=no
 Wants=local-fs-pre.target multipathd.socket blk-availability.service
 Conflicts=shutdown.target
@@ -11,7 +11,7 @@ Conflicts=shutdown.target
 Type=notify
 NotifyAccess=main
 LimitCORE=infinity
-ExecStartPre=/sbin/modprobe dm-multipath
+ExecStartPre=/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath
 ExecStart=/sbin/multipathd -d -s
 ExecReload=/sbin/multipathd reconfigure
 
index e5c5d90..9912e00 100644 (file)
@@ -44,6 +44,8 @@ struct client {
        int fd;
 };
 
+#define MIN_POLLS 1023
+
 LIST_HEAD(clients);
 pthread_mutex_t client_lock = PTHREAD_MUTEX_INITIALIZER;
 struct pollfd *polls;
@@ -129,10 +131,11 @@ void uxsock_cleanup(void *arg)
 void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
 {
        int ux_sock;
-       int rlen, timeout;
+       int rlen;
        char *inbuf;
        char *reply;
        sigset_t mask;
+       int old_clients = MIN_POLLS;
 
        ux_sock = ux_socket_listen(DEFAULT_SOCKET);
 
@@ -142,50 +145,50 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
        }
 
        if (!conf) {
-               condlog(1, "configuration changed");
+               condlog(1, "uxsock: configuration changed");
                return NULL;
        }
 
-       timeout = conf->uxsock_timeout;
-
        pthread_cleanup_push(uxsock_cleanup, NULL);
 
-       polls = (struct pollfd *)MALLOC(0);
+       condlog(3, "uxsock: startup listener");
+       polls = (struct pollfd *)MALLOC(MIN_POLLS + 1);
+       if (!polls) {
+               condlog(0, "uxsock: failed to allocate poll fds");
+               return NULL;
+       }
        pthread_sigmask(SIG_SETMASK, NULL, &mask);
        sigdelset(&mask, SIGHUP);
        sigdelset(&mask, SIGUSR1);
        while (1) {
-               struct pollfd *new;
                struct client *c, *tmp;
                int i, poll_count, num_clients;
 
-               /*
-                * Store configuration timeout;
-                * configuration might change during
-                * the call to 'reconfigure'.
-                */
-               if (conf)
-                       timeout = conf->uxsock_timeout;
-
                /* setup for a poll */
                pthread_mutex_lock(&client_lock);
                num_clients = 0;
                list_for_each_entry(c, &clients, node) {
                        num_clients++;
                }
-               new = REALLOC(polls, (1+num_clients) * sizeof(*polls));
-               /* If we can't allocate poliing space for the new client,
-                * close it */
-               if (!new) {
-                       if (!num_clients) {
-                               condlog(1, "can't listen for new clients");
-                               return NULL;
+               if (num_clients != old_clients) {
+                       struct pollfd *new;
+                       if (num_clients < MIN_POLLS) {
+                               new = REALLOC(polls, (1 + MIN_POLLS) *
+                                               sizeof(struct pollfd));
+                       } else {
+                               new = REALLOC(polls, (1+num_clients) *
+                                               sizeof(struct pollfd));
                        }
-                       dead_client(list_entry(clients.prev,
-                                              typeof(struct client), node));
-               }
-               else
+                       if (!new) {
+                               pthread_mutex_unlock(&client_lock);
+                               condlog(0, "%s: failed to realloc %d poll fds",
+                                       "uxsock", 1 + num_clients);
+                               pthread_yield();
+                               continue;
+                       }
+                       num_clients = old_clients;
                        polls = new;
+               }
                polls[0].fd = ux_sock;
                polls[0].events = POLLIN;
 
@@ -208,8 +211,8 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
                        }
 
                        /* something went badly wrong! */
-                       condlog(0, "poll");
-                       pthread_exit(NULL);
+                       condlog(0, "uxsock: poll failed with %d", errno);
+                       break;
                }
 
                if (poll_count == 0)
@@ -230,32 +233,36 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
                                }
                                pthread_mutex_unlock(&client_lock);
                                if (!c) {
-                                       condlog(3, "cli%d: invalid fd %d",
+                                       condlog(4, "cli%d: new fd %d",
                                                i, polls[i].fd);
                                        continue;
                                }
                                if (gettimeofday(&start_time, NULL) != 0)
                                        start_time.tv_sec = 0;
-                               if (recv_packet(c->fd, &inbuf, timeout) != 0) {
+                               if (recv_packet(c->fd, &inbuf,
+                                               uxsock_timeout) != 0) {
                                        dead_client(c);
-                               } else {
-                                       condlog(4, "Got request [%s]", inbuf);
-                                       uxsock_trigger(inbuf, &reply, &rlen,
-                                                      trigger_data);
-                                       if (reply) {
-                                               if (send_packet(c->fd,
-                                                               reply) != 0) {
-                                                       dead_client(c);
-                                               }
-                                               condlog(4, "Reply [%d bytes]",
-                                                       rlen);
-                                               FREE(reply);
-                                               reply = NULL;
+                                       continue;
+                               }
+                               condlog(4, "cli[%d]: Got request [%s]",
+                                       i, inbuf);
+                               uxsock_trigger(inbuf, &reply, &rlen,
+                                              trigger_data);
+                               if (reply) {
+                                       if (send_packet(c->fd,
+                                                       reply) != 0) {
+                                               dead_client(c);
+                                       } else {
+                                               condlog(4, "cli[%d]: "
+                                                       "Reply [%d bytes]",
+                                                       i, rlen);
                                        }
-                                       check_timeout(start_time, inbuf,
-                                                     timeout);
-                                       FREE(inbuf);
+                                       FREE(reply);
+                                       reply = NULL;
                                }
+                               check_timeout(start_time, inbuf,
+                                             uxsock_timeout);
+                               FREE(inbuf);
                        }
                }