All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Wilck <martin.wilck@suse.com>
To: Christophe Varoqui <christophe.varoqui@opensvc.com>,
	Benjamin Marzinski <bmarzins@redhat.com>
Cc: dm-devel@lists.linux.dev, Etienne AUJAMES <eaujames@ddn.com>
Subject: [PATCH 6/8] libmultipath: set max_sectors_kb in adopt_paths()
Date: Wed, 17 Apr 2024 20:46:42 +0200	[thread overview]
Message-ID: <20240417184644.6193-7-mwilck@suse.com> (raw)
In-Reply-To: <20240417184644.6193-1-mwilck@suse.com>

As explained in the previous commit, setting max_sectors_kb for
paths that are members of a live map is dangerous. But as long as
a path is not a member of a map, setting max_sectors_kb poses no risk.
Set the parameter in adopt_paths(), for paths that aren't members
of the map yet. In order to determine whether or not a path is currently
member of the map, adopt_paths() needs to passed the current member list. If
(and only if) it's called from coalesce_paths(), the passed struct multipath
does not represent the current state of the map; adopt_paths() must therefore
get a new argument current_mpp that represents the kernel state.

We must still call sysfs_set_max_sectors_kb() from domap() in the ACT_CREATE
case, because when adopt_paths is called from coalesce_paths() for a map that
doesn't exist yet, mpp->max_sectors_kb is not set.

Signed-off-by: Martin Wilck <mwilck@suse.com>
---
 libmultipath/configure.c   |  2 +-
 libmultipath/structs_vec.c | 62 ++++++++++++++++++++++++++++++++++----
 libmultipath/structs_vec.h |  6 ++--
 multipathd/main.c          |  6 ++--
 tests/Makefile             |  2 +-
 tests/test-lib.c           |  9 +++++-
 6 files changed, 73 insertions(+), 14 deletions(-)

diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 8cbb2a8..b5c701f 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1105,7 +1105,7 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
 		/*
 		 * at this point, we know we really got a new mp
 		 */
-		mpp = add_map_with_path(vecs, pp1, 0);
+		mpp = add_map_with_path(vecs, pp1, 0, cmpp);
 		if (!mpp) {
 			orphan_path(pp1, "failed to create multipath device");
 			continue;
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 0fc608c..c0c5cc9 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -242,7 +242,38 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp,
 	return must_reload;
 }
 
-int adopt_paths(vector pathvec, struct multipath *mpp)
+static bool set_path_max_sectors_kb(const struct path *pp, int max_sectors_kb)
+{
+	char buf[11];
+	ssize_t len;
+	int ret, current;
+	bool rc = false;
+
+	if (max_sectors_kb == MAX_SECTORS_KB_UNDEF)
+		return rc;
+
+	if (sysfs_attr_get_value(pp->udev, "queue/max_sectors_kb", buf, sizeof(buf)) <= 0
+	    || sscanf(buf, "%d\n", &current) != 1)
+		current = MAX_SECTORS_KB_UNDEF;
+	if (current == max_sectors_kb)
+		return rc;
+
+	len = snprintf(buf, sizeof(buf), "%d", max_sectors_kb);
+	ret = sysfs_attr_set_value(pp->udev, "queue/max_sectors_kb", buf, len);
+	if (ret != len)
+		log_sysfs_attr_set_value(3, ret,
+					 "failed setting max_sectors_kb on %s",
+					 pp->dev);
+	else {
+		condlog(3, "%s: set max_sectors_kb to %d for %s", __func__,
+			max_sectors_kb, pp->dev);
+		rc = true;
+	}
+	return rc;
+}
+
+int adopt_paths(vector pathvec, struct multipath *mpp,
+		const struct multipath *current_mpp)
 {
 	int i, ret;
 	struct path * pp;
@@ -285,9 +316,28 @@ int adopt_paths(vector pathvec, struct multipath *mpp)
 				continue;
 			}
 
-			if (!find_path_by_devt(mpp->paths, pp->dev_t) &&
-			    store_path(mpp->paths, pp))
-				goto err;
+			if (!find_path_by_devt(mpp->paths, pp->dev_t)) {
+
+				if (store_path(mpp->paths, pp))
+					goto err;
+				/*
+				 * Setting max_sectors_kb on live paths is dangerous.
+				 * But we can do it here on a path that isn't yet part
+				 * of the map. If this value is lower than the current
+				 * max_sectors_kb and the map is reloaded, the map's
+				 * max_sectors_kb will be safely adjusted by the kernel.
+				 *
+				 * We must make sure that the path is not part of the
+				 * map yet. Normally we can check this in mpp->paths.
+				 * But if adopt_paths is called from coalesce_paths,
+				 * we need to check the separate struct multipath that
+				 * has been obtained from map_discovery().
+				 */
+				if (!current_mpp ||
+				    !mp_find_path_by_devt(current_mpp, pp->dev_t))
+					mpp->need_reload = mpp->need_reload ||
+						set_path_max_sectors_kb(pp, mpp->max_sectors_kb);
+			}
 
 			pp->mpp = mpp;
 			condlog(3, "%s: ownership set to %s",
@@ -693,7 +743,7 @@ find_existing_alias (struct multipath * mpp,
 }
 
 struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp,
-				    int add_vec)
+				    int add_vec, const struct multipath *current_mpp)
 {
 	struct multipath * mpp;
 	struct config *conf = NULL;
@@ -721,7 +771,7 @@ struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp,
 		goto out;
 	mpp->size = pp->size;
 
-	if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp ||
+	if (adopt_paths(vecs->pathvec, mpp, current_mpp) || pp->mpp != mpp ||
 	    find_slot(mpp->paths, pp) == -1)
 		goto out;
 
diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h
index 3253f1b..dbc4305 100644
--- a/libmultipath/structs_vec.h
+++ b/libmultipath/structs_vec.h
@@ -13,7 +13,8 @@ struct vectors {
 
 void set_no_path_retry(struct multipath *mpp);
 
-int adopt_paths (vector pathvec, struct multipath * mpp);
+int adopt_paths (vector pathvec, struct multipath *mpp,
+		 const struct multipath *current_mpp);
 void orphan_path (struct path * pp, const char *reason);
 void set_path_removed(struct path *pp);
 
@@ -28,7 +29,8 @@ void remove_maps (struct vectors * vecs);
 
 void sync_map_state (struct multipath *);
 struct multipath * add_map_with_path (struct vectors * vecs,
-				struct path * pp, int add_vec);
+				      struct path * pp, int add_vec,
+				      const struct multipath *current_mpp);
 void update_queue_mode_del_path(struct multipath *mpp);
 void update_queue_mode_add_path(struct multipath *mpp);
 int update_multipath_table (struct multipath *mpp, vector pathvec, int flags);
diff --git a/multipathd/main.c b/multipathd/main.c
index dd17d5c..d8518a9 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -636,7 +636,7 @@ update_map (struct multipath *mpp, struct vectors *vecs, int new_map)
 
 retry:
 	condlog(4, "%s: updating new map", mpp->alias);
-	if (adopt_paths(vecs->pathvec, mpp)) {
+	if (adopt_paths(vecs->pathvec, mpp, NULL)) {
 		condlog(0, "%s: failed to adopt paths for new map update",
 			mpp->alias);
 		retries = -1;
@@ -1231,7 +1231,7 @@ rescan:
 	if (mpp) {
 		condlog(4,"%s: adopting all paths for path %s",
 			mpp->alias, pp->dev);
-		if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp ||
+		if (adopt_paths(vecs->pathvec, mpp, NULL) || pp->mpp != mpp ||
 		    find_slot(mpp->paths, pp) == -1)
 			goto fail; /* leave path added to pathvec */
 
@@ -1245,7 +1245,7 @@ rescan:
 			return 0;
 		}
 		condlog(4,"%s: creating new map", pp->dev);
-		if ((mpp = add_map_with_path(vecs, pp, 1))) {
+		if ((mpp = add_map_with_path(vecs, pp, 1, NULL))) {
 			mpp->action = ACT_CREATE;
 			/*
 			 * We don't depend on ACT_CREATE, as domap will
diff --git a/tests/Makefile b/tests/Makefile
index d1d52dd..4005204 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -45,7 +45,7 @@ dmevents-test_OBJDEPS = $(multipathdir)/devmapper.o
 dmevents-test_LIBDEPS = -lpthread -ldevmapper -lurcu
 hwtable-test_TESTDEPS := test-lib.o
 hwtable-test_OBJDEPS := $(multipathdir)/discovery.o $(multipathdir)/blacklist.o \
-	$(multipathdir)/structs.o $(multipathdir)/propsel.o
+	$(multipathdir)/structs_vec.o $(multipathdir)/structs.o $(multipathdir)/propsel.o
 hwtable-test_LIBDEPS := -ludev -lpthread -ldl
 blacklist-test_TESTDEPS := test-log.o
 blacklist-test_LIBDEPS := -ludev
diff --git a/tests/test-lib.c b/tests/test-lib.c
index cdb2780..88f35e9 100644
--- a/tests/test-lib.c
+++ b/tests/test-lib.c
@@ -152,6 +152,13 @@ int __wrap_sysfs_get_size(struct path *pp, unsigned long long *sz)
 	return 0;
 }
 
+int __wrap_sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
+			   const char * value, size_t value_len)
+{
+	condlog(5, "%s: %s", __func__, value);
+	return value_len;
+}
+
 void *__wrap_udev_device_get_parent_with_subsystem_devtype(
 	struct udev_device *ud, const char *subsys, char *type)
 {
@@ -400,7 +407,7 @@ struct multipath *__mock_multipath(struct vectors *vecs, struct path *pp)
 	/* pathinfo() call in adopt_paths */
 	mock_pathinfo(DI_CHECKER|DI_PRIO, &mop);
 
-	mp = add_map_with_path(vecs, pp, 1);
+	mp = add_map_with_path(vecs, pp, 1, NULL);
 	assert_ptr_not_equal(mp, NULL);
 
 	/* TBD: mock setup_map() ... */
-- 
2.44.0


  parent reply	other threads:[~2024-04-17 18:47 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-17 18:46 [PATCH 0/8] multipath-tools: max_sectors_kb rework Martin Wilck
2024-04-17 18:46 ` [PATCH 1/8] multipath-tools: add TGTDIR option Martin Wilck
2024-04-17 18:46 ` [PATCH 2/8] libmultipath: move get_udev_for_mpp to sysfs.c Martin Wilck
2024-04-17 18:46 ` [PATCH 3/8] libmultipath: add mp_find_path_by_devt() Martin Wilck
2024-04-17 18:46 ` [PATCH 4/8] Revert "libmultipath: fix max_sectors_kb on adding path" Martin Wilck
2024-04-17 18:46 ` [PATCH 5/8] libmultipath: Only set max_sectors_kb on map creation Martin Wilck
2024-04-17 18:46 ` Martin Wilck [this message]
2024-04-17 18:46 ` [PATCH 7/8] libmultipath: add wildcard %k for printing max_sectors_kb Martin Wilck
2024-04-17 18:46 ` [PATCH 8/8] multipath.conf(5): update documentation for max_sectors_kb Martin Wilck
2024-04-18 18:40 ` [PATCH 0/8] multipath-tools: max_sectors_kb rework Benjamin Marzinski

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=20240417184644.6193-7-mwilck@suse.com \
    --to=martin.wilck@suse.com \
    --cc=bmarzins@redhat.com \
    --cc=christophe.varoqui@opensvc.com \
    --cc=dm-devel@lists.linux.dev \
    --cc=eaujames@ddn.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.