add '-r' option to force devmap reload
authorChristophe Varoqui <christophe.varoqui@free.fr>
Mon, 19 May 2008 22:07:45 +0000 (00:07 +0200)
committerChristophe Varoqui <christophe.varoqui@free.fr>
Wed, 21 May 2008 20:01:17 +0000 (22:01 +0200)
This takes care of updating the write-protection flag
of the devmap in case the write-prot of the underlying
paths has changed (and the kernel somehow has discovered
so).

Now a RO->RW change scenario for a multipathed device can
be treated with :
1/ echo 1 >/sys/block/XX/device/rescan on all paths to dev
2/ multipath -r dev

Which minimaly fulfills my needs with Symmetrix SRDF spliting
in interim of more collaboration from other subsystems.

libmultipath/config.h
libmultipath/configure.c
libmultipath/configure.h
multipath/main.c
multipathd/main.c

index b644544..3483d6d 100644 (file)
@@ -65,6 +65,7 @@ struct config {
        int user_friendly_names;
        int pg_timeout;
        int max_fds;
+       int force_reload;
 
        char * dev;
        char * sysfs_dir;
index d9fa397..ad76832 100644 (file)
@@ -130,7 +130,7 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp)
 }
 
 static void
-select_action (struct multipath * mpp, vector curmp)
+select_action (struct multipath * mpp, vector curmp, int force_reload)
 {
        struct multipath * cmpp;
 
@@ -169,6 +169,12 @@ select_action (struct multipath * mpp, vector curmp)
                        mpp->alias);
                return;
        }
+       if (force_reload) {
+               mpp->action = ACT_RELOAD;
+               condlog(3, "%s: set ACT_RELOAD (forced by user)",
+                       mpp->alias);
+               return;
+       }
        if (cmpp->size != mpp->size) {
                mpp->action = ACT_RELOAD;
                condlog(3, "%s: set ACT_RELOAD (size change)",
@@ -410,7 +416,7 @@ deadmap (struct multipath * mpp)
 }
 
 extern int
-coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid)
+coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_reload)
 {
        int r = 1;
        int k, i;
@@ -423,6 +429,11 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid)
 
        memset(empty_buff, 0, WWID_SIZE);
 
+       if (force_reload) {
+               vector_foreach_slot (pathvec, pp1, k) {
+                       pp1->mpp = NULL;
+               }
+       }
        vector_foreach_slot (pathvec, pp1, k) {
                /* skip this path for some reason */
 
@@ -446,7 +457,8 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid)
                /*
                 * at this point, we know we really got a new mp
                 */
-               if ((mpp = add_map_with_path(vecs, pp1, 0)) == NULL)
+               mpp = add_map_with_path(vecs, pp1, 0);
+               if (!mpp)
                        return 1;
 
                if (pp1->priority == PRIO_UNDEF)
@@ -487,7 +499,7 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid)
                }
 
                if (mpp->action == ACT_UNDEF)
-                       select_action(mpp, curmp);
+                       select_action(mpp, curmp, force_reload);
 
                r = domap(mpp);
 
index 1cbbe82..75d5057 100644 (file)
@@ -24,6 +24,6 @@ enum actions {
 int setup_map (struct multipath * mpp);
 int domap (struct multipath * mpp);
 int reinstate_paths (struct multipath *mpp);
-int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid);
+int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload);
 char * get_refwwid (char * dev, enum devtypes dev_type, vector pathvec);
 
index f1ac256..44c6bf6 100644 (file)
@@ -75,34 +75,39 @@ static void
 usage (char * progname)
 {
        fprintf (stderr, VERSION_STRING);
-       fprintf (stderr, "Usage: %s\t[-v level] [-d] [-h|-l|-ll|-f|-F]\n",
-               progname);
+       fprintf (stderr, "Usage:\n");
+       fprintf (stderr, "  %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname);
+       fprintf (stderr, "  %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname);
+       fprintf (stderr, "  %s -F [-v lvl]\n", progname);
+       fprintf (stderr, "  %s -h\n", progname);
        fprintf (stderr,
-               "\t\t\t[-p failover|multibus|group_by_serial|group_by_prio]\n" \
-               "\t\t\t[device]\n" \
-               "\n" \
-               "\t-v level\tverbosity level\n" \
-               "\t   0\t\t\tno output\n" \
-               "\t   1\t\t\tprint created devmap names only\n" \
-               "\t   2\t\t\tdefault verbosity\n" \
-               "\t   3\t\t\tprint debug information\n" \
-               "\t-h\t\tprint this usage text\n" \
-               "\t-b file\t\tbindings file location\n" \
-               "\t-d\t\tdry run, do not create or update devmaps\n" \
-               "\t-l\t\tshow multipath topology (sysfs and DM info)\n" \
-               "\t-ll\t\tshow multipath topology (maximum info)\n" \
-               "\t-f\t\tflush a multipath device map\n" \
-               "\t-F\t\tflush all multipath device maps\n" \
-               "\t-p policy\tforce all maps to specified policy :\n" \
-               "\t   failover\t\t1 path per priority group\n" \
-               "\t   multibus\t\tall paths in 1 priority group\n" \
-               "\t   group_by_serial\t1 priority group per serial\n" \
-               "\t   group_by_prio\t1 priority group per priority lvl\n" \
-               "\t   group_by_node_name\t1 priority group per target node\n" \
-               "\n" \
-               "\tdevice\t\tlimit scope to the device's multipath\n" \
-               "\t\t\t(udev-style $DEVNAME reference, eg /dev/sdb\n" \
-               "\t\t\tor major:minor or a device map name)\n" \
+               "\n"
+               "Where:\n"
+               "  -h      print this usage text\n" \
+               "  -l      show multipath topology (sysfs and DM info)\n" \
+               "  -ll     show multipath topology (maximum info)\n" \
+               "  -f      flush a multipath device map\n" \
+               "  -F      flush all multipath device maps\n" \
+               "  -d      dry run, do not create or update devmaps\n" \
+               "  -r      force devmap reload\n" \
+               "  -p      policy failover|multibus|group_by_serial|group_by_prio\n" \
+               "  -b fil  bindings file location\n" \
+               "  -p pol  force all maps to specified path grouping policy :\n" \
+               "          . failover            one path per priority group\n" \
+               "          . multibus            all paths in one priority group\n" \
+               "          . group_by_serial     one priority group per serial\n" \
+               "          . group_by_prio       one priority group per priority lvl\n" \
+               "          . group_by_node_name  one priority group per target node\n" \
+               "  -v lvl  verbosity level\n" \
+               "          . 0 no output\n" \
+               "          . 1 print created devmap names only\n" \
+               "          . 2 default verbosity\n" \
+               "          . 3 print debug information\n" \
+               "  dev     action limited to:\n" \
+               "          . multipath named 'dev' (ex: mpath0) or\n" \
+               "          . multipath whose wwid is 'dev' (ex: 60051..)\n" \
+               "          . multipath including the path named 'dev' (ex: /dev/sda)\n" \
+               "          . multipath including the path with maj:min 'dev' (ex: 8:0)\n" \
                );
 
        exit(1);
@@ -298,7 +303,7 @@ configure (void)
        /*
         * core logic entry point
         */
-       r = coalesce_paths(&vecs, NULL, NULL);
+       r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload);
 
 out:
        if (refwwid)
@@ -341,7 +346,7 @@ main (int argc, char *argv[])
                condlog(0, "multipath tools need sysfs mounted");
                exit(1);
        }
-       while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:")) != EOF ) {
+       while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:r")) != EOF ) {
                switch(arg) {
                case 1: printf("optarg : %s\n",optarg);
                        break;
@@ -384,6 +389,9 @@ main (int argc, char *argv[])
                                usage(argv[0]);
                        }                
                        break;
+               case 'r':
+                       conf->force_reload = 1;
+                       break;
                case 'h':
                        usage(argv[0]);
                case ':':
index ac9cd36..8c752d2 100644 (file)
@@ -266,7 +266,7 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs)
        refwwid = get_refwwid(dev->kernel, DEV_DEVMAP, vecs->pathvec);
 
        if (refwwid) {
-               r = coalesce_paths(vecs, NULL, refwwid);
+               r = coalesce_paths(vecs, NULL, refwwid, 0);
                dm_lib_release();
        }
 
@@ -1080,7 +1080,7 @@ configure (struct vectors * vecs, int start_waiters)
        /*
         * create new set of maps & push changed ones into dm
         */
-       if (coalesce_paths(vecs, mpvec, NULL))
+       if (coalesce_paths(vecs, mpvec, NULL, 0))
                return 1;
 
        /*