@@ -8,6 +8,7 @@
#include <libdevmapper.h>
#include <ctype.h>
#include <errno.h>
+#include <sys/sysmacros.h>
#include "devmapper.h"
#define UUID_PREFIX "part%d-"
@@ -418,8 +419,8 @@ dm_compare_uuid(const char *mapuuid, const char *partname)
return 1;
if (!strncmp(partuuid, "part", 4)) {
- char *p = strstr(partuuid, "mpath-");
- if (p && !strcmp(mapuuid, p))
+ char *p = strchr(partuuid, '-');
+ if (p && !strcmp(mapuuid, p + 1))
r = 0;
}
free(partuuid);
@@ -432,6 +433,7 @@ struct remove_data {
static int
do_foreach_partmaps (const char * mapname, const char *uuid,
+ dev_t devt,
int (*partmap_func)(const char *, void *),
void *data)
{
@@ -443,6 +445,7 @@ do_foreach_partmaps (const char * mapname, const char *uuid,
int major, minor;
char dev_t[32];
int r = 1;
+ int is_dmdev = 1;
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
return 1;
@@ -460,15 +463,20 @@ do_foreach_partmaps (const char * mapname, const char *uuid,
goto out;
}
- if (dm_devn(mapname, &major, &minor))
- goto out;
+ if (dm_devn(mapname, &major, &minor) ||
+ (major != major(devt) || minor != minor(devt)))
+ /*
+ * The latter could happen if a dm device "/dev/mapper/loop0"
+ * exits while kpartx is called on "/dev/loop0".
+ */
+ is_dmdev = 0;
- sprintf(dev_t, "%d:%d", major, minor);
+ sprintf(dev_t, "%d:%d", major(devt), minor(devt));
do {
/*
* skip our devmap
*/
- if (!strcmp(names->name, mapname))
+ if (is_dmdev && !strcmp(names->name, mapname))
goto next;
/*
@@ -496,7 +504,7 @@ do_foreach_partmaps (const char * mapname, const char *uuid,
/*
* skip if uuids don't match
*/
- if (dm_compare_uuid(uuid, names->name)) {
+ if (is_dmdev && uuid && dm_compare_uuid(uuid, names->name)) {
if (rd->verbose)
printf("%s: is not a kpartx partition. Not removing\n",
names->name);
@@ -537,10 +545,10 @@ remove_partmap(const char *name, void *data)
}
int
-dm_remove_partmaps (char * mapname, char *uuid, int verbose)
+dm_remove_partmaps (char * mapname, char *uuid, dev_t devt, int verbose)
{
struct remove_data rd = { verbose };
- return do_foreach_partmaps(mapname, uuid, remove_partmap, &rd);
+ return do_foreach_partmaps(mapname, uuid, devt, remove_partmap, &rd);
}
#define FEATURE_NO_PART "no_partitions"
@@ -18,7 +18,7 @@ char * dm_mapname(int major, int minor);
dev_t dm_get_first_dep(char *devname);
char * dm_mapuuid(const char *mapname);
int dm_devn (const char * mapname, int *major, int *minor);
-int dm_remove_partmaps (char * mapname, char *uuid, int verbose);
+int dm_remove_partmaps (char * mapname, char *uuid, dev_t devt, int verbose);
int dm_no_partitions(char * mapname);
#endif /* _KPARTX_DEVMAPPER_H */
@@ -451,7 +451,8 @@ main(int argc, char **argv){
break;
case DELETE:
- r = dm_remove_partmaps(mapname, uuid, verbose);
+ r = dm_remove_partmaps(mapname, uuid, buf.st_rdev,
+ verbose);
if (loopdev) {
if (del_loop(loopdev)) {
if (verbose)
Commit 3d709241 improved partition removal, but broke support for handling partitions of non-dm devices such as loop devices or RAM disks. This requires passing the dev_t of the device down to do_foreach_partmap(). Doing so, there's little use in trying to derive major/minor numbers from the "mapname" any more (which actually is the device name for non-DM devices). But we can use this to find out whether the device in question is a dm device. The test for UUID match doesn't work for non-DM devices (this shall be improved in a later patch in this series). The test for equal name of parent dev and partition is only valid for dm devices. For non-dm devices such as loop, "/dev/mapper/loop0" could, theoretically, be a partition of "/dev/loop0" (and we don't want to rely on map names). Fixes: 3d709241 "kpartx: sanitize delete partitions" Signed-off-by: Martin Wilck <mwilck@suse.com> --- kpartx/devmapper.c | 26 +++++++++++++++++--------- kpartx/devmapper.h | 2 +- kpartx/kpartx.c | 3 ++- 3 files changed, 20 insertions(+), 11 deletions(-)