From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=91.218.175.91 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794402657; b=P107ZPKuAjBzXdgBzQ9SykGmySNKz3kytdMPC6JLZMRVM/mqajRBUNwEEYEVRji4DF36 zSxtmpA3jrbMU5Cw3MdC6e6yZnFwFoDRPQmxXIJ23Ao1JsEMt4SIvR8Nek6KCzzgvCRSU LEAKvfnXbwMf4ruDr+o6Yc2kLS6pgJADorkdAigUmyas3n37Eg/P+YEelWohM41hLJu0g 5tnYwP7qv3N7QSuBFre4fO/mOmFbLBTcBvxNbSTSRvH4eeiVsSaOL9edI0UGBwWPvZe6C G/qRTdj07dBk8vt1JmfL0NjrS/4P1LGupjLQTvmbAZBAyfloA6JMnpSG2ufTOBB2j9A== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794402657; h=DMARC-Filter:X-Envelope-To:DKIM-Signature:X-Envelope-To:Received: X-Mizu-Trace-ID:X-Migadu-Flow:From:Date:Subject:MIME-Version: Content-Type:Content-Transfer-Encoding:Message-Id:References: In-Reply-To:To:Cc:X-Mailer; bh=WIaBD4pgSCmuibi93MYmQK12NXnIoOv5CQ8dP5MJQxs=; b=Vw/S5AxrBW9/CF9xqFS0v8ddiq3htAqQqmjCcSQVH0CCVQ3m7mqCniNfEQcqIa1c47Hh UYUfXTDqcqFXygklUPWa28khPoc1KZr3S2zclG3iDtut+gvTEYRiP7ErgQrF1umREalws qYzgaaLUjiF+uMrYpn6XtZh3GVfpQWO8rF/XQfspkDamrDhwRn3m9aBLV27IwG0OBcW04 kR5VJAtrgdJjqlNpSQ2IxbHKyAJovNKN/A/L4yfOI/vtW3Q0ye1fguQKllxpgiEwVCreA 2Hmh/pmVWWuNK6j4D3IcCXRcswq3b3m1TKPgqSCGUXGZXqwvPVRYi7T6xJvU8iAjW8A== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass header.d=linux.dev header.i=@linux.dev header.a=rsa-sha256 header.s=key1 header.b=e99vVF9B; arc=none smtp.remote-ip=91.218.175.91 Received: from mta0.migadu.com (out-91.mta0.migadu.com [91.218.175.91]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AFE6606A32A for ; Wed, 11 Nov 2026 13:10:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 7AFE6606A32A Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key, unprotected) header.d=linux.dev header.i=@linux.dev header.a=rsa-sha256 header.s=key1 header.b=e99vVF9B X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=YZBAqSuD53IPCe0IdHJimmdy+f3FgILysUny7J+HSiE=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1794402654; v=1; x=1795007454; b=e99vVF9Bq5ioTiAPPx6HwDhBph8Rh4QyUJedrpGrlfh8pBmnJ5QQ8wD5fHKLSeNulAb8B42Y GbPs+LP8p7fSnUYQTw5a3DQDIJ6g5X7ugJ96TWtABVeyWI60Yp5s56yUWdYfe8y+KfHFYPEcrqD U/XDAzosWrz7cCUgjkFnirw4= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id c557147aac95f8f3; Wed, 11 Nov 2026 13:10:54 +0000 X-Mizu-Trace-ID: c557147aac95f8f3 X-Migadu-Flow: FLOW_OUT From: Qiliang Yuan Date: Wed, 11 Nov 2026 08:10:22 -0500 Subject: [PATCH v2 2/2] nvme-multipath: don't wait for a grace period in nvme_mpath_set_live() X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20261111-bug-nvme-mpath-set-live-srcu-v2-2-fc772914d293@linux.dev> References: <20261111-bug-nvme-mpath-set-live-srcu-v2-0-fc772914d293@linux.dev> In-Reply-To: <20261111-bug-nvme-mpath-set-live-srcu-v2-0-fc772914d293@linux.dev> To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg , Nilay Shroff , Hannes Reinecke Cc: linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Qiliang Yuan X-Mailer: b4 0.13.0 When a path goes live, nvme_mpath_set_live() waits for an SRCU grace period of the namespace head before kicking the requeue work, so that bios which found no usable path are on the requeue list by the time it runs. The ANA work calls nvme_mpath_set_live() for every namespace that becomes optimized or non-optimized, one after another, so an ANA change waits for one grace period per namespace. Start the grace period with start_poll_synchronize_srcu() instead and have nvme_requeue_work() wait for it only if it has not completed yet. Take the cookie under head->lock, so that concurrent callers store their cookies in order and the requeue work never sees an older one. The grace periods of all namespaces then run in parallel, and requeue work kicked for other reasons finds the cookie completed and does not wait. Flipping an ANA group from inaccessible to optimized ten times over nvme-tcp loopback, nvme_read_ana_log() takes (median, min-max in parentheses): namespaces before (ms) after (ms) change 256 51.9 (42.5-85.4) 8.9 (2.6-12.0) -83% 1024 157.5 (133.5-179.6) 49.5 (32.8-67.1) -69% Signed-off-by: Qiliang Yuan --- drivers/nvme/host/multipath.c | 15 ++++++++++++++- drivers/nvme/host/nvme.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index a92a05b1f925a..9c1023102902c 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -712,6 +712,11 @@ static void nvme_requeue_work(struct work_struct *work) container_of(work, struct nvme_ns_head, requeue_work); struct bio *bio, *next; + /* Let bios that found no usable path reach the requeue list first. */ + if (!poll_state_synchronize_srcu(&head->srcu, + READ_ONCE(head->requeue_srcu_cookie))) + synchronize_srcu(&head->srcu); + spin_lock_irq(&head->requeue_lock); next = bio_list_get(&head->requeue_list); spin_unlock_irq(&head->requeue_lock); @@ -767,6 +772,7 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head) mutex_init(&head->lock); spin_lock_init(&head->requeue_lock); INIT_WORK(&head->requeue_work, nvme_requeue_work); + head->requeue_srcu_cookie = get_completed_synchronize_srcu(); INIT_WORK(&head->partition_scan_work, nvme_partition_scan_work); INIT_DELAYED_WORK(&head->remove_work, nvme_remove_head_work); @@ -849,9 +855,16 @@ static void nvme_mpath_set_live(struct nvme_ns *ns) __nvme_find_path(head, node); srcu_read_unlock(&head->srcu, srcu_idx); } + /* + * Have nvme_requeue_work() wait for the grace period instead of + * blocking here, so that namespaces going live together, e.g. on + * an ANA change, do not wait for one grace period each. Start it + * under head->lock so that the newest cookie is stored last. + */ + WRITE_ONCE(head->requeue_srcu_cookie, + start_poll_synchronize_srcu(&head->srcu)); mutex_unlock(&head->lock); - synchronize_srcu(&head->srcu); nvme_mpath_revalidate_zones(head); kblockd_schedule_work(&head->requeue_work); } diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 8833a463f1c84..3fff9b394b1cd 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -587,6 +587,7 @@ struct nvme_ns_head { __guarded_by(&requeue_lock); spinlock_t requeue_lock; struct work_struct requeue_work; + unsigned long requeue_srcu_cookie; struct work_struct partition_scan_work; struct mutex lock; unsigned long flags; -- 2.43.0