All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Wilck <mwilck@suse.com>
To: dm-devel@redhat.com
Subject: [PATCH 29/33] kpartx: sanitize delete partitions
Date: Tue, 28 Feb 2017 17:23:25 +0100	[thread overview]
Message-ID: <20170228162329.14517-30-mwilck@suse.com> (raw)
In-Reply-To: <20170228162329.14517-1-mwilck@suse.com>

From: Hannes Reinecke <hare@suse.de>

kpartx has a rather braindead method for deleting partitions;
generating 'possible' partition names and trying to remove all
of them.
With this patch kpartx looks at the device-mapper devices on top
of the referenced device, and removes them if they found to be
kpartx-generated devices.


Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 kpartx/devmapper.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 kpartx/devmapper.h |   7 +-
 kpartx/kpartx.c    |  44 ++--------
 3 files changed, 229 insertions(+), 51 deletions(-)

diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c
index 2acae25e..cf6650c6 100644
--- a/kpartx/devmapper.c
+++ b/kpartx/devmapper.c
@@ -252,7 +252,7 @@ out:
 }
 
 char *
-dm_mapuuid(int major, int minor)
+dm_mapuuid(const char *mapname)
 {
 	struct dm_task *dmt;
 	const char *tmp;
@@ -261,9 +261,9 @@ dm_mapuuid(int major, int minor)
 	if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
 		return NULL;
 
+	if (!dm_task_set_name(dmt, mapname))
+		goto out;
 	dm_task_no_open_count(dmt);
-	dm_task_set_major(dmt, major);
-	dm_task_set_minor(dmt, minor);
 
 	if (!dm_task_run(dmt))
 		goto out;
@@ -277,7 +277,7 @@ out:
 }
 
 int
-dm_devn (char * mapname, int *major, int *minor)
+dm_devn (const char * mapname, int *major, int *minor)
 {
 	int r = 1;
 	struct dm_task *dmt;
@@ -304,8 +304,8 @@ out:
 	return r;
 }
 
-int
-dm_get_map(int major, int minor, char * outparams)
+static int
+dm_get_map(char *mapname, char * outparams)
 {
 	int r = 1;
 	struct dm_task *dmt;
@@ -316,8 +316,8 @@ dm_get_map(int major, int minor, char * outparams)
 	if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
 		return 1;
 
-	dm_task_set_major(dmt, major);
-	dm_task_set_minor(dmt, minor);
+	if (!dm_task_set_name(dmt, mapname))
+		goto out;
 	dm_task_no_open_count(dmt);
 
 	if (!dm_task_run(dmt))
@@ -334,15 +334,224 @@ out:
 	return r;
 }
 
+static int
+dm_get_opencount (const char * mapname)
+{
+	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;
+
+	if (!info.exists)
+		goto out;
+
+	r = info.open_count;
+out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+/*
+ * returns:
+ *    1 : match
+ *    0 : no match
+ *   -1 : empty map
+ */
+static int
+dm_type(const char * name, char * type)
+{
+	int r = 0;
+	struct dm_task *dmt;
+	uint64_t start, length;
+	char *target_type = NULL;
+	char *params;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+		return 0;
+
+	if (!dm_task_set_name(dmt, name))
+		goto out;
+
+	dm_task_no_open_count(dmt);
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	/* Fetch 1st target */
+	dm_get_next_target(dmt, NULL, &start, &length,
+			   &target_type, &params);
+
+	if (!target_type)
+		r = -1;
+	else if (!strcmp(target_type, type))
+		r = 1;
+
+out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+/*
+ * returns:
+ *    0 : if both uuids end with same suffix which starts with UUID_PREFIX
+ *    1 : otherwise
+ */
+int
+dm_compare_uuid(const char *mapuuid, const char *partname)
+{
+	char *partuuid;
+	int r = 1;
+
+	partuuid = dm_mapuuid(partname);
+	if (!partuuid)
+		return 1;
+
+	if (!strncmp(partuuid, "part", 4)) {
+		char *p = strstr(partuuid, "mpath-");
+		if (p && !strcmp(mapuuid, p))
+			r = 0;
+	}
+	free(partuuid);
+	return r;
+}
+
+struct remove_data {
+	int verbose;
+};
+
+static int
+do_foreach_partmaps (const char * mapname, const char *uuid,
+		     int (*partmap_func)(const char *, void *),
+		     void *data)
+{
+	struct dm_task *dmt;
+	struct dm_names *names;
+	struct remove_data *rd = data;
+	unsigned next = 0;
+	char params[PARAMS_SIZE];
+	int major, minor;
+	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_devn(mapname, &major, &minor))
+		goto out;
+
+	sprintf(dev_t, "%d:%d", major, minor);
+	do {
+		/*
+		 * skip our devmap
+		 */
+		if (!strcmp(names->name, mapname))
+			goto next;
+
+		/*
+		 * skip if we cannot fetch the map table from the kernel
+		 */
+		if (dm_get_map(names->name, &params[0]))
+			goto next;
+
+		/*
+		 * skip if the table does not map over the multipath map
+		 */
+		if (!strstr(params, dev_t))
+			goto next;
+
+		/*
+		 * skip if devmap target is not "linear"
+		 */
+		if (!dm_type(names->name, "linear")) {
+			if (rd->verbose)
+				printf("%s: is not a linear target. Not removing\n",
+				       names->name);
+			goto next;
+		}
+
+		/*
+		 * skip if uuids don't match
+		 */
+		if (dm_compare_uuid(uuid, names->name)) {
+			if (rd->verbose)
+				printf("%s: is not a kpartx partition. Not removing\n",
+				       names->name);
+			goto next;
+		}
+
+		if (partmap_func(names->name, data) != 0)
+			goto out;
+	next:
+		next = names->next;
+		names = (void *) names + next;
+	} while (next);
+
+	r = 0;
+out:
+	dm_task_destroy (dmt);
+	return r;
+}
+
+static int
+remove_partmap(const char *name, void *data)
+{
+	struct remove_data *rd = (struct remove_data *)data;
+	int r = 0;
+
+	if (dm_get_opencount(name)) {
+		if (rd->verbose)
+			printf("%s is in use. Not removing", name);
+		return 1;
+	}
+	if (!dm_simplecmd(DM_DEVICE_REMOVE, name, 0, 0)) {
+		if (rd->verbose)
+			printf("%s: failed to remove\n", name);
+		r = 1;
+	} else if (rd->verbose)
+		printf("del devmap : %s\n", name);
+	return r;
+}
+
+int
+dm_remove_partmaps (char * mapname, char *uuid, int verbose)
+{
+	struct remove_data rd = { verbose };
+	return do_foreach_partmaps(mapname, uuid, remove_partmap, &rd);
+}
+
 #define FEATURE_NO_PART "no_partitions"
 
 int
-dm_no_partitions(int major, int minor)
+dm_no_partitions(char *mapname)
 {
 	char params[PARAMS_SIZE], *ptr;
 	int i, num_features;
 
-	if (dm_get_map(major, minor, params))
+	if (dm_get_map(mapname, params))
 		return 0;
 
 	ptr = params;
diff --git a/kpartx/devmapper.h b/kpartx/devmapper.h
index 436efe11..9988ec0f 100644
--- a/kpartx/devmapper.h
+++ b/kpartx/devmapper.h
@@ -16,8 +16,9 @@ int dm_addmap (int, const char *, const char *, const char *, uint64_t,
 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);
-int dm_devn (char * mapname, int *major, int *minor);
-int dm_no_partitions(int major, int minor);
+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_no_partitions(char * mapname);
 
 #endif /* _KPARTX_DEVMAPPER_H */
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
index 34527877..58e60ffe 100644
--- a/kpartx/kpartx.c
+++ b/kpartx/kpartx.c
@@ -355,17 +355,15 @@ main(int argc, char **argv){
 	off = find_devname_offset(device);
 
 	if (!loopdev) {
-		uuid = dm_mapuuid(major(buf.st_rdev), minor(buf.st_rdev));
 		mapname = dm_mapname(major(buf.st_rdev), minor(buf.st_rdev));
+		if (mapname)
+			uuid = dm_mapuuid(mapname);
 	}
 
-	if (!uuid)
-		uuid = device + off;
-
 	if (!mapname)
 		mapname = device + off;
-	else if (!force_devmap &&
-		 dm_no_partitions(major(buf.st_rdev), minor(buf.st_rdev))) {
+	if (!force_devmap &&
+		 dm_no_partitions(mapname)) {
 		/* Feature 'no_partitions' is set, return */
 		return 0;
 	}
@@ -453,42 +451,12 @@ main(int argc, char **argv){
 			break;
 
 		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");
-					exit(1);
-				}
-				strip_slash(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, 0)) {
-					r++;
-					continue;
-				}
-				if (verbose)
-					printf("del devmap : %s\n", partname);
-			}
-
+			r = dm_remove_partmaps(mapname, uuid, verbose);
 			if (loopdev) {
 				if (del_loop(loopdev)) {
 					if (verbose)
 						printf("can't del loop : %s\n",
-							loopdev);
+						       loopdev);
 					exit(1);
 				}
 				printf("loop deleted : %s\n", loopdev);
-- 
2.11.0

  parent reply	other threads:[~2017-02-28 16:23 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-28 16:22 [PATCH 00/33] multipath-tools fixes from SUSE Martin Wilck
2017-02-28 16:22 ` [PATCH 01/33] multipathd.service: fixup Wants= and Before= statements Martin Wilck
2017-03-13 23:06   ` Benjamin Marzinski
2017-03-14  7:36     ` Martin Wilck
2017-02-28 16:22 ` [PATCH 02/33] multipathd: start daemon after udev trigger Martin Wilck
2017-02-28 16:22 ` [PATCH 03/33] Add support for "multipath=off" and "nompath" on kernel cmdline Martin Wilck
2017-02-28 16:23 ` [PATCH 04/33] multipath: do not check daemon from udev rules Martin Wilck
2017-04-05 21:54   ` Benjamin Marzinski
2017-04-06 12:10     ` Martin Wilck
2017-02-28 16:23 ` [PATCH 05/33] Invalid error code when using multipathd CLI Martin Wilck
2017-02-28 16:23 ` [PATCH 06/33] multipathd: set timeout for CLI commands correctly Martin Wilck
2017-04-05 22:07   ` Benjamin Marzinski
2017-04-12 20:26     ` Martin Wilck
2017-04-13 13:11     ` [PATCH] Revert "multipathd: set timeout for CLI commands correctly" Martin Wilck
2017-02-28 16:23 ` [PATCH 07/33] libmultipath: fall back to search paths by devt Martin Wilck
2017-02-28 16:23 ` [PATCH 08/33] libmultipath: Do not crash on empty features Martin Wilck
2017-02-28 16:23 ` [PATCH 09/33] multipathd: Set CLI timeout correctly Martin Wilck
2017-02-28 16:23 ` [PATCH 10/33] multipath: avoid crash when using modified configuration Martin Wilck
2017-02-28 16:23 ` [PATCH 11/33] multipathd: issue systemd READY after initial configuration Martin Wilck
2017-02-28 16:23 ` [PATCH 12/33] libmultipath/discovery: do not cache 'access_state' sysfs attribute Martin Wilck
2017-02-28 16:23 ` [PATCH 13/33] libmultipath: use existing alias from bindings file Martin Wilck
2017-02-28 16:23 ` [PATCH 14/33] multipath -ll: set DI_SERIAL Martin Wilck
2017-02-28 16:23 ` [PATCH 15/33] libmultipath: move suspend logic to _dm_flush_map Martin Wilck
2017-04-05 22:44   ` Benjamin Marzinski
2017-04-12 20:54     ` Martin Wilck
2017-04-13 13:05     ` [PATCH] libmultipath: fix skip_kpartx support for removing maps Martin Wilck
2017-04-14  8:42       ` Christophe Varoqui
2017-02-28 16:23 ` [PATCH 16/33] multipath: ignore -i if find_multipaths is set Martin Wilck
2017-02-28 16:23 ` [PATCH 17/33] multipathd: imply -n " Martin Wilck
2017-04-05 23:03   ` Benjamin Marzinski
2017-04-12 21:36     ` Martin Wilck
2017-04-13 21:54       ` Benjamin Marzinski
2017-02-28 16:23 ` [PATCH 18/33] multipathd: use weaker "force_reload" at startup Martin Wilck
2017-02-28 16:23 ` [PATCH 19/33] libmultipath: setup_features: log msg if queue_if_no_path is ignored Martin Wilck
2017-02-28 16:23 ` [PATCH 20/33] libmultipath: setup_feature: print log msg if no_path_retry cant be set Martin Wilck
2017-02-28 16:23 ` [PATCH 21/33] libmultipath: setup_feature: handle "retain_attached_hw_handler" Martin Wilck
2017-02-28 16:23 ` [PATCH 22/33] libmultipath: disassemble_map: skip no_path_retry check Martin Wilck
2017-02-28 16:23 ` [PATCH 23/33] libmultipath: disassemble_map: treat minio like assemble_map does Martin Wilck
2017-02-28 16:23 ` [PATCH 24/33] libmultipath: select_action: check special features separately Martin Wilck
2017-02-28 16:23 ` [PATCH 25/33] libmultipath: sysfs_attr_set_value: use const char* Martin Wilck
2017-02-28 16:23 ` [PATCH 26/33] libmultipath: reload map if not known to udev Martin Wilck
2017-02-28 16:23 ` [PATCH 27/33] libmultipath: differentiate ACT_NOTHING and ACT_IMPOSSIBLE Martin Wilck
2017-02-28 16:23 ` [PATCH 28/33] libmultipath: coalesce_paths: trigger uevent if nothing done Martin Wilck
2017-02-28 16:23 ` Martin Wilck [this message]
2017-02-28 16:23 ` [PATCH 30/33] tur: Add pthread_testcancel() Martin Wilck
2017-02-28 16:23 ` [PATCH 31/33] multipathd: fixup check for new path states Martin Wilck
2017-02-28 16:23 ` [PATCH 32/33] libmultipath/checkers: make RADOS checker optional Martin Wilck
2017-02-28 16:23 ` [PATCH 33/33] Make libdmmp build optional Martin Wilck
2017-02-28 22:44 ` [PATCH 00/33] multipath-tools fixes from SUSE Xose Vazquez Perez
2017-03-01  8:12   ` Martin Wilck
2017-03-23 18:43     ` multipath-tools (patch): Do not select sysfs prioritizer for RDAC arrays (was Re: [PATCH 00/33] multipath-tools fixes from SUSE) Xose Vazquez Perez
2017-03-23 20:40       ` Stewart, Sean
2017-03-22 19:02 ` [PATCH 00/33] multipath-tools fixes from SUSE Xose Vazquez Perez
2017-03-22 21:29   ` Christophe Varoqui
2017-03-23  8:30     ` Christophe Varoqui
2017-03-24  7:44       ` Martin Wilck
2017-04-12  7:38         ` Christophe Varoqui

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170228162329.14517-30-mwilck@suse.com \
    --to=mwilck@suse.com \
    --cc=dm-devel@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.