Re: [PATCH v4 01/28] libmultipath: Add initial framework
Hannes Reinecke <[email protected]> Fri, 24 Jul 2026 08:50:40 +0200
| Newsgroups | dev.linux.lists.dm-devel,org.infradead.lists.linux-nvme,org.kernel.vger.linux-kernel,org.kernel.vger.linux-scsi |
|---|---|
| Message-ID | <[email protected]> |
On 7/23/26 11:35 AM, John Garry wrote: > Add initial framework for libmultipath. libmultipath is a library for > multipath-capable block drivers, such as NVMe. The main function is to > support path management, path selection, and failover handling. > > Basic support to add and remove the head structure - mpath_head - is > included. > > This main purpose of this structure is to manage available paths and path > selection. It is quite similar to the multipath functionality in > nvme_ns_head. It also manages the multipath gendisk. > > Each path is represented by the mpath_device structure. It should hold a > pointer to the per-path gendisk and also a list element for all siblings > of paths. For NVMe, there would be a mpath_device per nvme_ns. > > All the libmultipath code is more or less taken from > drivers/nvme/host/multipath.c, which was originally authored by Christoph > Hellwig <[email protected]>. > > Signed-off-by: John Garry <[email protected]> > --- > include/linux/multipath.h | 28 +++++++++++++++++ > lib/Kconfig | 6 ++++ > lib/Makefile | 2 ++ > lib/multipath.c | 66 +++++++++++++++++++++++++++++++++++++++ > 4 files changed, 102 insertions(+) > create mode 100644 include/linux/multipath.h > create mode 100644 lib/multipath.c > > diff --git a/include/linux/multipath.h b/include/linux/multipath.h > new file mode 100644 > index 0000000000000..e98b4b241020a > --- /dev/null > +++ b/include/linux/multipath.h > @@ -0,0 +1,28 @@ Please add an SPDX tag. And possibly a copyright. > + > +#ifndef _LIBMULTIPATH_H > +#define _LIBMULTIPATH_H > + > +#include <linux/blkdev.h> > +#include <linux/srcu.h> > + > +struct mpath_device { > + struct list_head siblings; > + struct gendisk *disk; > +}; > + > +struct mpath_head { > + struct srcu_struct srcu; > + struct list_head dev_list; /* list of all mpath_devs */ > + struct mutex lock; > + > + refcount_t refcount; > + > + struct mpath_device __rcu *current_path[MAX_NUMNODES]; > +}; > + > +int mpath_get_head(struct mpath_head *mpath_head); > +void mpath_put_head(struct mpath_head *mpath_head); > +int mpath_head_init(struct mpath_head *mpath_head); > +void mpath_head_uninit(struct mpath_head *mpath_head); > + > +#endif // _LIBMULTIPATH_H > diff --git a/lib/Kconfig b/lib/Kconfig > index 55748b68714e0..d0258bef374a1 100644 > --- a/lib/Kconfig > +++ b/lib/Kconfig > @@ -636,3 +636,9 @@ config UNION_FIND > > config MIN_HEAP > bool > + > +config LIBMULTIPATH > + bool "MULTIPATH BLOCK DRIVER LIBRARY" > + depends on BLOCK > + help > + If you say yes here then you get a multipath lib for block drivers > diff --git a/lib/Makefile b/lib/Makefile > index 7f75cc6edf94a..7ba5e13be4171 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -334,3 +334,5 @@ CONTEXT_ANALYSIS_test_context-analysis.o := y > obj-$(CONFIG_CONTEXT_ANALYSIS_TEST) += test_context-analysis.o > > subdir-$(CONFIG_FORTIFY_SOURCE) += test_fortify > + > +obj-$(CONFIG_LIBMULTIPATH) += multipath.o > diff --git a/lib/multipath.c b/lib/multipath.c > new file mode 100644 > index 0000000000000..9cc398d266adf > --- /dev/null > +++ b/lib/multipath.c > @@ -0,0 +1,66 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) 2017-2018 Christoph Hellwig. A bit unusual, creating a new file and add a copyright from _another_ person ... > + * Copyright (c) 2026 Oracle and/or its affiliates. > + */ > +#include <linux/module.h> > +#include <linux/multipath.h> > + > +static struct workqueue_struct *mpath_wq; > + > +int mpath_get_head(struct mpath_head *mpath_head) > +{ > + if (!refcount_inc_not_zero(&mpath_head->refcount)) > + return -ENXIO; > + return 0; > +} > +EXPORT_SYMBOL_GPL(mpath_get_head); > + > +void mpath_put_head(struct mpath_head *mpath_head) > +{ > + refcount_t *refcount = &mpath_head->refcount; > + > + if (refcount_dec_and_test(&mpath_head->refcount)) > + wake_up_var(refcount); > +} > +EXPORT_SYMBOL_GPL(mpath_put_head); > + > +void mpath_head_uninit(struct mpath_head *mpath_head) > +{ > + refcount_t *refcount = &mpath_head->refcount; > + > + if (!refcount_dec_and_test(refcount)) > + wait_var_event(refcount, !refcount_read(refcount)); > + cleanup_srcu_struct(&mpath_head->srcu); > +} > +EXPORT_SYMBOL_GPL(mpath_head_uninit); > + > +int mpath_head_init(struct mpath_head *mpath_head) > +{ > + memset(mpath_head, 0, sizeof(*mpath_head)); > + INIT_LIST_HEAD(&mpath_head->dev_list); > + mutex_init(&mpath_head->lock); > + refcount_set(&mpath_head->refcount, 1); > + > + return init_srcu_struct(&mpath_head->srcu); > +} > +EXPORT_SYMBOL_GPL(mpath_head_init); > + > +static int __init mpath_init(void) > +{ > + mpath_wq = alloc_workqueue("mpath-wq", > + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0); > + if (!mpath_wq) > + return -ENOMEM; > + return 0; > +} > + > +static void __exit mpath_exit(void) > +{ > + destroy_workqueue(mpath_wq); > +} > + > +module_init(mpath_init); > +module_exit(mpath_exit); > +MODULE_LICENSE("GPL"); > +MODULE_DESCRIPTION("libmultipath"); Otherwise: Reviewed-by: Hannes Reinecke <[email protected]> Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect [email protected] +49 911 74053 688 SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich