All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Wilck <mwilck@suse.com>
To: Christophe Varoqui <christophe.varoqui@opensvc.com>,
	Benjamin Marzinski <bmarzins@redhat.com>,
	Hannes Reinecke <hare@suse.de>
Cc: dm-devel@redhat.com
Subject: [PATCH 15/31] multipath: implement "check usable paths" (-C/-U)
Date: Sun,  3 Sep 2017 00:38:44 +0200	[thread overview]
Message-ID: <20170902223900.7339-16-mwilck@suse.com> (raw)
In-Reply-To: <20170902223900.7339-1-mwilck@suse.com>

When we process udev rules, it's crucial to know whether I/O on a given
device will succeed. Unfortunately DM_NR_VALID_PATHS is not reliable,
because the kernel path events aren't necessarily received in order, and
even if they are, the number of usable paths may have changed during
udev processing, in particular when there's a lot of load on udev
because many paths are failing or reinstating at the same time.
The latter problem can't be completely avoided, but the closer the
test before the actual "blkid" call, the better.

This patch adds the -C/-U options to multipath to check if a given
map has usable paths. Obviously this command must avoid doing any I/O
on the multipath map itself, thus no checkers are called; only status
from sysfs and dm is collected.

Signed-off-by: Martin Wilck <mwilck@suse.com>
---
 libmultipath/config.h |  1 +
 multipath/main.c      | 90 +++++++++++++++++++++++++++++++++++++++++++++++++--
 multipath/multipath.8 | 13 +++++++-
 3 files changed, 101 insertions(+), 3 deletions(-)

diff --git a/libmultipath/config.h b/libmultipath/config.h
index ffc69b5f..4aa53da8 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -34,6 +34,7 @@ enum mpath_cmds {
 	CMD_REMOVE_WWID,
 	CMD_RESET_WWIDS,
 	CMD_ADD_WWID,
+	CMD_USABLE_PATHS,
 };
 
 enum force_reload_types {
diff --git a/multipath/main.c b/multipath/main.c
index dede017e..704c491f 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -117,6 +117,7 @@ usage (char * progname)
 		"  -F      flush all multipath device maps\n"
 		"  -a      add a device wwid to the wwids file\n"
 		"  -c      check if a device should be a path in a multipath device\n"
+		"  -C      check if a multipath device has usable paths\n"
 		"  -q      allow queue_if_no_path when multipathd is not running\n"
 		"  -d      dry run, do not create or update devmaps\n"
 		"  -t      dump internal hardware table\n"
@@ -258,6 +259,81 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
 	return 0;
 }
 
+static int check_usable_paths(struct config *conf,
+			      const char *devpath, enum devtypes dev_type)
+{
+	struct udev_device *ud = NULL;
+	struct multipath *mpp = NULL;
+	struct pathgroup *pg;
+	struct path *pp;
+	char *mapname;
+	vector pathvec = NULL;
+	char params[PARAMS_SIZE], status[PARAMS_SIZE];
+	dev_t devt;
+	int r = 1, i, j;
+
+	ud = get_udev_device(devpath, dev_type);
+	if (ud == NULL)
+		return r;
+
+	devt = udev_device_get_devnum(ud);
+	if (!dm_is_dm_major(major(devt))) {
+		condlog(1, "%s is not a dm device", devpath);
+		goto out;
+	}
+
+	mapname = dm_mapname(major(devt), minor(devt));
+	if (mapname == NULL) {
+		condlog(1, "dm device not found: %s", devpath);
+		goto out;
+	}
+
+	if (!dm_is_mpath(mapname)) {
+		condlog(1, "%s is not a multipath map", devpath);
+		goto free;
+	}
+
+	/* pathvec is needed for disassemble_map */
+	pathvec = vector_alloc();
+	if (pathvec == NULL)
+		goto free;
+
+	mpp = dm_get_multipath(mapname);
+	if (mpp == NULL)
+		goto free;
+
+	dm_get_map(mpp->alias, &mpp->size, params);
+	dm_get_status(mpp->alias, status);
+	disassemble_map(pathvec, params, mpp, 0);
+	disassemble_status(status, mpp);
+
+	vector_foreach_slot (mpp->pg, pg, i) {
+		vector_foreach_slot (pg->paths, pp, j) {
+			pp->udev = get_udev_device(pp->dev_t, DEV_DEVT);
+			if (pp->udev == NULL)
+				continue;
+			if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO) != PATHINFO_OK)
+				continue;
+
+			if (pp->state == PATH_UP &&
+			    pp->dmstate == PSTATE_ACTIVE) {
+				condlog(3, "%s: path %s is usable",
+					devpath, pp->dev);
+				r = 0;
+				goto found;
+			}
+		}
+	}
+found:
+	condlog(2, "%s:%s usable paths found", devpath, r == 0 ? "" : " no");
+free:
+	FREE(mapname);
+	free_multipath(mpp, FREE_PATHS);
+	vector_free(pathvec);
+out:
+	udev_device_unref(ud);
+	return r;
+}
 
 /*
  * Return value:
@@ -522,7 +598,7 @@ main (int argc, char *argv[])
 		exit(1);
 	multipath_conf = conf;
 	conf->retrigger_tries = 0;
-	while ((arg = getopt(argc, argv, ":adchl::FfM:v:p:b:BrR:itquwW")) != EOF ) {
+	while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itquUwW")) != EOF ) {
 		switch(arg) {
 		case 1: printf("optarg : %s\n",optarg);
 			break;
@@ -547,6 +623,9 @@ main (int argc, char *argv[])
 		case 'c':
 			cmd = CMD_VALID_PATH;
 			break;
+		case 'C':
+			cmd = CMD_USABLE_PATHS;
+			break;
 		case 'd':
 			if (cmd == CMD_CREATE)
 				cmd = CMD_DRY_RUN;
@@ -593,6 +672,10 @@ main (int argc, char *argv[])
 			cmd = CMD_VALID_PATH;
 			dev_type = DEV_UEVENT;
 			break;
+		case 'U':
+			cmd = CMD_USABLE_PATHS;
+			dev_type = DEV_UEVENT;
+			break;
 		case 'w':
 			cmd = CMD_REMOVE_WWID;
 			break;
@@ -674,7 +757,10 @@ main (int argc, char *argv[])
 		condlog(0, "failed to initialize prioritizers");
 		goto out;
 	}
-
+	if (cmd == CMD_USABLE_PATHS) {
+		r = check_usable_paths(conf, dev, dev_type);
+		goto out;
+	}
 	if (cmd == CMD_VALID_PATH &&
 	    (!dev || dev_type == DEV_DEVMAP)) {
 		condlog(0, "the -c option requires a path to check");
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index b9436e52..a47a027d 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -25,7 +25,7 @@ multipath \- Device mapper target autoconfig.
 .RB [\| \-b\ \c
 .IR bindings_file \|]
 .RB [\| \-d \|]
-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \|-i | \-a | \|-u | \-w | \-W \|]
+.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-C | \-q | \-r | \-i | \-a | \-u | \-U | \-w | \-W \|]
 .RB [\| \-p\ \c
 .IR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|]
 .RB [\| \-R\ \c
@@ -110,6 +110,12 @@ Set user_friendly_names bindings file location.  The default is
 Check if a block device should be a path in a multipath device.
 .
 .TP
+.B \-C
+Check if a multipath device has usable paths. This can be used to
+test whether or not I/O on this device is likely to succeed. The command
+itself doesn't attempt to do I/O on the device.
+.
+.TP
 .B \-q
 Allow device tables with \fIqueue_if_no_path\fR when multipathd is not running.
 .
@@ -123,6 +129,11 @@ Check if the device specified in the program environment should be
 a path in a multipath device.
 .
 .TP
+.B \-U
+Check if the device specified in the program environment is a multipath device
+with usable paths. See \fB-C\fB.
+.
+.TP
 .B \-w
 Remove the WWID for the specified device from the WWIDs file.
 .
-- 
2.14.0

  parent reply	other threads:[~2017-09-02 22:38 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-02 22:38 [PATCH 00/31] multipath/kpartx udev rules cleanup, and fixes Martin Wilck
2017-09-02 22:38 ` [PATCH 01/31] libmultipath: fix partition_delimiter config option Martin Wilck
2017-09-02 22:38 ` [PATCH 02/31] kpartx: helper functions for name and uuid generation Martin Wilck
2017-09-02 22:38 ` [PATCH 03/31] kpartx: search partitions by UUID, and rename Martin Wilck
2017-09-02 22:38 ` [PATCH 04/31] test-kpartx: add tests for renaming functionality Martin Wilck
2017-09-02 22:38 ` [PATCH 05/31] kpartx: fix a corner case when renaming partitions Martin Wilck
2017-09-02 22:38 ` [PATCH 06/31] kpartx: fix part deletion without partition table Martin Wilck
2017-09-02 22:38 ` [PATCH 07/31] test-kpartx: test deletion with empty part table Martin Wilck
2017-09-02 22:38 ` [PATCH 08/31] kpartx: only recognize dasd part table on DASD Martin Wilck
2017-09-02 22:38 ` [PATCH 09/31] libmultipath: support MPATH_UDEV_NO_PATHS_FLAG on map creation Martin Wilck
2017-09-13 20:33   ` Benjamin Marzinski
2017-09-14 11:53     ` Martin Wilck
2017-09-02 22:38 ` [PATCH 10/31] libmultipath: add get_udev_device Martin Wilck
2017-09-02 22:38 ` [PATCH 11/31] libmultipath: get_refwwid: use get_udev_device Martin Wilck
2017-09-02 22:38 ` [PATCH 12/31] libmultipath: use const char* in some dm helpers Martin Wilck
2017-09-02 22:38 ` [PATCH 13/31] libmultipath: add DI_NOIO flag for pathinfo Martin Wilck
2017-09-02 22:38 ` [PATCH 14/31] libmultipath: add dm_get_multipath Martin Wilck
2017-09-02 22:38 ` Martin Wilck [this message]
2017-09-13 20:53   ` [PATCH 15/31] multipath: implement "check usable paths" (-C/-U) Benjamin Marzinski
2017-09-14 11:47     ` Martin Wilck
2017-09-15 21:06       ` Benjamin Marzinski
2017-09-02 22:38 ` [PATCH 16/31] 11-dm-mpath.rules: multipath -U for READY check Martin Wilck
2017-09-02 22:38 ` [PATCH 17/31] 11-dm-mpath.rules: import more ID_FS_xxx vars from db Martin Wilck
2017-09-02 22:38 ` [PATCH 18/31] 11-dm-mpath.rules: no need to test before IMPORT Martin Wilck
2017-09-02 22:38 ` [PATCH 19/31] 11-dm-mpath.rules: handle new maps with READY==0 Martin Wilck
2017-09-02 22:38 ` [PATCH 20/31] 11-dm-mpath.rules: don't set READY->ACTIVATION Martin Wilck
2017-09-13 21:19   ` Benjamin Marzinski
2017-09-13 21:33     ` Martin Wilck
2017-09-14 12:48     ` Martin Wilck
2017-09-15 20:33       ` Benjamin Marzinski
2017-09-02 22:38 ` [PATCH 21/31] 11-dm-mpath.rules: Remember DM_ACTIVATION Martin Wilck
2017-09-13 21:19   ` Benjamin Marzinski
2017-09-14 13:06     ` Martin Wilck
2017-09-15 20:40       ` Benjamin Marzinski
2017-09-18 19:54         ` Martin Wilck
2017-09-02 22:38 ` [PATCH 22/31] multipath.rules: set ID_FS_TYPE to "mpath_member" Martin Wilck
2017-09-02 22:38 ` [PATCH 23/31] kpartx.rules: don't rely on DM_DEPS and DM_TABLE_STATE Martin Wilck
2017-09-02 22:38 ` [PATCH 24/31] kpartx.rules: respect DM_UDEV_LOW_PRIORITY_FLAG Martin Wilck
2017-09-02 22:38 ` [PATCH 25/31] kpartx.rules: improved logic for by-uuid and by-label links Martin Wilck
2017-09-02 22:38 ` [PATCH 26/31] kpartx.rules: create by-partuuid and by-partlabel symlinks Martin Wilck
2017-09-02 22:38 ` [PATCH 27/31] kpartx.rules: generate type-name links only for multipath devices Martin Wilck
2017-09-02 22:38 ` [PATCH 28/31] kpartx.rules: fix logic for adding partitions Martin Wilck
2017-09-02 22:38 ` [PATCH 29/31] multipath/kpartx rules: avoid superfluous scanning Martin Wilck
2017-09-02 22:38 ` [PATCH 30/31] kpartx/del-part-nodes.rules: new udev file Martin Wilck
2017-09-13 21:23   ` Benjamin Marzinski
2017-09-02 22:39 ` [PATCH 31/31] kpartx.rules: move symlink code to other files Martin Wilck
2017-09-13 21:26   ` Benjamin Marzinski
2017-09-13 21:28 ` [PATCH 00/31] multipath/kpartx udev rules cleanup, and fixes Benjamin Marzinski
2017-09-14 11:56   ` Martin Wilck
2017-09-14 20:00   ` [PATCH v2 30/31] kpartx/del-part-nodes.rules: new udev file Martin Wilck
2017-09-14 20:00     ` [PATCH v2 31/31] kpartx.rules: move symlink code to other files Martin Wilck

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=20170902223900.7339-16-mwilck@suse.com \
    --to=mwilck@suse.com \
    --cc=bmarzins@redhat.com \
    --cc=christophe.varoqui@opensvc.com \
    --cc=dm-devel@redhat.com \
    --cc=hare@suse.de \
    /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.