Merge branch 'master' of git://git.kernel.org/pub/scm/linux/storage/multipath-tools/
[platform/upstream/multipath-tools.git] / libmultipath / devmapper.c
index 6b289cf..fb69ee8 100644 (file)
@@ -10,7 +10,6 @@
 #include <string.h>
 #include <libdevmapper.h>
 #include <ctype.h>
-#include <linux/kdev_t.h>
 #include <unistd.h>
 #include <errno.h>
 
@@ -78,7 +77,7 @@ dm_libprereq (void)
 {
        char version[64];
        int v[3];
-       int minv[3] = {1, 2, 8};
+       int minv[3] = {1, 2, 38};
 
        dm_get_library_version(version, sizeof(version));
        condlog(3, "libdevmapper version %s", version);
@@ -149,9 +148,11 @@ dm_prereq (void)
        return dm_drvprereq(TGT_MPATH);
 }
 
-extern int
-dm_simplecmd (int task, const char *name) {
+static int
+dm_simplecmd (int task, const char *name, int no_flush, int need_sync) {
        int r = 0;
+       int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME ||
+                                           task == DM_DEVICE_REMOVE));
        struct dm_task *dmt;
 
        if (!(dmt = dm_task_create (task)))
@@ -163,9 +164,12 @@ dm_simplecmd (int task, const char *name) {
        dm_task_no_open_count(dmt);
        dm_task_skip_lockfs(dmt);       /* for DM_DEVICE_RESUME */
 #ifdef LIBDM_API_FLUSH
-       dm_task_no_flush(dmt);          /* for DM_DEVICE_SUSPEND/RESUME */
+       if (no_flush)
+               dm_task_no_flush(dmt);          /* for DM_DEVICE_SUSPEND/RESUME */
 #endif
 
+       if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, 0))
+               goto out;
        r = dm_task_run (dmt);
 
        out:
@@ -174,8 +178,17 @@ dm_simplecmd (int task, const char *name) {
 }
 
 extern int
-dm_addmap (int task, const char *name, const char *target,
-          const char *params, unsigned long long size, const char *uuid,
+dm_simplecmd_flush (int task, const char *name, int needsync) {
+       return dm_simplecmd(task, name, 0, needsync);
+}
+
+extern int
+dm_simplecmd_noflush (int task, const char *name) {
+       return dm_simplecmd(task, name, 1, 1);
+}
+
+extern int
+dm_addmap (int task, const char *target, struct multipath *mpp, int use_uuid,
           int ro) {
        int r = 0;
        struct dm_task *dmt;
@@ -184,29 +197,42 @@ dm_addmap (int task, const char *name, const char *target,
        if (!(dmt = dm_task_create (task)))
                return 0;
 
-       if (!dm_task_set_name (dmt, name))
+       if (!dm_task_set_name (dmt, mpp->alias))
                goto addout;
 
-       if (!dm_task_add_target (dmt, 0, size, target, params))
+       if (!dm_task_add_target (dmt, 0, mpp->size, target, mpp->params))
                goto addout;
 
        if (ro)
                dm_task_set_ro(dmt);
 
-       if (uuid){
-               prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(uuid) + 1);
+       if (use_uuid && mpp->wwid){
+               prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(mpp->wwid) + 1);
                if (!prefixed_uuid) {
                        condlog(0, "cannot create prefixed uuid : %s\n",
                                strerror(errno));
                        goto addout;
                }
-               sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid);
+               sprintf(prefixed_uuid, UUID_PREFIX "%s", mpp->wwid);
                if (!dm_task_set_uuid(dmt, prefixed_uuid))
                        goto freeout;
        }
 
+       if (mpp->attribute_flags & (1 << ATTR_MODE) &&
+           !dm_task_set_mode(dmt, mpp->mode))
+               goto freeout;
+       if (mpp->attribute_flags & (1 << ATTR_UID) &&
+           !dm_task_set_uid(dmt, mpp->uid))
+               goto freeout;
+       if (mpp->attribute_flags & (1 << ATTR_GID) &&
+           !dm_task_set_gid(dmt, mpp->gid))
+               goto freeout;
+
        dm_task_no_open_count(dmt);
 
+       if (task == DM_DEVICE_CREATE &&
+           !dm_task_set_cookie(dmt, &conf->cookie, 0))
+               goto freeout;
        r = dm_task_run (dmt);
 
        freeout:
@@ -220,19 +246,17 @@ dm_addmap (int task, const char *name, const char *target,
 }
 
 static int
-_dm_addmap_create (const char *name, const char *params,
-                 unsigned long long size, const char *uuid, int ro) {
+_dm_addmap_create (struct multipath *mpp, int ro) {
        int r;
-       r = dm_addmap(DM_DEVICE_CREATE, name, TGT_MPATH, params, size, uuid,
-                     ro);
+       r = dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, 1, ro);
        /*
         * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
         * Failing the second part leaves an empty map. Clean it up.
         */
-       if (!r && dm_map_present(name)) {
+       if (!r && dm_map_present(mpp->alias)) {
                condlog(3, "%s: failed to load map (a path might be in use)",
-                       name);
-               dm_flush_map(name);
+                       mpp->alias);
+               dm_flush_map_nosync(mpp->alias);
        }
        return r;
 }
@@ -241,29 +265,23 @@ _dm_addmap_create (const char *name, const char *params,
 #define ADDMAP_RO 1
 
 extern int
-dm_addmap_create (const char *name, const char *params,
-                 unsigned long long size, const char *uuid) {
-       return _dm_addmap_create(name, params, size, uuid, ADDMAP_RW);
+dm_addmap_create (struct multipath *mpp) {
+       return _dm_addmap_create(mpp, ADDMAP_RW);
 }
 
 extern int
-dm_addmap_create_ro (const char *name, const char *params,
-                 unsigned long long size, const char *uuid) {
-       return _dm_addmap_create(name, params, size, uuid, ADDMAP_RO);
+dm_addmap_create_ro (struct multipath *mpp) {
+       return _dm_addmap_create(mpp, ADDMAP_RO);
 }
 
 extern int
-dm_addmap_reload (const char *name, const char *params,
-                 unsigned long long size, const char *uuid) {
-       return dm_addmap(DM_DEVICE_RELOAD, name, TGT_MPATH, params, size, uuid,
-                        ADDMAP_RW);
+dm_addmap_reload (struct multipath *mpp) {
+       return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, 0, ADDMAP_RW);
 }
 
 extern int
-dm_addmap_reload_ro (const char *name, const char *params,
-                    unsigned long long size, const char *uuid) {
-       return dm_addmap(DM_DEVICE_RELOAD, name, TGT_MPATH, params, size, uuid,
-                        ADDMAP_RO);
+dm_addmap_reload_ro (struct multipath *mpp) {
+       return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, 0, ADDMAP_RO);
 }
 
 extern int
@@ -518,7 +536,7 @@ out:
 }
 
 extern int
-dm_flush_map (const char * mapname)
+_dm_flush_map (const char * mapname, int need_sync)
 {
        int r;
 
@@ -526,9 +544,9 @@ dm_flush_map (const char * mapname)
                return 0;
 
        if (dm_type(mapname, TGT_MPATH) <= 0)
-               return 1;
+               return 0; /* nothing to do */
 
-       if (dm_remove_partmaps(mapname))
+       if (dm_remove_partmaps(mapname, need_sync))
                return 1;
 
        if (dm_get_opencount(mapname)) {
@@ -536,7 +554,7 @@ dm_flush_map (const char * mapname)
                return 1;
        }
 
-       r = dm_simplecmd(DM_DEVICE_REMOVE, mapname);
+       r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync);
 
        if (r) {
                condlog(4, "multipath map %s removed", mapname);
@@ -759,35 +777,49 @@ out:
        return r;
 }
 
-extern int
-dm_get_name(char *uuid, char *name)
+extern char *
+dm_get_name(char *uuid)
 {
-       vector vec;
-       struct multipath *mpp;
-       int i, rc = 0;
-
-       vec = vector_alloc();
+       struct dm_task *dmt;
+       struct dm_info info;
+       char *prefixed_uuid, *name = NULL;
+       const char *nametmp;
 
-       if (!vec)
-               return 0;
+       dmt = dm_task_create(DM_DEVICE_INFO);
+       if (!dmt)
+               return NULL;
 
-       if (dm_get_maps(vec)) {
-               goto out;
+       prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(uuid) + 1);
+       if (!prefixed_uuid) {
+               condlog(0, "cannot create prefixed uuid : %s\n",
+                       strerror(errno));
+               goto freeout;
        }
+       sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid);
+       if (!dm_task_set_uuid(dmt, prefixed_uuid))
+               goto freeout;
 
-       vector_foreach_slot(vec, mpp, i) {
-               if (!strcmp(uuid, mpp->wwid)) {
-                       strcpy(name, mpp->alias);
-                       rc=1;
-                       break;
-               }
-       }
-out:
-       vector_foreach_slot(vec, mpp, i) {
-               free_multipath(mpp, KEEP_PATHS);
+       if (!dm_task_run(dmt))
+               goto freeout;
+
+       if (!dm_task_get_info(dmt, &info) || !info.exists)
+               goto freeout;
+
+       nametmp = dm_task_get_name(dmt);
+       if (nametmp && strlen(nametmp)) {
+               name = MALLOC(strlen(nametmp) + 1);
+               if (name)
+                       strcpy(name, nametmp);
+       } else {
+               condlog(2, "%s: no device-mapper name found", uuid);
        }
-       vector_free(vec);
-       return rc;
+
+freeout:
+       if (prefixed_uuid)
+               FREE(prefixed_uuid);
+       dm_task_destroy(dmt);
+
+       return name;
 }
 
 int
@@ -872,7 +904,7 @@ bad:
 }
 
 int
-dm_remove_partmaps (const char * mapname)
+dm_remove_partmaps (const char * mapname, int need_sync)
 {
        struct dm_task *dmt;
        struct dm_names *names;
@@ -935,7 +967,7 @@ dm_remove_partmaps (const char * mapname)
                                 */
                                condlog(4, "partition map %s removed",
                                        names->name);
-                               dm_simplecmd(DM_DEVICE_REMOVE, names->name);
+                               dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name, need_sync);
                   }
 
                next = names->next;
@@ -985,8 +1017,11 @@ dm_get_info (char * mapname, struct dm_info ** dmi)
 
        r = 0;
 out:
-       if (r)
+       if (r) {
                memset(*dmi, 0, sizeof(struct dm_info));
+               FREE(*dmi);
+               *dmi = NULL;
+       }
 
        if (dmt)
                dm_task_destroy(dmt);
@@ -1088,6 +1123,8 @@ dm_rename (char * old, char * new)
 
        dm_task_no_open_count(dmt);
 
+       if (!dm_task_set_cookie(dmt, &conf->cookie, 0))
+               goto out;
        if (!dm_task_run(dmt))
                goto out;