chiark / gitweb /
[PATCH] extras multipath update
authorchristophe.varoqui@free.fr <christophe.varoqui@free.fr>
Tue, 23 Dec 2003 04:49:22 +0000 (20:49 -0800)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:13:10 +0000 (21:13 -0700)
An important one, against stock udev-009 :

 2003-12-20 multipath-010
        * big ChangeLog update
        * start to give a little control over target params :
          introduce cmdline arg -i to control polling interval
        * cope with hotplug-style calling convention :
          ie "multipath scsi $DEVPATH" ... to avoid messing with
          online maps not concerned by an event
        * example hotplug agent to drop in /etc/hotplug.d/scsi
        * revert the run & resched patch : unless someone proves me
          wrong, this was overdesigned
        * move commented out functions in unused.c
        * update multipath target params to "udm[23] style"
        * mp target now supports nr_path == 1, so do we
        * add gratuitous free()
        * push version forward

extras/multipath/ChangeLog
extras/multipath/main.c
extras/multipath/main.h
extras/multipath/multipath.hotplug [new file with mode: 0644]
extras/multipath/unsused.c [new file with mode: 0644]

index f3014cf..f31fbf4 100644 (file)
@@ -1,3 +1,60 @@
+2003-12-20 multipath-010
+       * big ChangeLog update
+       * start to give a little control over target params :
+         introduce cmdline arg -i to control polling interval
+       * cope with hotplug-style calling convention :
+         ie "multipath scsi $DEVPATH" ... to avoid messing with
+         online maps not concerned by an event
+       * example hotplug agent to drop in /etc/hotplug.d/scsi
+       * revert the run & resched patch : unless someone proves me
+         wrong, this was overdesigned
+       * move commented out functions in unused.c
+       * update multipath target params to "udm[23] style"
+       * mp target now supports nr_path == 1, so do we
+       * add gratuitous free()
+       * push version forward
+2003-12-15 multipath-009
+       * Make the HW-specific get_unique_id switch pretty
+       * Prepare to field-test by whitelisting all known fibre array,
+         try to fetch WWID from the standard EVPD 0x83 off 8 for everyone
+       * configure the multipath target with round-robin path selector and
+         conservative default for a start (udm1 style) :
+         yes it makes this release the firstreally useful one.
+       * temporarily disable map creation for single path device
+         due to current restrictive defaults in the kernel target.
+         Sistina should work it out.
+       * correct the strncmp logic in blacklist function.
+       * update the Makefiles to autodetect libgcc.a & gcc includes
+         "ulibc-style". Factorisation of udevdirs & others niceties
+       * drop a hint about absent /dev/sd? on failed open()
+       * implement a reschedule flag in /var/run.
+         Last thing the prog do before exit is check if a call to multipath
+         was done (but canceled by /var/run/multipath.run check) during its
+         execution. If so restart themain loop.
+       * implement a blacklist of sysfs bdev to not bother with for now
+         (hd,md, dm, sr, scd, ram, raw).
+         This avoid sending SG_IO to unappropiate devices.
+       * Adds a /var/run/multipath.run handling to avoid simultaneous runs.
+       * Remove a commented-out "printf"
+       * drop a libdevmapper copy in extras/multipath;
+         maybe discussions w/Sistina folks will bring a better solution in the future.
+       * drop a putchar usage in libdevmapper to compile cleanly with klibc
+       * drop another such usage of my own in main.c
+       * massage the Makefile to compile libdevmapper against klibc
+       * use "ld" to produce the binary rather than "gcc -static"
+       * stop being stupid w/ uneeded major, minor & dev in main.c:dm_mk_node()
+       * reverse to creating striped target for now because the multipath target
+         is more hairy than expected initialy
+       * push the version code to 009 to be in synch w/ udev
+2003-11-27 multipath-007
+       * removes sg_err.[ch] deps
+       * makes sure the core code play nice with klibc
+       * port the sysfs calls to dlist helpers
+       * links against udev's sysfs (need libsysfs.a & dlist.a)
+       * finally define DM_TARGET as "multipath" as Joe posted the code today (not tested yet)
+       * push version forward (do you want it in sync with udev version?)
+2003-11-19
+       * merged in udev-006 tree
 2003-09-18  Christophe Varoqui <christophe.varoqui@free.fr>
        * multipath 0.0.1 released.
        * Initial release.
index 9402888..39b4a9f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Soft:        Description here...
+ * Soft:        multipath device mapper target autoconfig
  *
  * Version:     $Id: main.h,v 0.0.1 2003/09/18 15:13:38 cvaroqui Exp $
  *
@@ -258,38 +258,80 @@ get_all_paths_sysfs(struct env * conf, struct path * all_paths)
        struct sysfs_directory * sdir;
        struct sysfs_directory * devp;
        struct sysfs_link * linkp;
+       char refwwid[WWID_SIZE];
+       char empty_buff[WWID_SIZE];
        char buff[FILE_NAME_SIZE];
+       char path[FILE_NAME_SIZE];
+       struct path curpath;
 
-       char block_path[FILE_NAME_SIZE];
+       /* if called from udev, only consider the paths that relate to */
+       /* to the device pointed by conf.hotplugdev */
+       memset(empty_buff, 0, WWID_SIZE);
+       memset(refwwid, 0, WWID_SIZE);
+       if (strncmp("/devices", conf->hotplugdev, 8) == 0) {
+               sprintf(buff, "%s%s/block",
+                       conf->sysfs_path, conf->hotplugdev);
+               memset(conf->hotplugdev, 0, FILE_NAME_SIZE);
+               readlink(buff, conf->hotplugdev, FILE_NAME_SIZE);
+               basename(conf->hotplugdev, buff);
+               sprintf(curpath.sg_dev, "/dev/%s", buff);
+
+               if ((sg_fd = open(curpath.sg_dev, O_RDONLY)) < 0)
+                       exit(1);
+
+               get_lun_strings(sg_fd, &curpath);
+               get_unique_id(sg_fd, &curpath);
+               strcpy(refwwid, curpath.wwid);
+               memset(&curpath, 0, sizeof(path));
+       }
 
-       sprintf(block_path, "%s/block", conf->sysfs_path);
-       sdir = sysfs_open_directory(block_path);
+       sprintf(path, "%s/block", conf->sysfs_path);
+       sdir = sysfs_open_directory(path);
        sysfs_read_directory(sdir);
+
        dlist_for_each_data(sdir->subdirs, devp, struct sysfs_directory) {
                if (blacklist(devp->name))
                        continue;
+
                sysfs_read_directory(devp);
+
                if(devp->links == NULL)
                        continue;
+
                dlist_for_each_data(devp->links, linkp, struct sysfs_link) {
                        if (!strncmp(linkp->name, "device", 6))
                                break;
                }
+
                if (linkp == NULL) {
                        continue;
                }
 
                basename(devp->path, buff);
-               sprintf(all_paths[k].sg_dev, "/dev/%s", buff);
-               strcpy(all_paths[k].dev, all_paths[k].sg_dev);
-               if ((sg_fd = open(all_paths[k].sg_dev, O_RDONLY)) < 0) {
+               sprintf(curpath.sg_dev, "/dev/%s", buff);
+
+               if ((sg_fd = open(curpath.sg_dev, O_RDONLY)) < 0) {
                        if (conf->verbose)
-                               fprintf(stderr, "can't open %s. mknod ?",
-                                       all_paths[k].sg_dev); 
+                               fprintf(stderr, "can't open %s\n",
+                                       curpath.sg_dev); 
                        continue;
                }
-               get_lun_strings(sg_fd, &all_paths[k]);
-               get_unique_id(sg_fd, &all_paths[k]);
+
+               get_lun_strings(sg_fd, &curpath);
+               get_unique_id(sg_fd, &curpath);
+
+               if (memcmp(empty_buff, refwwid, WWID_SIZE) != 0 && 
+                   strncmp(curpath.wwid, refwwid, WWID_SIZE) != 0) {
+                       memset(&curpath, 0, sizeof(path));
+                       continue;
+               }
+
+               strcpy(all_paths[k].sg_dev, curpath.sg_dev);
+               strcpy(all_paths[k].dev, curpath.sg_dev);
+               strcpy(all_paths[k].wwid, curpath.wwid);
+               strcpy(all_paths[k].vendor_id, curpath.vendor_id);
+               strcpy(all_paths[k].product_id, curpath.product_id);
+               memset(&curpath, 0, sizeof(path));
                all_paths[k].state = do_tur(sg_fd);
                close(sg_fd);
                basename(linkp->target, buff);
@@ -301,7 +343,6 @@ get_all_paths_sysfs(struct env * conf, struct path * all_paths)
                k++;
        }
        sysfs_close_directory(sdir);
-
        return 0;
 }
 
@@ -562,26 +603,6 @@ make_dm_node(char * str)
 
 }
 
-/* future use ?
-static int
-del_map(char * str) {
-       struct dm_task *dmt;
-
-       if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
-               return 0;
-       if (!dm_task_set_name(dmt, str))
-               goto delout;
-       if (!dm_task_run(dmt))
-               goto delout;
-
-       printf("Deleted device map : %s\n", str);
-
-       delout:
-       dm_task_destroy(dmt);
-       return 1;
-}
-*/
-
 static int
 add_map(struct env * conf, struct path * all_paths,
        struct multipath * mp, int index, int op)
@@ -593,15 +614,9 @@ add_map(struct env * conf, struct path * all_paths,
        long size = -1;
 
        /* defaults for multipath target */
-       int dm_nr_path_args         = 2;
-       int dm_path_test_int        = 10;
+       int dm_pg_prio              = 1;
        char * dm_ps_name           = "round-robin";
-       int dm_ps_nr_args           = 2;
-       int dm_path_failback_int    = 10;
-       int dm_path_nr_fail         = 2;
-       int dm_ps_prio              = 1;
-       int dm_ps_min_io            = 2;
-
+       int dm_ps_nr_args           = 0;
 
        if (!(dmt = dm_task_create(op)))
                return 0;
@@ -618,14 +633,13 @@ add_map(struct env * conf, struct path * all_paths,
        }
        if (np == 0)
                goto addout;
-       /* temporarily disable creation of single path maps */
-       /* Sistina should modify the target limits */
-       if (np < 2)
+
+       if (np < 1)
                goto addout;
 
-       params_p += sprintf(params_p, "%i %i %i %s %i",
-                           np, dm_nr_path_args, dm_path_test_int,
-                           dm_ps_name, dm_ps_nr_args);
+       params_p += sprintf(params_p, "%i %i %s %i %i",
+                           conf->dm_path_test_int, dm_pg_prio, 
+                           dm_ps_name, np, dm_ps_nr_args);
        
        for (i=0; i<=mp[index].npaths; i++) {
                if (( 0 == all_paths[PINDEX(index,i)].state) ||
@@ -633,10 +647,8 @@ add_map(struct env * conf, struct path * all_paths,
                        continue;
                if (size < 0)
                        size = get_disk_size(conf, all_paths[PINDEX(index,0)].dev);
-               params_p += sprintf(params_p, " %s %i %i %i %i",
-                                   all_paths[PINDEX(index,i)].dev,
-                                   dm_path_failback_int, dm_path_nr_fail,
-                                   dm_ps_prio, dm_ps_min_io);
+               params_p += sprintf(params_p, " %s",
+                                   all_paths[PINDEX(index,i)].dev);
        }
 
        if (size < 0)
@@ -665,44 +677,6 @@ add_map(struct env * conf, struct path * all_paths,
        return 1;
 }
 
-/*
-static int
-get_table(const char * str)
-{
-       int r = 0;
-       struct dm_task *dmt;
-       void *next = NULL;
-       uint64_t start, length;
-       char *target_type = NULL;
-       char *params;
-
-        if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
-                return 0;
-
-        if (!dm_task_set_name(dmt, str))
-                goto out;
-
-        if (!dm_task_run(dmt))
-                goto out;
-
-        do {
-                next = dm_get_next_target(dmt, next, &start, &length,
-                                          &target_type, &params);
-                if (target_type) {
-                        printf("%" PRIu64 " %" PRIu64 " %s %s\n",
-                               start, length, target_type, params);
-                }
-        } while (next);
-
-        r = 1;
-
-      out:
-        dm_task_destroy(dmt);
-        return r;
-
-}
-*/
-
 static int
 map_present(char * str)
 {
@@ -740,28 +714,18 @@ static void
 usage(char * progname)
 {
        fprintf(stderr, VERSION_STRING);
-       fprintf(stderr, "Usage: %s [-v|-q] [-d] [-m max_devs]\n", progname);
-       fprintf(stderr, "\t-v\t\tverbose, print all paths and multipaths\n");
-       fprintf(stderr, "\t-q\t\tquiet, no output at all\n");
+       fprintf(stderr, "Usage: %s [-v|-q] [-d] [-i int] [-m max_devs]\n", progname);
        fprintf(stderr, "\t-d\t\tdry run, do not create or update devmaps\n");
+       fprintf(stderr, "\t-i\t\tmultipath target param : polling interval\n");
        fprintf(stderr, "\t-m max_devs\tscan {max_devs} devices at most\n");
+       fprintf(stderr, "\t-q\t\tquiet, no output at all\n");
+       fprintf(stderr, "\t-v\t\tverbose, print all paths and multipaths\n");
        exit(1);
 }
 
-static int
-filepresent(char * run) {
-       struct stat buf;
-
-       if(!stat(run, &buf))
-               return 1;
-       return 0;
-}
-
 int
 main(int argc, char *argv[])
 {
-       char * run = "/var/run/multipath.run";
-       char * resched = "/var/run/multipath.reschedule";
        struct multipath * mp;
        struct path * all_paths;
        struct scsi_dev * all_scsi_ids;
@@ -774,6 +738,7 @@ main(int argc, char *argv[])
        conf.verbose = 0;       /* 1 == Print all_paths and mp */
        conf.quiet = 0;         /* 1 == Do not even print devmaps */
        conf.with_sysfs = 0;    /* Default to compat / suboptimal behaviour */
+       conf.dm_path_test_int = 10;
 
        /* kindly provided by libsysfs */
        if (0 == sysfs_get_mnt_path(conf.sysfs_path, FILE_NAME_SIZE))
@@ -794,6 +759,10 @@ main(int argc, char *argv[])
                        conf.quiet = 1;
                } else if (0 == strcmp("-d", argv[i]))
                        conf.dry_run = 1;
+               else if (0 == strcmp("-i", argv[i]))
+                       conf.dm_path_test_int = atoi(argv[++i]);
+               else if (0 == strcmp("scsi", argv[i]))
+                       strcpy(conf.hotplugdev, argv[++i]);
                else if (*argv[i] == '-') {
                        fprintf(stderr, "Unknown switch: %s\n", argv[i]);
                        usage(argv[0]);
@@ -804,27 +773,11 @@ main(int argc, char *argv[])
 
        }
 
-       if (filepresent(run)) {
-               if (conf.verbose) {
-                       fprintf(stderr, "Already running.\n");
-                       fprintf(stderr, "If you know what you do, please ");
-                       fprintf(stderr, "remove %s\n", run);
-               }
-               /* leave a trace that we were called while already running */
-               open(resched, O_CREAT);
-               return 1;
-       }
-
        /* dynamic allocations */
        mp = malloc(conf.max_devs * sizeof(struct multipath));
        all_paths = malloc(conf.max_devs * sizeof(struct path));
        all_scsi_ids = malloc(conf.max_devs * sizeof(struct scsi_dev));
-       if (mp == NULL || all_paths == NULL || all_scsi_ids == NULL) {
-               unlink(run);
-               exit(1);
-       }
-start:
-       if(!open(run, O_CREAT))
+       if (mp == NULL || all_paths == NULL || all_scsi_ids == NULL)
                exit(1);
 
        if (!conf.with_sysfs) {
@@ -842,10 +795,8 @@ start:
                fprintf(stdout, "\n");
        }
 
-       if (conf.dry_run) {
-               unlink(run);
+       if (conf.dry_run)
                exit(0);
-       }
 
        for (k=0; k<=nmp; k++) {
                if (map_present(mp[k].wwid)) {
@@ -854,13 +805,11 @@ start:
                        add_map(&conf, all_paths, mp, k, DM_DEVICE_CREATE);
                }
        }
-       unlink(run);
 
-       /* start again if we were ask to during this process run */
-       /* ie. do not loose an event-asked run */
-       if (filepresent(resched)) {
-               unlink(resched);
-               goto start;
-       }
+       /* free allocs */
+       free(mp);
+       free(all_paths);
+       free(all_scsi_ids);
+
        exit(0);
 }
index d6dfb14..0c5620f 100644 (file)
@@ -99,14 +99,16 @@ struct env {
        int quiet;
        int dry_run;
        int with_sysfs;
+       int dm_path_test_int;
        char sysfs_path[FILE_NAME_SIZE];
+       char hotplugdev[FILE_NAME_SIZE];
 };
 
 /* Build version */
 #define PROG    "multipath"
 
-#define VERSION_CODE 0x000009
-#define DATE_CODE    0x0C0503
+#define VERSION_CODE 0x000010
+#define DATE_CODE    0x0C1503
 
 #define MULTIPATH_VERSION(version)     \
        (version >> 16) & 0xFF,         \
diff --git a/extras/multipath/multipath.hotplug b/extras/multipath/multipath.hotplug
new file mode 100644 (file)
index 0000000..db7894c
--- /dev/null
@@ -0,0 +1,3 @@
+. /etc/hotplug/hotplug.functions
+sleep 1
+mesg `/root/multipath scsi $DEVPATH`
diff --git a/extras/multipath/unsused.c b/extras/multipath/unsused.c
new file mode 100644 (file)
index 0000000..ecdd695
--- /dev/null
@@ -0,0 +1,52 @@
+static int
+del_map(char * str) {
+        struct dm_task *dmt;
+
+        if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
+                return 0;
+        if (!dm_task_set_name(dmt, str))
+                goto delout;
+        if (!dm_task_run(dmt))
+                goto delout;
+
+        printf("Deleted device map : %s\n", str);
+
+        delout:
+        dm_task_destroy(dmt);
+        return 1;
+}
+
+get_table(const char * str)
+{
+        int r = 0;
+        struct dm_task *dmt;
+        void *next = NULL;
+        uint64_t start, length;
+        char *target_type = NULL;
+        char *params;
+
+        if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+                return 0;
+
+        if (!dm_task_set_name(dmt, str))
+                goto out;
+
+        if (!dm_task_run(dmt))
+                goto out;
+
+        do {
+                next = dm_get_next_target(dmt, next, &start, &length,
+                                          &target_type, &params);
+                if (target_type) {
+                        printf("%" PRIu64 " %" PRIu64 " %s %s\n",
+                               start, length, target_type, params);
+                }
+        } while (next);
+
+        r = 1;
+
+      out:
+        dm_task_destroy(dmt);
+        return r;
+
+}