From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E8892606A330 for ; Sun, 8 Nov 2026 20:48:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=yaS7NfLS; dkim=pass (1024-bit key, unprotected) header.d=linux.dev header.i=@linux.dev header.a=rsa-sha256 header.s=key1 header.b=CYaEu3qM DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Unsubscribe-Post: List-Owner; bh=e/ENcDTT/46/JqAXL/szZUWwi4iIP1GEc08oJGPBrmo=; b=yaS7NfLSyZz+wX a5AKbNust6SXPXYnY/1oecn4f6/r0Mt6KXO3x9TG9hqIu8nL0Jplw9APSpCienvhFVf29vaCKEKSC OwU4gv87TNM2gYGwHRQomOEnHDxnpBXD6IDgW3C15XyMW8aIA1EkyVCm24goFdqe3l+KomfjzAUm9 IEi60y7dyTGXWElcwkBOLclOr10iGkaMF4KQX8iyUYGbv4BbTtKWGhzLbdWhv6lvIExJVjY5obYFo 40WzOwNHavhEJFzyLOH9vZ9bziIjQOfyM3LbzWd12Lwa/5HTnX2fc26a2D/cuXFJLzz6mQcJgWGvc 1g3RZlZY/VLZA4DVqGSg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.100.1 #2 (Red Hat Linux)) id 1xQ9o2-0000000Gbjw-1qn3; Sun, 08 Nov 2026 20:48:02 +0000 Received: from out-21.mta1.migadu.com ([95.215.58.21] helo=mta1.migadu.com) by bombadil.infradead.org with esmtps (Exim 4.100.1 #2 (Red Hat Linux)) id 1xQ9nv-0000000Gbgg-1Vir for linux-nvme@lists.infradead.org; Sun, 08 Nov 2026 20:47:56 +0000 X-Envelope-To: linux-nvme@lists.infradead.org DKIM-Signature: a=rsa-sha256; bh=MZn8yrwKf5iQXSOFESiRDw+YiIRgNh5gAITR+UTucsU=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1794170873; v=1; x=1794775673; b=CYaEu3qMK1rqlylLHp5liht6NyRDfpYSnyT5OsZNxBPSSOPi0WpVzCbLx7rz3cMblDO+Ru9V iv5YfmNNaA73Rmq0IUCVd7b07CAzInBp/bEAsCsCxu7jc2QFIEck915JgukpNR0IG316O8RmIRd vUqBeAz6lh3EIQlGkrZRxfqY= X-Envelope-To: linux-nvme@lists.infradead.org Received: by mta10.migadu.com with ESMTPS id 10538c3942c06036; Sun, 08 Nov 2026 20:47:53 +0000 X-Mizu-Trace-ID: 10538c3942c06036 X-Migadu-Flow: FLOW_OUT From: John Garry To: james.bottomley@hansenpartnership.com, mkp@kernel.org Cc: hare@suse.com, linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, snitzer@kernel.org, jmeneghi@redhat.com, bmarzins@redhat.com, dm-devel@lists.linux.dev, hch@lst.de, michael.christie@oracle.com, John Garry , Hannes Reinecke Subject: [PATCH v9 02/29] libmultipath: Add initial framework Date: Sun, 8 Nov 2026 20:47:06 +0000 Message-ID: <20261108204733.557995-3-john.garry@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261108204733.557995-1-john.garry@linux.dev> References: <20261108204733.557995-1-john.garry@linux.dev> X-Archived-By: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20261108_124755_543071_2C3A0228 X-CRM114-Status: GOOD ( 21.12 ) X-Spam-Score: -2.8 (--) X-BeenThere: linux-nvme@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-nvme" X-Spam-Status: No, score=-18.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=4.0.1 X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on aws-us-west-2-korg-listserv-alma10-1 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 . Reviewed-by: Hannes Reinecke Signed-off-by: John Garry --- include/linux/multipath.h | 28 ++++++++++++++++ lib/Kconfig | 6 ++++ lib/Makefile | 2 ++ lib/multipath.c | 68 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 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 000000000000..407d985cd31f --- /dev/null +++ b/include/linux/multipath.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only +#ifndef _LIBMULTIPATH_H +#define _LIBMULTIPATH_H + +#include +#include + +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 1e42f5167c68..3580bab7c2b1 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -630,3 +630,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 a2afe954805c..b4c0da268b67 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -350,3 +350,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 000000000000..31ef98980ba4 --- /dev/null +++ b/lib/multipath.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018 Christoph Hellwig. + * + * Base on NVMe multipath support in drivers/nvme/host/multipath.c + */ +#include +#include +#include + +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"); -- 2.43.0