All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
To: Hannes Reinecke <hare@suse.de>, Martin Wilck <mwilck@suse.com>,
	device-mapper development <dm-devel@redhat.com>
Subject: least-pending multipath path selector WAS (9/14/14 !!!!): Re: Powerpath vs dm-multipath - two points of FUD?
Date: Mon, 1 Apr 2019 01:16:33 +0200	[thread overview]
Message-ID: <80c5be3f-f00a-36cb-c848-5207a8556b2f@gmail.com> (raw)
In-Reply-To: <54155446.2030700@suse.de>

On 9/14/14 10:39 AM, Hannes Reinecke wrote:

> We do this with the switch to request-based multipathing.
> Using one of the other load balancers (eg least-pending) and set rr_min_io to '1' will give you exactly that behaviour.

As the original authors team, at HP, was dissolved ( https://bugzilla.redhat.com/show_bug.cgi?id=438760#c14 )
Hannes, do you consider least-pending mp selector helpful for upstream?

https://raw.githubusercontent.com/kdave/kernel-source/master/patches.suse/dm-mpath-leastpending-path-update

---cut---
Subject: Update least-pending-IO dynamic load balancer
From: Hannes Reinecke <hare@suse.de>
Date: Wed Jan 7 09:26:30 2009 +0100:
References: bnc#444199
Patch-mainline: not yet, <hare: will resubmit, Oct 4, 2017>

Attached patch provides "Least pending IO" dynamic load balancing policy for
bio based device mapper multipath. This load balancing policy considers the
number of unserviced requests pending on a path and selects the path with least
count for pending service request.

We find this policy more useful especially when the SAN environment has
heterogeneous components. Ex, when there is one 8GB HBA and one 2GB HBA
connected to the same server, 8GB HBA could be utilized better with this
algorithm.

This patch includes the update as posted in the bugzilla,
based on the review comments received in the dm-devel mailing list.

Signed-off-by: Sakshi Chaitanya Veni <vsakshi@hp.com>
Signed-off-by: Vijayakumar Balasubramanian <vijayakumar@hp.com>
Signed-off-by: Senthil Kumar V <senthil-kumar.veluswamy@hp.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>

---
 drivers/md/Makefile           |    2
 drivers/md/dm-least-pending.c |  265 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 266 insertions(+), 1 deletion(-)

--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -41,7 +41,7 @@ obj-$(CONFIG_DM_BIO_PRISON)	+= dm-bio-pr
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
 obj-$(CONFIG_DM_FLAKEY)		+= dm-flakey.o
-obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
+obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o dm-least-pending.o
 obj-$(CONFIG_DM_MULTIPATH_QL)	+= dm-queue-length.o
 obj-$(CONFIG_DM_MULTIPATH_ST)	+= dm-service-time.o
 obj-$(CONFIG_DM_SWITCH)		+= dm-switch.o
--- /dev/null
+++ b/drivers/md/dm-least-pending.c
@@ -0,0 +1,265 @@
+/*
+ * (C) Copyright 2008 Hewlett-Packard Development Company, L.P
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-path-selector.h"
+
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#define DM_MSG_PREFIX "multipath least-pending"
+
+/*-----------------------------------------------------------------
+* Path-handling code, paths are held in lists
+*---------------------------------------------------------------*/
+struct path_info {
+       struct list_head list;
+       struct dm_path *path;
+       atomic_t io_count;
+};
+
+static void free_paths(struct list_head *paths)
+{
+       struct path_info *pi, *next;
+
+       list_for_each_entry_safe(pi, next, paths, list) {
+		list_del(&pi->list);
+		kfree(pi);
+       }
+}
+
+/*-----------------------------------------------------------------
+ * Least-pending selector
+ *---------------------------------------------------------------*/
+
+#define LPP_MIN_IO     1
+
+struct selector {
+       struct list_head valid_paths;
+       struct list_head invalid_paths;
+};
+
+static struct selector *alloc_selector(void)
+{
+       struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+       if (s) {
+		INIT_LIST_HEAD(&s->valid_paths);
+		INIT_LIST_HEAD(&s->invalid_paths);
+       }
+
+       return s;
+}
+
+static int lpp_create(struct path_selector *ps, unsigned argc, char **argv)
+{
+       struct selector *s;
+
+       s = alloc_selector();
+       if (!s)
+		return -ENOMEM;
+
+       ps->context = s;
+       return 0;
+}
+
+static void lpp_destroy(struct path_selector *ps)
+{
+       struct selector *s = ps->context;
+
+       free_paths(&s->valid_paths);
+       free_paths(&s->invalid_paths);
+       kfree(s);
+       ps->context = NULL;
+}
+
+static int lpp_status(struct path_selector *ps, struct dm_path *path,
+			status_type_t type, char *result, unsigned int maxlen)
+{
+       struct path_info *pi;
+       int sz = 0;
+
+       if (!path)
+		switch (type) {
+		case STATUSTYPE_INFO:
+			DMEMIT("1 ");
+		break;
+		case STATUSTYPE_TABLE:
+			DMEMIT("0 ");
+		break;
+		}
+       else {
+		pi = path->pscontext;
+		switch (type) {
+		case STATUSTYPE_INFO:
+			/*
+			 * Even though repeat_count isn't used anymore,
+			 * status info expects it. It's always 1.
+			 */
+			DMEMIT("1:%u ", atomic_read(&pi->io_count));
+		break;
+		case STATUSTYPE_TABLE:
+		break;
+		}
+	}
+
+       return sz;
+}
+
+/*
+ * Called during initialisation to register each path
+ */
+static int lpp_add_path(struct path_selector *ps, struct dm_path *path,
+			int argc, char **argv, char **error)
+{
+       struct selector *s = ps->context;
+       struct path_info *pi;
+
+	if (argc > 1) {
+		*error = "least-pending ps: incorrect number of arguments";
+		return -EINVAL;
+	}
+
+       /*
+        * Sanity check the optional repeat_count argument.  It must
+	* always be 1 and isn't actually variable.  We can just issue
+	* a warning and adjust automatically rather than error out.
+	*/
+       if (argc == 1) {
+		unsigned repeat_count = 1;
+	        if (sscanf(argv[0], "%u", &repeat_count) != 1) {
+			*error = "least-pending ps: invalid repeat count";
+			return -EINVAL;
+		}
+		if (repeat_count > 1)
+			DMWARN_LIMIT("repeat_count > 1 is deprecated, using 1 instead");
+       }
+
+       /* allocate the path */
+       pi = kmalloc(sizeof(*pi), GFP_KERNEL);
+       if (!pi) {
+		*error = "least-pending ps: Error allocating path context";
+		return -ENOMEM;
+       }
+
+       pi->path = path;
+       atomic_set(&pi->io_count, 0);
+
+       path->pscontext = pi;
+
+       list_add(&pi->list, &s->valid_paths);
+
+       return 0;
+}
+
+static void lpp_fail_path(struct path_selector *ps, struct dm_path *p)
+{
+       struct selector *s = ps->context;
+       struct path_info *pi = p->pscontext;
+
+       if (!pi)
+	return;
+
+       atomic_set(&pi->io_count, 0);
+
+       list_move(&pi->list, &s->invalid_paths);
+}
+
+static int lpp_reinstate_path(struct path_selector *ps, struct dm_path *p)
+{
+       struct selector *s = ps->context;
+       struct path_info *pi = p->pscontext;
+
+       if (!pi)
+	return 1;
+
+       list_move(&pi->list, &s->valid_paths);
+
+       return 0;
+}
+
+static struct dm_path *lpp_select_path(struct path_selector *ps,
+				       size_t nr_bytes)
+{
+       struct selector *s = ps->context;
+       struct path_info *pi, *next, *least_io_path = NULL;
+       struct list_head *paths;
+
+       if (list_empty(&s->valid_paths))
+		return NULL;
+
+       paths = &s->valid_paths;
+
+       list_for_each_entry_safe(pi, next, paths, list) {
+		if (!least_io_path || atomic_read(&least_io_path->io_count) < atomic_read(&pi->io_count))
+			least_io_path = pi;
+		if (!atomic_read(&least_io_path->io_count))
+			break;
+       }
+
+       if (!least_io_path)
+		return NULL;
+
+       atomic_inc(&least_io_path->io_count);
+
+       return least_io_path->path;
+}
+
+static int lpp_end_io(struct path_selector *ps, struct dm_path *path,
+		      size_t nr_bytes)
+{
+       struct path_info *pi = NULL;
+
+       pi = path->pscontext;
+       if (!pi)
+	return 1;
+
+       atomic_dec(&pi->io_count);
+
+       return 0;
+}
+
+static struct path_selector_type lpp_ps = {
+       .name = "least-pending",
+       .module = THIS_MODULE,
+       .table_args = 1,
+       .info_args = 0,
+       .create = lpp_create,
+       .destroy = lpp_destroy,
+       .status = lpp_status,
+       .add_path = lpp_add_path,
+       .fail_path = lpp_fail_path,
+       .reinstate_path = lpp_reinstate_path,
+       .select_path = lpp_select_path,
+       .end_io = lpp_end_io,
+};
+
+static int __init dm_lpp_init(void)
+{
+       int r = dm_register_path_selector(&lpp_ps);
+
+       if (r < 0)
+		DMERR("register failed %d", r);
+
+       DMINFO("version 1.0.0 loaded");
+
+       return r;
+}
+
+static void __exit dm_lpp_exit(void)
+{
+       int r = dm_unregister_path_selector(&lpp_ps);
+
+       if (r < 0)
+		DMERR("unregister failed %d", r);
+}
+
+module_init(dm_lpp_init);
+module_exit(dm_lpp_exit);
+
+MODULE_DESCRIPTION(DM_NAME " least-pending multipath path selector");
+MODULE_AUTHOR("Sakshi Chaitanya Veni <vsakshi@hp.com>");
+MODULE_LICENSE("GPL");
+
---end---


Missing Kconfig option:

diff -pNaur linux-2.6.28-rc7-org//drivers/md/Kconfig linux-2.6.28-rc7-mod//drivers/md/Kconfig
--- linux-2.6.28-rc7-org//drivers/md/Kconfig	2008-12-04 14:50:35.000000000 +0530
+++ linux-2.6.28-rc7-mod//drivers/md/Kconfig	2008-12-05 15:32:56.000000000 +0530
@@ -192,6 +192,16 @@ config MD_MULTIPATH

 	  If unsure, say N.

+config MD_MULTIPATH_LPP
+        tristate "Multipath - Least Pending IO Path Selector"
+        depends on MD_MULTIPATH
+        help
+          Least Pending IO Path Selector - This load balancing policy
+          considers the number of unserviced requests pending on a path
+          and selects the path with least count for pending service request.
+
+          If unsure, say N.
+
 config MD_FAULTY
 	tristate "Faulty test module for MD"
 	depends on BLK_DEV_MD

  reply	other threads:[~2019-03-31 23:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-09 16:50 Powerpath vs dm-multipath - two points of FUD? Rob
2014-09-10 10:04 ` Bryn M. Reeves
2014-09-14  8:39 ` Hannes Reinecke
2019-03-31 23:16   ` Xose Vazquez Perez [this message]
2019-04-01 11:05     ` least-pending multipath path selector WAS (9/14/14 !!!!): " 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=80c5be3f-f00a-36cb-c848-5207a8556b2f@gmail.com \
    --to=xose.vazquez@gmail.com \
    --cc=dm-devel@redhat.com \
    --cc=hare@suse.de \
    --cc=mwilck@suse.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.