--- kpartx/devmapper.c | 17 +++++++++++++-- kpartx/devmapper.h | 2 - kpartx/kpartx.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 69 insertions(+), 7 deletions(-) Index: multipath-tools-130222/kpartx/devmapper.c =================================================================== --- multipath-tools-130222.orig/kpartx/devmapper.c +++ multipath-tools-130222/kpartx/devmapper.c @@ -140,12 +140,16 @@ addout: } extern int -dm_map_present (char * str) +dm_map_present (char * str, char **uuid) { int r = 0; struct dm_task *dmt; + const char *uuidtmp; struct dm_info info; + if (uuid) + *uuid = NULL; + if (!(dmt = dm_task_create(DM_DEVICE_INFO))) return 0; @@ -160,8 +164,15 @@ dm_map_present (char * str) if (!dm_task_get_info(dmt, &info)) goto out; - if (info.exists) - r = 1; + if (!info.exists) + goto out; + + r = 1; + if (uuid) { + uuidtmp = dm_task_get_uuid(dmt); + if (uuidtmp && strlen(uuidtmp)) + *uuid = strdup(uuidtmp); + } out: dm_task_destroy(dmt); return r; Index: multipath-tools-130222/kpartx/devmapper.h =================================================================== --- multipath-tools-130222.orig/kpartx/devmapper.h +++ multipath-tools-130222/kpartx/devmapper.h @@ -14,7 +14,7 @@ int dm_prereq (char *, int, int, int); int dm_simplecmd (int, const char *, int, uint32_t *, uint16_t); int dm_addmap (int, const char *, const char *, const char *, uint64_t, int, const char *, int, mode_t, uid_t, gid_t, uint32_t *); -int dm_map_present (char *); +int dm_map_present (char *, char **); char * dm_mapname(int major, int minor); dev_t dm_get_first_dep(char *devname); char * dm_mapuuid(int major, int minor); Index: multipath-tools-130222/kpartx/kpartx.c =================================================================== --- multipath-tools-130222.orig/kpartx/kpartx.c +++ multipath-tools-130222/kpartx/kpartx.c @@ -191,6 +191,21 @@ get_hotplug_device(void) return device; } +static int +check_uuid(char *uuid, char *part_uuid, char **err_msg) { + char *map_uuid = strchr(part_uuid, '-'); + if (!map_uuid || strncmp(part_uuid, "part", 4) != 0) { + *err_msg = "not a kpartx partition"; + return -1; + } + map_uuid++; + if (strcmp(uuid, map_uuid) != 0) { + *err_msg = "a partition of a different device"; + return -1; + } + return 0; +} + int main(int argc, char **argv){ int i, j, m, n, op, off, arg, ro=0; @@ -410,6 +425,8 @@ main(int argc, char **argv){ case DELETE: for (j = MAXSLICES-1; j >= 0; j--) { + char *part_uuid, *reason; + if (safe_sprintf(partname, "%s%s%d", mapname, delim, j+1)) { fprintf(stderr, "partname too small\n"); @@ -417,9 +434,18 @@ main(int argc, char **argv){ } strip_slash(partname); - if (!dm_map_present(partname)) + if (!dm_map_present(partname, &part_uuid)) continue; + if (part_uuid && uuid) { + if (check_uuid(uuid, part_uuid, &reason) != 0) { + fprintf(stderr, "%s is %s. Not removing\n", partname, reason); + free(part_uuid); + continue; + } + free(part_uuid); + } + if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, 0, &cookie, 0)) { r++; @@ -444,6 +470,8 @@ main(int argc, char **argv){ case UPDATE: /* ADD and UPDATE share the same code that adds new partitions. */ for (j = 0; j < n; j++) { + char *part_uuid, *reason; + if (slices[j].size == 0) continue; @@ -460,9 +488,19 @@ main(int argc, char **argv){ exit(1); } - op = (dm_map_present(partname) ? + op = (dm_map_present(partname, &part_uuid) ? DM_DEVICE_RELOAD : DM_DEVICE_CREATE); + if (part_uuid && uuid) { + if (check_uuid(uuid, part_uuid, &reason) != 0) { + fprintf(stderr, "%s is already in use, and %s\n", partname, reason); + r++; + free(part_uuid); + continue; + } + free(part_uuid); + } + if (!dm_addmap(op, partname, DM_TARGET, params, slices[j].size, ro, uuid, j+1, buf.st_mode & 0777, buf.st_uid, @@ -470,6 +508,7 @@ main(int argc, char **argv){ fprintf(stderr, "create/reload failed on %s\n", partname); r++; + continue; } if (op == DM_DEVICE_RELOAD && !dm_simplecmd(DM_DEVICE_RESUME, partname, @@ -477,6 +516,7 @@ main(int argc, char **argv){ fprintf(stderr, "resume failed on %s\n", partname); r++; + continue; } dm_devn(partname, &slices[j].major, &slices[j].minor); @@ -494,6 +534,7 @@ main(int argc, char **argv){ } for (j = MAXSLICES-1; j >= 0; j--) { + char *part_uuid, *reason; if (safe_sprintf(partname, "%s%s%d", mapname, delim, j+1)) { fprintf(stderr, "partname too small\n"); @@ -501,9 +542,19 @@ main(int argc, char **argv){ } strip_slash(partname); - if (slices[j].size || !dm_map_present(partname)) + if (slices[j].size || + !dm_map_present(partname, &part_uuid)) continue; + if (part_uuid && uuid) { + if (check_uuid(uuid, part_uuid, &reason) != 0) { + fprintf(stderr, "%s is %s. Not removing\n", partname, reason); + free(part_uuid); + continue; + } + free(part_uuid); + } + if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, 1, &cookie, 0)) { r++;