[multipath] map flushing to remove layered DM-partitioned too
authorroot <root@xa-s05.(none)>
Wed, 22 Jun 2005 13:04:27 +0000 (15:04 +0200)
committerroot <root@xa-s05.(none)>
Wed, 22 Jun 2005 13:04:27 +0000 (15:04 +0200)
"multipath -F" or "multipath -f $map" refused to remove a map if kpartx
layered partioned upon it. This patch should take care of that.

libmultipath/devmapper.c
libmultipath/devmapper.h
multipath/main.c
multipath/main.h

index 9c0f6d2..10b2c2b 100644 (file)
@@ -10,6 +10,7 @@
 #include "structs.h"
 #include "debug.h"
 #include "memory.h"
+#include "devmapper.h"
 
 #define MAX_WAIT 5
 #define LOOPS_PER_SEC 5
@@ -224,6 +225,35 @@ out:
        return r;
 }
 
+static int
+dm_dev_t (char * mapname, char * dev_t, int len)
+{
+       int r = 1;
+       struct dm_task *dmt;
+       struct dm_info info;
+
+       if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
+               return 0;
+
+       if (!dm_task_set_name(dmt, mapname))
+               goto out;
+
+       if (!dm_task_run(dmt))
+               goto out;
+
+       if (!dm_task_get_info(dmt, &info))
+               goto out;
+
+       r = info.open_count;
+       if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
+                   goto out;
+
+       r = 0;
+out:
+       dm_task_destroy(dmt);
+       return r;
+}
+       
 int
 dm_get_opencount (char * mapname)
 {
@@ -277,10 +307,27 @@ out:
 extern int
 dm_flush_map (char * mapname, char * type)
 {
-       if (!dm_type(mapname, type) || dm_get_opencount(mapname))
+       int r;
+
+       if (!dm_map_present(mapname))
+               return 0;
+
+       if (!dm_type(mapname, type))
                return 1;
 
-       return dm_simplecmd(DM_DEVICE_REMOVE, mapname);
+       if (dm_remove_partmaps(mapname))
+               return 1;
+
+       if (dm_get_opencount(mapname))
+               return 1;
+
+       r = dm_simplecmd(DM_DEVICE_REMOVE, mapname);
+
+       if (r) {
+               condlog(4, "multipath map %s removed", mapname);
+               return 0;
+       }
+       return 1;
 }
 
 extern int
@@ -589,3 +636,79 @@ bad:
        return NULL;
 }
 
+int
+dm_remove_partmaps (char * mapname)
+{
+       struct dm_task *dmt;
+       struct dm_names *names;
+       unsigned next = 0;
+       char params[PARAMS_SIZE];
+       unsigned long size;
+       char dev_t[32];
+       int r = 1;
+
+       if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
+               return 1;
+
+       dm_task_no_open_count(dmt);
+
+       if (!dm_task_run(dmt))
+               goto out;
+
+       if (!(names = dm_task_get_names(dmt)))
+               goto out;
+
+       if (!names->dev) {
+               r = 0; /* this is perfectly valid */
+               goto out;
+       }
+
+       if (dm_dev_t(mapname, &dev_t[0], 32))
+               goto out;
+
+       do {
+               if (
+                   /*
+                    * if devmap target is "linear"
+                    */
+                   dm_type(names->name, "linear") &&
+
+                   /*
+                    * and the multipath mapname and the part mapname start
+                    * the same
+                    */
+                   !strncmp(names->name, mapname, strlen(mapname)) &&
+
+                   /*
+                    * and the opencount is 0 for us to allow removal
+                    */
+                   !dm_get_opencount(names->name) &&
+
+                   /*
+                    * and we can fetch the map table from the kernel
+                    */
+                   !dm_get_map(names->name, &size, &params[0]) &&
+
+                   /*
+                    * and the table maps over the multipath map
+                    */
+                   strstr(params, dev_t)
+                  ) {
+                               /*
+                                * then it's a kpartx generated partition.
+                                * remove it.
+                                */
+                               condlog(4, "partition map %s removed",
+                                       names->name);
+                               dm_simplecmd(DM_DEVICE_REMOVE, names->name);
+                  }
+
+               next = names->next;
+               names = (void *) names + next;
+       } while (next);
+
+       r = 0;
+out:
+       dm_task_destroy (dmt);
+       return r;
+}
index f0036c6..3600c91 100644 (file)
@@ -5,6 +5,7 @@ int dm_map_present (char *);
 int dm_get_map(char *, unsigned long *, char *);
 int dm_get_status(char *, char *);
 int dm_type(char *, char *);
+int dm_flush_map (char *, char *);
 int dm_flush_maps (char *);
 int dm_fail_path(char * mapname, char * path);
 int dm_reinstate(char * mapname, char * path);
@@ -15,3 +16,4 @@ int dm_get_maps (vector mp, char * type);
 int dm_geteventnr (char *name);
 int dm_get_minor (char *name);
 char * dm_mapname(int major, int minor, char *type);
+int dm_remove_partmaps (char * mapname);
index 5f287cf..5b571d9 100644 (file)
@@ -892,8 +892,7 @@ main (int argc, char *argv[])
                        conf->remove = 1;
                        break;
                case 'F':
-                       dm_flush_maps(DEFAULT_TARGET);
-                       goto out;
+                       conf->remove = 2;
                        break;
                case 'l':
                        conf->list = 1;
@@ -942,16 +941,18 @@ main (int argc, char *argv[])
 
        }
 
-       if (conf->remove) {
-               if (conf->dev_type == DEV_DEVMAP) {
-                       condlog(4, "remove %s map", conf->dev);
+       if (conf->remove == FLUSH_ONE) {
+               if (conf->dev_type == DEV_DEVMAP)
                        dm_flush_map(conf->dev, DEFAULT_TARGET);
-               }
                else
                        condlog(0, "must provide a map name to remove");
 
                goto out;
        }
+       else if (conf->remove == FLUSH_ALL) {
+               dm_flush_maps(DEFAULT_TARGET);
+               goto out;
+       }
 
        /*
         * allocate core vectors to store paths and multipaths
index 0f2b046..d8bb16f 100644 (file)
@@ -35,6 +35,9 @@ enum actions {
        ACT_CREATE
 };
 
+#define FLUSH_ONE 1
+#define FLUSH_ALL 2
+
 /*
  * Build version
  */