summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2010-05-17 14:03:38 -0500
committerChristophe Varoqui <christophe.varoqui@opensvc.com>2010-05-20 06:49:03 +0200
commit8d63b33d0996e141a2451df552b062b908db15bc (patch)
tree9371f7a2edae027b1061ac4283043029dfb7560d
parent07352dffc44c6e6b297d0c8cb804e6f08003be1d (diff)
downloadmultipath-tools-8d63b33d0996e141a2451df552b062b908db15bc.tar.gz
multipath-tools-8d63b33d0996e141a2451df552b062b908db15bc.tar.bz2
multipath-tools-8d63b33d0996e141a2451df552b062b908db15bc.zip
multipath: add udev sync support.
device-mapper in now able to synchronize operations through udev. This patch allows multipath and kpartx to make use of this feature. If kpartx is run with "-s", it waits for the partitions to be created before returning. Multipath will now always wait for the devices to be created before returning. This feature requires dm_task_set_cookie() which was finalized in device-mapper version 1.2.38 Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
-rw-r--r--kpartx/devmapper.c10
-rw-r--r--kpartx/devmapper.h4
-rw-r--r--kpartx/kpartx.c28
-rw-r--r--libmultipath/config.h2
-rw-r--r--libmultipath/configure.c2
-rw-r--r--libmultipath/devmapper.c31
-rw-r--r--libmultipath/devmapper.h8
-rw-r--r--multipath/main.c1
-rw-r--r--multipathd/main.c1
9 files changed, 60 insertions, 27 deletions
diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c
index dea1501..f884511 100644
--- a/kpartx/devmapper.c
+++ b/kpartx/devmapper.c
@@ -52,8 +52,10 @@ dm_prereq (char * str, int x, int y, int z)
}
extern int
-dm_simplecmd (int task, const char *name, int no_flush) {
+dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie) {
int r = 0;
+ int udev_wait_flag = (task == DM_DEVICE_RESUME ||
+ task == DM_DEVICE_REMOVE);
struct dm_task *dmt;
if (!(dmt = dm_task_create(task)))
@@ -68,6 +70,8 @@ dm_simplecmd (int task, const char *name, int no_flush) {
if (no_flush)
dm_task_no_flush(dmt);
+ if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, 0))
+ goto out;
r = dm_task_run(dmt);
out:
@@ -78,7 +82,7 @@ dm_simplecmd (int task, const char *name, int no_flush) {
extern int
dm_addmap (int task, const char *name, const char *target,
const char *params, uint64_t size, const char *uuid, int part,
- mode_t mode, uid_t uid, gid_t gid) {
+ mode_t mode, uid_t uid, gid_t gid, uint32_t *cookie) {
int r = 0;
struct dm_task *dmt;
char *prefixed_uuid = NULL;
@@ -113,6 +117,8 @@ dm_addmap (int task, const char *name, const char *target,
dm_task_no_open_count(dmt);
+ if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, cookie, 0))
+ goto addout;
r = dm_task_run (dmt);
addout:
diff --git a/kpartx/devmapper.h b/kpartx/devmapper.h
index 09cdced..f8692cc 100644
--- a/kpartx/devmapper.h
+++ b/kpartx/devmapper.h
@@ -3,9 +3,9 @@
#define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
int dm_prereq (char *, int, int, int);
-int dm_simplecmd (int, const char *, int);
+int dm_simplecmd (int, const char *, int, uint32_t *);
int dm_addmap (int, const char *, const char *, const char *, uint64_t,
- const char *, int, mode_t, uid_t, gid_t);
+ const char *, int, mode_t, uid_t, gid_t, uint32_t *);
int dm_map_present (char *);
char * dm_mapname(int major, int minor);
dev_t dm_get_first_dep(char *devname);
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
index 103ed0a..3d33990 100644
--- a/kpartx/kpartx.c
+++ b/kpartx/kpartx.c
@@ -82,7 +82,7 @@ initpts(void)
addpts("sun", read_sun_pt);
}
-static char short_opts[] = "ladgvp:t:";
+static char short_opts[] = "ladgvp:t:s";
/* Used in gpt.c */
int force_gpt=0;
@@ -96,6 +96,7 @@ usage(void) {
printf("\t-p set device name-partition number delimiter\n");
printf("\t-g force GUID partition table (GPT)\n");
printf("\t-v verbose\n");
+ printf("\t-s sync mode. Don't return until the partitions are created\n");
return 1;
}
@@ -198,7 +199,9 @@ main(int argc, char **argv){
int loopro = 0;
int hotplug = 0;
int loopcreated = 0;
+ int sync = 0;
struct stat buf;
+ uint32_t cookie = 0;
initpts();
init_crc32();
@@ -251,11 +254,17 @@ main(int argc, char **argv){
case 'd':
what = DELETE;
break;
+ case 's':
+ sync = 1;
+ break;
default:
usage();
exit(1);
}
+ if (!sync)
+ dm_udev_set_sync_support(0);
+
if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE)) {
fprintf(stderr, "device mapper prerequisites not met\n");
exit(1);
@@ -413,8 +422,8 @@ main(int argc, char **argv){
if (!slices[j].size || !dm_map_present(partname))
continue;
- if (!dm_simplecmd(DM_DEVICE_REMOVE,
- partname, 0)) {
+ if (!dm_simplecmd(DM_DEVICE_REMOVE, partname,
+ 0, &cookie)) {
r++;
continue;
}
@@ -463,14 +472,14 @@ main(int argc, char **argv){
if (!dm_addmap(op, partname, DM_TARGET, params,
slices[j].size, uuid, j+1,
buf.st_mode & 0777, buf.st_uid,
- buf.st_gid)) {
+ buf.st_gid, &cookie)) {
fprintf(stderr, "create/reload failed on %s\n",
partname);
r++;
}
if (op == DM_DEVICE_RELOAD &&
- !dm_simplecmd(DM_DEVICE_RESUME,
- partname, 1)) {
+ !dm_simplecmd(DM_DEVICE_RESUME, partname,
+ 1, &cookie)) {
fprintf(stderr, "resume failed on %s\n",
partname);
r++;
@@ -529,11 +538,13 @@ main(int argc, char **argv){
dm_addmap(op, partname, DM_TARGET, params,
slices[j].size, uuid, j+1,
buf.st_mode & 0777,
- buf.st_uid, buf.st_gid);
+ buf.st_uid, buf.st_gid,
+ &cookie);
if (op == DM_DEVICE_RELOAD)
dm_simplecmd(DM_DEVICE_RESUME,
- partname, 1);
+ partname, 1,
+ &cookie);
dm_devn(partname, &slices[j].major,
&slices[j].minor);
@@ -557,6 +568,7 @@ main(int argc, char **argv){
if (n > 0)
break;
}
+ dm_udev_wait(cookie);
dm_lib_release();
dm_lib_exit();
diff --git a/libmultipath/config.h b/libmultipath/config.h
index f6f39e6..d8e6915 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -2,6 +2,7 @@
#define _CONFIG_H
#include <sys/types.h>
+#include <stdint.h>
#define ORIGIN_DEFAULT 0
#define ORIGIN_CONFIG 1
@@ -83,6 +84,7 @@ struct config {
uid_t uid;
gid_t gid;
mode_t mode;
+ uint32_t cookie;
char * dev;
char * sysfs_dir;
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index c69190c..c6ca4b6 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -373,7 +373,7 @@ domap (struct multipath * mpp)
if (!r)
r = dm_addmap_reload_ro(mpp);
if (r)
- r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias);
+ r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1);
break;
case ACT_RENAME:
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 8883a37..333659b 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -77,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,8 +149,10 @@ dm_prereq (void)
}
static int
-dm_simplecmd (int task, const char *name, int no_flush) {
+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)))
@@ -166,6 +168,8 @@ dm_simplecmd (int task, const char *name, int 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,13 +178,13 @@ dm_simplecmd (int task, const char *name, int no_flush) {
}
extern int
-dm_simplecmd_flush (int task, const char *name) {
- return dm_simplecmd(task, name, 0);
+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);
+ return dm_simplecmd(task, name, 1, 1);
}
extern int
@@ -226,6 +230,9 @@ dm_addmap (int task, const char *target, struct multipath *mpp, int use_uuid,
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:
@@ -249,7 +256,7 @@ _dm_addmap_create (struct multipath *mpp, int ro) {
if (!r && dm_map_present(mpp->alias)) {
condlog(3, "%s: failed to load map (a path might be in use)",
mpp->alias);
- dm_flush_map(mpp->alias);
+ dm_flush_map_nosync(mpp->alias);
}
return r;
}
@@ -529,7 +536,7 @@ out:
}
extern int
-dm_flush_map (const char * mapname)
+_dm_flush_map (const char * mapname, int need_sync)
{
int r;
@@ -539,7 +546,7 @@ dm_flush_map (const char * mapname)
if (dm_type(mapname, TGT_MPATH) <= 0)
return 0; /* nothing to do */
- if (dm_remove_partmaps(mapname))
+ if (dm_remove_partmaps(mapname, need_sync))
return 1;
if (dm_get_opencount(mapname)) {
@@ -547,7 +554,7 @@ dm_flush_map (const char * mapname)
return 1;
}
- r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname);
+ r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync);
if (r) {
condlog(4, "multipath map %s removed", mapname);
@@ -883,7 +890,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;
@@ -946,7 +953,7 @@ dm_remove_partmaps (const char * mapname)
*/
condlog(4, "partition map %s removed",
names->name);
- dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name);
+ dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name, need_sync);
}
next = names->next;
@@ -1102,6 +1109,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;
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 9bbf48b..f3ffeaa 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -8,7 +8,7 @@
void dm_init(void);
int dm_prereq (void);
-int dm_simplecmd_flush (int, const char *);
+int dm_simplecmd_flush (int, const char *, int);
int dm_simplecmd_noflush (int, const char *);
int dm_addmap_create (struct multipath *mpp);
int dm_addmap_create_ro (struct multipath *mpp);
@@ -18,7 +18,9 @@ int dm_map_present (const char *);
int dm_get_map(char *, unsigned long long *, char *);
int dm_get_status(char *, char *);
int dm_type(const char *, char *);
-int dm_flush_map (const char *);
+int _dm_flush_map (const char *, int);
+#define dm_flush_map(mapname) _dm_flush_map(mapname, 1)
+#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0)
int dm_flush_maps (void);
int dm_fail_path(char * mapname, char * path);
int dm_reinstate_path(char * mapname, char * path);
@@ -31,7 +33,7 @@ int dm_get_maps (vector mp);
int dm_geteventnr (char *name);
int dm_get_minor (char *name);
char * dm_mapname(int major, int minor);
-int dm_remove_partmaps (const char * mapname);
+int dm_remove_partmaps (const char * mapname, int need_sync);
int dm_get_uuid(char *name, char *uuid);
int dm_get_info (char * mapname, struct dm_info ** dmi);
int dm_rename (char * old, char * new);
diff --git a/multipath/main.c b/multipath/main.c
index d72e242..1689efd 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -454,6 +454,7 @@ main (int argc, char *argv[])
condlog(3, "restart multipath configuration process");
out:
+ dm_udev_wait(conf->cookie);
sysfs_cleanup();
dm_lib_release();
diff --git a/multipathd/main.c b/multipathd/main.c
index 44d07c2..c247c43 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1411,6 +1411,7 @@ child (void * param)
exit(1);
}
conf->daemon = 1;
+ dm_udev_set_sync_support(0);
/*
* fetch and configure both paths and multipaths
*/