From patchwork Thu Nov 14 03:59:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874517 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DFB546BF for ; Thu, 14 Nov 2024 03:59:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556795; cv=none; b=gw5tVMiNpMQqsAZrNo0YT+m/++DxvBMFiQ2zdtNqvwCOah1F4hUx3s9ofCHA0qm7XvJjgy6isvqiKS2tWhG4jBIf7I77a0fWlzjUVGLOQfhuuHQRueJw4/omnak0wlcLliYYQm+ONZhkmF83vs8iS+M9kM5elNn2Htshdg/hG50= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556795; c=relaxed/simple; bh=JlUUXL8QPWNOdHpktSKSvbUqA2w1Sg1yPC+lcPGvhsk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=owoCPV/Gm1XhwepWnQRtkXmoDmFqtqT96LiOfu8BDqktoK8QH/ACAI5socS/E0QkCyiS0C5bQuBkxLnW88CReyDT2IyldTac80wCLufBM5w2AYp/e3R8n/f37p1DVlQ4Te6s2X01UvZJmKoy2jOqcEFwxJxitXiWG19ojk3HzWU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GXul8tgp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GXul8tgp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BE801C4CED6; Thu, 14 Nov 2024 03:59:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556795; bh=JlUUXL8QPWNOdHpktSKSvbUqA2w1Sg1yPC+lcPGvhsk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GXul8tgphdMSdY8KVcrHOMQM7kcu4hAHPITNx5ljXDueyniani1ObJdbYMWh74tjT RVfW2asrC1nrg+QO6ZEDpw2/Oe4X2e0fGD5oiaDBzsu/MQ9UNPgn9kq6lgImWPhN99 iLFAxBzszidNeapUJuxSkK5vqf1tkkP5dhl8Vi1P8GjE+Sy1ObpbuVf9xNPmY0PbI1 jmLAC0gt+HaEJZg41oGQHL2eiI0WVBqZ8MBq9Do0oD7S2YTQMgTsZhn6MozeoTJL9g cuEgNqSLL+j4FWrdfd99yFYVex3UYK8T/a6khVFOr6c1Oq+3q3mFnz6rOFvoaC0fzJ 1VfRDAPVLNFiA== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 01/15] nfs_common: must not hold RCU while calling nfsd_file_put_local Date: Wed, 13 Nov 2024 22:59:38 -0500 Message-ID: <20241114035952.13889-2-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Move holding the RCU from nfs_to_nfsd_file_put_local to nfs_to_nfsd_net_put. It is the call to nfs_to->nfsd_serv_put that requires the RCU anyway (the puts for nfsd_file and netns were combined to avoid an extra indirect reference but that micro-optimization isn't possible now). This fixes xfstests generic/013 and it triggering: "Voluntary context switch within RCU read-side critical section!" [ 143.545738] Call Trace: [ 143.546206] [ 143.546625] ? show_regs+0x6d/0x80 [ 143.547267] ? __warn+0x91/0x140 [ 143.547951] ? rcu_note_context_switch+0x496/0x5d0 [ 143.548856] ? report_bug+0x193/0x1a0 [ 143.549557] ? handle_bug+0x63/0xa0 [ 143.550214] ? exc_invalid_op+0x1d/0x80 [ 143.550938] ? asm_exc_invalid_op+0x1f/0x30 [ 143.551736] ? rcu_note_context_switch+0x496/0x5d0 [ 143.552634] ? wakeup_preempt+0x62/0x70 [ 143.553358] __schedule+0xaa/0x1380 [ 143.554025] ? _raw_spin_unlock_irqrestore+0x12/0x40 [ 143.554958] ? try_to_wake_up+0x1fe/0x6b0 [ 143.555715] ? wake_up_process+0x19/0x20 [ 143.556452] schedule+0x2e/0x120 [ 143.557066] schedule_preempt_disabled+0x19/0x30 [ 143.557933] rwsem_down_read_slowpath+0x24d/0x4a0 [ 143.558818] ? xfs_efi_item_format+0x50/0xc0 [xfs] [ 143.559894] down_read+0x4e/0xb0 [ 143.560519] xlog_cil_commit+0x1b2/0xbc0 [xfs] [ 143.561460] ? _raw_spin_unlock+0x12/0x30 [ 143.562212] ? xfs_inode_item_precommit+0xc7/0x220 [xfs] [ 143.563309] ? xfs_trans_run_precommits+0x69/0xd0 [xfs] [ 143.564394] __xfs_trans_commit+0xb5/0x330 [xfs] [ 143.565367] xfs_trans_roll+0x48/0xc0 [xfs] [ 143.566262] xfs_defer_trans_roll+0x57/0x100 [xfs] [ 143.567278] xfs_defer_finish_noroll+0x27a/0x490 [xfs] [ 143.568342] xfs_defer_finish+0x1a/0x80 [xfs] [ 143.569267] xfs_bunmapi_range+0x4d/0xb0 [xfs] [ 143.570208] xfs_itruncate_extents_flags+0x13d/0x230 [xfs] [ 143.571353] xfs_free_eofblocks+0x12e/0x190 [xfs] [ 143.572359] xfs_file_release+0x12d/0x140 [xfs] [ 143.573324] __fput+0xe8/0x2d0 [ 143.573922] __fput_sync+0x1d/0x30 [ 143.574574] nfsd_filp_close+0x33/0x60 [nfsd] [ 143.575430] nfsd_file_free+0x96/0x150 [nfsd] [ 143.576274] nfsd_file_put+0xf7/0x1a0 [nfsd] [ 143.577104] nfsd_file_put_local+0x18/0x30 [nfsd] [ 143.578070] nfs_close_local_fh+0x101/0x110 [nfs_localio] [ 143.579079] __put_nfs_open_context+0xc9/0x180 [nfs] [ 143.580031] nfs_file_clear_open_context+0x4a/0x60 [nfs] [ 143.581038] nfs_file_release+0x3e/0x60 [nfs] [ 143.581879] __fput+0xe8/0x2d0 [ 143.582464] __fput_sync+0x1d/0x30 [ 143.583108] __x64_sys_close+0x41/0x80 [ 143.583823] x64_sys_call+0x189a/0x20d0 [ 143.584552] do_syscall_64+0x64/0x170 [ 143.585240] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 143.586185] RIP: 0033:0x7f3c5153efd7 Fixes: 65f2a5c36635 ("nfs_common: fix race in NFS calls to nfsd_file_put_local() and nfsd_serv_put()") Signed-off-by: Mike Snitzer Reviewed-by: NeilBrown Reviewed-by: Jeff Layton --- fs/nfs_common/nfslocalio.c | 8 +++----- fs/nfsd/filecache.c | 14 +++++++------- fs/nfsd/filecache.h | 2 +- include/linux/nfslocalio.h | 18 +++++++++++++++--- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index 09404d142d1ae..a74ec08f6c96d 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -155,11 +155,9 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, /* We have an implied reference to net thanks to nfsd_serv_try_get */ localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt, cred, nfs_fh, fmode); - if (IS_ERR(localio)) { - rcu_read_lock(); - nfs_to->nfsd_serv_put(net); - rcu_read_unlock(); - } + if (IS_ERR(localio)) + nfs_to_nfsd_net_put(net); + return localio; } EXPORT_SYMBOL_GPL(nfs_open_local_fh); diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index c16671135d176..9a62b4da89bb7 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -391,19 +391,19 @@ nfsd_file_put(struct nfsd_file *nf) } /** - * nfsd_file_put_local - put the reference to nfsd_file and local nfsd_serv - * @nf: nfsd_file of which to put the references + * nfsd_file_put_local - put nfsd_file reference and arm nfsd_serv_put in caller + * @nf: nfsd_file of which to put the reference * - * First put the reference of the nfsd_file and then put the - * reference to the associated nn->nfsd_serv. + * First save the associated net to return to caller, then put + * the reference of the nfsd_file. */ -void -nfsd_file_put_local(struct nfsd_file *nf) __must_hold(rcu) +struct net * +nfsd_file_put_local(struct nfsd_file *nf) { struct net *net = nf->nf_net; nfsd_file_put(nf); - nfsd_serv_put(net); + return net; } /** diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h index cadf3c2689c44..d5db6b34ba302 100644 --- a/fs/nfsd/filecache.h +++ b/fs/nfsd/filecache.h @@ -55,7 +55,7 @@ void nfsd_file_cache_shutdown(void); int nfsd_file_cache_start_net(struct net *net); void nfsd_file_cache_shutdown_net(struct net *net); void nfsd_file_put(struct nfsd_file *nf); -void nfsd_file_put_local(struct nfsd_file *nf); +struct net *nfsd_file_put_local(struct nfsd_file *nf); struct nfsd_file *nfsd_file_get(struct nfsd_file *nf); struct file *nfsd_file_file(struct nfsd_file *nf); void nfsd_file_close_inode_sync(struct inode *inode); diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index 3982fea799195..9202f4b24343d 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -55,7 +55,7 @@ struct nfsd_localio_operations { const struct cred *, const struct nfs_fh *, const fmode_t); - void (*nfsd_file_put_local)(struct nfsd_file *); + struct net *(*nfsd_file_put_local)(struct nfsd_file *); struct file *(*nfsd_file_file)(struct nfsd_file *); } ____cacheline_aligned; @@ -66,7 +66,7 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *, struct rpc_clnt *, const struct cred *, const struct nfs_fh *, const fmode_t); -static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) +static inline void nfs_to_nfsd_net_put(struct net *net) { /* * Once reference to nfsd_serv is dropped, NFSD could be @@ -74,10 +74,22 @@ static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) * by always taking RCU. */ rcu_read_lock(); - nfs_to->nfsd_file_put_local(localio); + nfs_to->nfsd_serv_put(net); rcu_read_unlock(); } +static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) +{ + /* + * Must not hold RCU otherwise nfsd_file_put() can easily trigger: + * "Voluntary context switch within RCU read-side critical section!" + * by scheduling deep in underlying filesystem (e.g. XFS). + */ + struct net *net = nfs_to->nfsd_file_put_local(localio); + + nfs_to_nfsd_net_put(net); +} + #else /* CONFIG_NFS_LOCALIO */ static inline void nfsd_localio_ops_init(void) { From patchwork Thu Nov 14 03:59:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874518 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A07A01E7C2A for ; Thu, 14 Nov 2024 03:59:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556796; cv=none; b=eEq15w/8bbPnTciH7FUGTlvZFAOQdYNKp0H6azoyzvMrMBRpXeYh6PlHJivPedqdPRYFFegzn7hKmQX5Ml0ud6nNdm1IzRcpmneb9W7XCNKjpgIYJJgF0GHqABWMWv71v/ABtrL6hBtURbJl9bp+wWpkaklAidUkQHP0i0QUiIQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556796; c=relaxed/simple; bh=mt5l/PhqSR5Fvq/Ed80gzI0rKgUrJu7Xhy5MIy4f/tg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=peIoTo36L5rxxjlIF3BjbLfCA23OC9I0rUdQ67kCse9EMSSxI7cDVvkXgsabxhv86qThK1Apls2T8FvvILcFYx/Qh7xOezbPzrbgM0Htpk4pKfxrFGbM4E5LiXtK8hxnzY7vi7spw6D9QhcLmcekcxRmU/6yLAXlBT+ELLdwDmk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HDxlG8QA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HDxlG8QA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4193BC4CED0; Thu, 14 Nov 2024 03:59:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556796; bh=mt5l/PhqSR5Fvq/Ed80gzI0rKgUrJu7Xhy5MIy4f/tg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HDxlG8QAQWkdOsgK6B9olIplw7acIIvhfRIEXMAochPai9HnZlSt6J0kmPVgJcG0X QBEfK+AB5lAf/bx8TjH1ydA/2aox4hzShgApheXLvlRAdK5k/QXsLBfAVUN8S0ElOG /0Xxc9CgUpreenbA7OFmUtmPp52Sa90ZWtAH0Z7bpkFWTIW/g4fo43diYCUnXMbwZG 9G4847hPp3nZ+OTuNazlwGshVgqcax85ksgD/psa93zPM6EQBLw39q/Rm9/lnue3mn vPgFPFKolvZWeKYeVV976Tgqxx4Tr4sBLfQsRYypjtjGzAdUF1mBHK+gMdAYFLlDM4 IVnySEhT2NghQ== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 02/15] nfs/localio: add direct IO enablement with sync and async IO support Date: Wed, 13 Nov 2024 22:59:39 -0500 Message-ID: <20241114035952.13889-3-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This commit simply adds the required O_DIRECT plumbing. It doesn't address the fact that NFS doesn't ensure all writes are page aligned (nor device logical block size aligned as required by O_DIRECT). Because NFS will read-modify-write for IO that isn't aligned, LOCALIO will not use O_DIRECT semantics by default if/when an application requests the use of O_DIRECT. Allow the use of O_DIRECT semantics by: 1: Adding a flag to the nfs_pgio_header struct to allow the NFS O_DIRECT layer to signal that O_DIRECT was used by the application 2: Adding a 'localio_O_DIRECT_semantics' NFS module parameter that when enabled will cause LOCALIO to use O_DIRECT semantics (this may cause IO to fail if applications do not properly align their IO). This commit is derived from code developed by Weston Andros Adamson. Signed-off-by: Mike Snitzer --- Documentation/filesystems/nfs/localio.rst | 11 +++ fs/nfs/direct.c | 1 + fs/nfs/localio.c | 93 ++++++++++++++++++++--- include/linux/nfs_xdr.h | 1 + 4 files changed, 96 insertions(+), 10 deletions(-) diff --git a/Documentation/filesystems/nfs/localio.rst b/Documentation/filesystems/nfs/localio.rst index bd1967e2eab32..eb3dc764cfce8 100644 --- a/Documentation/filesystems/nfs/localio.rst +++ b/Documentation/filesystems/nfs/localio.rst @@ -306,6 +306,17 @@ is issuing IO to the underlying local filesystem that it is sharing with the NFS server. See: fs/nfs/localio.c:nfs_local_doio() and fs/nfs/localio.c:nfs_local_commit(). +With normal NFS that makes use of RPC to issue IO to the server, if an +application uses O_DIRECT the NFS client will bypass the pagecache but +the NFS server will not. Because the NFS server's use of buffered IO +affords applications to be less precise with their alignment when +issuing IO to the NFS client. LOCALIO can be configured to use O_DIRECT +semantics by setting the 'localio_O_DIRECT_semantics' nfs module +parameter to Y, e.g.: + echo Y > /sys/module/nfs/parameters/localio_O_DIRECT_semantics +Once enabled, it will cause LOCALIO to use O_DIRECT semantics (this may +cause IO to fail if applications do not properly align their IO). + Security ======== diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 90079ca134dd3..4b92493d6ff0e 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -303,6 +303,7 @@ static void nfs_read_sync_pgio_error(struct list_head *head, int error) static void nfs_direct_pgio_init(struct nfs_pgio_header *hdr) { get_dreq(hdr->dreq); + set_bit(NFS_IOHDR_ODIRECT, &hdr->flags); } static const struct nfs_pgio_completion_ops nfs_direct_read_completion_ops = { diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index 4b8618cf114ca..7637786c5cb70 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -35,6 +35,7 @@ struct nfs_local_kiocb { struct bio_vec *bvec; struct nfs_pgio_header *hdr; struct work_struct work; + void (*aio_complete_work)(struct work_struct *); struct nfsd_file *localio; }; @@ -48,6 +49,11 @@ struct nfs_local_fsync_ctx { static bool localio_enabled __read_mostly = true; module_param(localio_enabled, bool, 0644); +static bool localio_O_DIRECT_semantics __read_mostly = false; +module_param(localio_O_DIRECT_semantics, bool, 0644); +MODULE_PARM_DESC(localio_O_DIRECT_semantics, + "LOCALIO will use O_DIRECT semantics to filesystem."); + static inline bool nfs_client_is_local(const struct nfs_client *clp) { return !!test_bit(NFS_CS_LOCAL_IO, &clp->cl_flags); @@ -285,10 +291,19 @@ nfs_local_iocb_alloc(struct nfs_pgio_header *hdr, kfree(iocb); return NULL; } - init_sync_kiocb(&iocb->kiocb, file); + + if (localio_O_DIRECT_semantics && + test_bit(NFS_IOHDR_ODIRECT, &hdr->flags)) { + iocb->kiocb.ki_filp = file; + iocb->kiocb.ki_flags = IOCB_DIRECT; + } else + init_sync_kiocb(&iocb->kiocb, file); + iocb->kiocb.ki_pos = hdr->args.offset; iocb->hdr = hdr; iocb->kiocb.ki_flags &= ~IOCB_APPEND; + iocb->aio_complete_work = NULL; + return iocb; } @@ -343,6 +358,18 @@ nfs_local_pgio_release(struct nfs_local_kiocb *iocb) nfs_local_hdr_release(hdr, hdr->task.tk_ops); } +/* + * Complete the I/O from iocb->kiocb.ki_complete() + * + * Note that this function can be called from a bottom half context, + * hence we need to queue the rpc_call_done() etc to a workqueue + */ +static inline void nfs_local_pgio_aio_complete(struct nfs_local_kiocb *iocb) +{ + INIT_WORK(&iocb->work, iocb->aio_complete_work); + queue_work(nfsiod_workqueue, &iocb->work); +} + static void nfs_local_read_done(struct nfs_local_kiocb *iocb, long status) { @@ -365,6 +392,23 @@ nfs_local_read_done(struct nfs_local_kiocb *iocb, long status) status > 0 ? status : 0, hdr->res.eof); } +static void nfs_local_read_aio_complete_work(struct work_struct *work) +{ + struct nfs_local_kiocb *iocb = + container_of(work, struct nfs_local_kiocb, work); + + nfs_local_pgio_release(iocb); +} + +static void nfs_local_read_aio_complete(struct kiocb *kiocb, long ret) +{ + struct nfs_local_kiocb *iocb = + container_of(kiocb, struct nfs_local_kiocb, kiocb); + + nfs_local_read_done(iocb, ret); + nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_read_aio_complete_work */ +} + static void nfs_local_call_read(struct work_struct *work) { struct nfs_local_kiocb *iocb = @@ -379,10 +423,10 @@ static void nfs_local_call_read(struct work_struct *work) nfs_local_iter_init(&iter, iocb, READ); status = filp->f_op->read_iter(&iocb->kiocb, &iter); - WARN_ON_ONCE(status == -EIOCBQUEUED); - - nfs_local_read_done(iocb, status); - nfs_local_pgio_release(iocb); + if (status != -EIOCBQUEUED) { + nfs_local_read_done(iocb, status); + nfs_local_pgio_release(iocb); + } revert_creds(save_cred); } @@ -410,6 +454,11 @@ nfs_do_local_read(struct nfs_pgio_header *hdr, nfs_local_pgio_init(hdr, call_ops); hdr->res.eof = false; + if (iocb->kiocb.ki_flags & IOCB_DIRECT) { + iocb->kiocb.ki_complete = nfs_local_read_aio_complete; + iocb->aio_complete_work = nfs_local_read_aio_complete_work; + } + INIT_WORK(&iocb->work, nfs_local_call_read); queue_work(nfslocaliod_workqueue, &iocb->work); @@ -534,6 +583,24 @@ nfs_local_write_done(struct nfs_local_kiocb *iocb, long status) nfs_local_pgio_done(hdr, status); } +static void nfs_local_write_aio_complete_work(struct work_struct *work) +{ + struct nfs_local_kiocb *iocb = + container_of(work, struct nfs_local_kiocb, work); + + nfs_local_vfs_getattr(iocb); + nfs_local_pgio_release(iocb); +} + +static void nfs_local_write_aio_complete(struct kiocb *kiocb, long ret) +{ + struct nfs_local_kiocb *iocb = + container_of(kiocb, struct nfs_local_kiocb, kiocb); + + nfs_local_write_done(iocb, ret); + nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_write_aio_complete_work */ +} + static void nfs_local_call_write(struct work_struct *work) { struct nfs_local_kiocb *iocb = @@ -552,11 +619,11 @@ static void nfs_local_call_write(struct work_struct *work) file_start_write(filp); status = filp->f_op->write_iter(&iocb->kiocb, &iter); file_end_write(filp); - WARN_ON_ONCE(status == -EIOCBQUEUED); - - nfs_local_write_done(iocb, status); - nfs_local_vfs_getattr(iocb); - nfs_local_pgio_release(iocb); + if (status != -EIOCBQUEUED) { + nfs_local_write_done(iocb, status); + nfs_local_vfs_getattr(iocb); + nfs_local_pgio_release(iocb); + } revert_creds(save_cred); current->flags = old_flags; @@ -592,10 +659,16 @@ nfs_do_local_write(struct nfs_pgio_header *hdr, case NFS_FILE_SYNC: iocb->kiocb.ki_flags |= IOCB_DSYNC|IOCB_SYNC; } + nfs_local_pgio_init(hdr, call_ops); nfs_set_local_verifier(hdr->inode, hdr->res.verf, hdr->args.stable); + if (iocb->kiocb.ki_flags & IOCB_DIRECT) { + iocb->kiocb.ki_complete = nfs_local_write_aio_complete; + iocb->aio_complete_work = nfs_local_write_aio_complete_work; + } + INIT_WORK(&iocb->work, nfs_local_call_write); queue_work(nfslocaliod_workqueue, &iocb->work); diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index e74a87bb18a44..162b7c0c35557 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1632,6 +1632,7 @@ enum { NFS_IOHDR_RESEND_PNFS, NFS_IOHDR_RESEND_MDS, NFS_IOHDR_UNSTABLE_WRITES, + NFS_IOHDR_ODIRECT, }; struct nfs_io_completion; From patchwork Thu Nov 14 03:59:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874519 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D6A246BF for ; Thu, 14 Nov 2024 03:59:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556798; cv=none; b=bBje+xus2wtBC6Ovn6VPzOW74ty72XzE5tA8Zx/a7nY/m1B/t4Jekk49kFQb1ND3c8cP2ao0O9r4DJtQlkItwWfWIbP4AY/nlEBgtbsJI7jMW5qSg3bK3ZxmIQAhYYEPU9TMqSKX5qvPOIJdEFJQQgh7H43LzOpq5eBxo8o/0a8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556798; c=relaxed/simple; bh=ZBYnj3Ea/NZBkZws315uRVwroPK4UE+L8kyLv7DOk9I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WvHu+LKgbGAhoMXDjiIxg1+iV/RwJ0UAOv+D7CTzMG8OmncJq+sTwvk6b+tqV9ZhPJB2yCVpXYfXj5HM0vec/e9/M+PYicV6Jj6juv4ML06Wbf8pVpW89nGfH/z3LSMkqUpD1TtWlIRJaRrrNK187bV2FJFjHL/jYNalwc345as= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qAWVJorG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qAWVJorG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 89B91C4CED0; Thu, 14 Nov 2024 03:59:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556797; bh=ZBYnj3Ea/NZBkZws315uRVwroPK4UE+L8kyLv7DOk9I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qAWVJorGrviSOyDMT5ZlR7ugScTGuCAMLN5oGxo7O0Qa5dPAfCwdP4Z+S+Tyn7jA+ urOwGsRhfZM1NypkAUDzkJGusrG7ySg51kNceYKhPm6D/wcXiJVXC/iUeWL9/wJgeL hJH3m29gDgEh2FoLsHSceYe2e8kwLJtF2ExOulYRNV3D4tgvZ2MJ8gTLEdg3+SdKvB qoiFawsEElXuaWHYCpEOYkPgJ6TVO3v5CUuF31TzKc+RFzFql9RN3d8guLp4kzmAhm ykPGp/fmr/78BgoAoFNC1SxBH6QW0JnUUWbsZ8aqm0raupDWk3HuUHNfdEJtHwN+3U NRLdZbAv7SqbQ== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 03/15] nfsd: add nfsd_file_{get,put} to 'nfs_to' nfsd_localio_operations Date: Wed, 13 Nov 2024 22:59:40 -0500 Message-ID: <20241114035952.13889-4-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In later a commit LOCALIO must call both nfsd_file_get and nfsd_file_put to manage extra nfsd_file references. Signed-off-by: Mike Snitzer --- fs/nfsd/localio.c | 2 ++ include/linux/nfslocalio.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c index f441cb9f74d56..8beda4c851119 100644 --- a/fs/nfsd/localio.c +++ b/fs/nfsd/localio.c @@ -29,6 +29,8 @@ static const struct nfsd_localio_operations nfsd_localio_ops = { .nfsd_serv_put = nfsd_serv_put, .nfsd_open_local_fh = nfsd_open_local_fh, .nfsd_file_put_local = nfsd_file_put_local, + .nfsd_file_get = nfsd_file_get, + .nfsd_file_put = nfsd_file_put, .nfsd_file_file = nfsd_file_file, }; diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index 9202f4b24343d..ab6a2a53f505f 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -56,6 +56,8 @@ struct nfsd_localio_operations { const struct nfs_fh *, const fmode_t); struct net *(*nfsd_file_put_local)(struct nfsd_file *); + struct nfsd_file *(*nfsd_file_get)(struct nfsd_file *); + void (*nfsd_file_put)(struct nfsd_file *); struct file *(*nfsd_file_file)(struct nfsd_file *); } ____cacheline_aligned; From patchwork Thu Nov 14 03:59:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874520 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 717F746BF for ; Thu, 14 Nov 2024 03:59:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556799; cv=none; b=hXOcwV/b9hoghM+tOq3h0kDqgD+JC08mhegVs94LpNKG1EM8SLQKfBQ+gjJsFdqQy7zbyA8TqrRZKFOoqnRrpt89pLRQs7GE0yXdOtk7ebAIArE+lSXdipGUNjJfmy1jgNEevAKcFnPNZ6e43fbwgXhiwaMTVeMG+76YE3E9wJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556799; c=relaxed/simple; bh=rCegmDgiRLKCXqyAh0ay4IpuZvkcSE+txkSiPSDtxc0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EIGqhYEJ0oP9N4Gc+o1101BAmz+7an4IfFLIB9aLUvEwXP7aa+b6CWVTa5rWtKTHU27Zp0QnLt30XfVT3Lx3I8vqmSmJbqjoRJCrDgDygvNDZYc2knV75uC8+seT6qy0EAAZ4MifxlTaTQll/bA66rirhXtp9a4c78BmNTOilmc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Jo/ZsC3g; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Jo/ZsC3g" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CEB02C4CED0; Thu, 14 Nov 2024 03:59:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556799; bh=rCegmDgiRLKCXqyAh0ay4IpuZvkcSE+txkSiPSDtxc0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Jo/ZsC3gWwpZaeL6wk5y1R1VhpefHgw22Clc135cxGRjfQud8gBjIG7Eh9rVjqfur NCLgXN3Ja64yHaOaRzjTesxwzPlkqWIUHyS16uSN/k5L0FPFaqc82R0ibqOmfBFHtU MgBtr+sgLnAFezfgZlSnDmPZRPaSG0p2HCPnYfsoemJsvvRQuPlRtFjJ6kVrT0SCE/ Y8oBRajMIHlyPhF+FQBW8shbjKmPSK6LsHkAC6dH3LzcuqYQnfHGhMAGu0Vqa9Sb4A kDI8TH4uDkv2Jw2ToJN7JCCBPOw/CPFZfv1YBo64jEo0ILSdqThCSnPAZ6T2R9ukYg hglwfaJnNgONg== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 04/15] nfs_common: rename functions that invalidate LOCALIO nfs_clients Date: Wed, 13 Nov 2024 22:59:41 -0500 Message-ID: <20241114035952.13889-5-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Rename nfs_uuid_invalidate_one_client to nfs_localio_disable_client. Rename nfs_uuid_invalidate_clients to nfs_localio_invalidate_clients. Signed-off-by: Mike Snitzer Reviewed-by: NeilBrown --- fs/nfs/localio.c | 2 +- fs/nfs_common/nfslocalio.c | 8 ++++---- fs/nfsd/nfsctl.c | 4 ++-- include/linux/nfslocalio.h | 5 +++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index 7637786c5cb70..94af5d89bb996 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -140,7 +140,7 @@ void nfs_local_disable(struct nfs_client *clp) spin_lock(&clp->cl_localio_lock); if (test_and_clear_bit(NFS_CS_LOCAL_IO, &clp->cl_flags)) { trace_nfs_local_disable(clp); - nfs_uuid_invalidate_one_client(&clp->cl_uuid); + nfs_localio_disable_client(&clp->cl_uuid); } spin_unlock(&clp->cl_localio_lock); } diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index a74ec08f6c96d..904439e4bb859 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -107,7 +107,7 @@ static void nfs_uuid_put_locked(nfs_uuid_t *nfs_uuid) list_del_init(&nfs_uuid->list); } -void nfs_uuid_invalidate_clients(struct list_head *list) +void nfs_localio_invalidate_clients(struct list_head *list) { nfs_uuid_t *nfs_uuid, *tmp; @@ -116,9 +116,9 @@ void nfs_uuid_invalidate_clients(struct list_head *list) nfs_uuid_put_locked(nfs_uuid); spin_unlock(&nfs_uuid_lock); } -EXPORT_SYMBOL_GPL(nfs_uuid_invalidate_clients); +EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients); -void nfs_uuid_invalidate_one_client(nfs_uuid_t *nfs_uuid) +void nfs_localio_disable_client(nfs_uuid_t *nfs_uuid) { if (nfs_uuid->net) { spin_lock(&nfs_uuid_lock); @@ -126,7 +126,7 @@ void nfs_uuid_invalidate_one_client(nfs_uuid_t *nfs_uuid) spin_unlock(&nfs_uuid_lock); } } -EXPORT_SYMBOL_GPL(nfs_uuid_invalidate_one_client); +EXPORT_SYMBOL_GPL(nfs_localio_disable_client); struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, struct rpc_clnt *rpc_clnt, const struct cred *cred, diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3adbc05ebaac4..727904d8a4d01 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2276,14 +2276,14 @@ static __net_init int nfsd_net_init(struct net *net) * nfsd_net_pre_exit - Disconnect localio clients from net namespace * @net: a network namespace that is about to be destroyed * - * This invalidated ->net pointers held by localio clients + * This invalidates ->net pointers held by localio clients * while they can still safely access nn->counter. */ static __net_exit void nfsd_net_pre_exit(struct net *net) { struct nfsd_net *nn = net_generic(net, nfsd_net_id); - nfs_uuid_invalidate_clients(&nn->local_clients); + nfs_localio_invalidate_clients(&nn->local_clients); } #endif diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index ab6a2a53f505f..a05d1043f2b07 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -37,8 +37,9 @@ bool nfs_uuid_begin(nfs_uuid_t *); void nfs_uuid_end(nfs_uuid_t *); void nfs_uuid_is_local(const uuid_t *, struct list_head *, struct net *, struct auth_domain *, struct module *); -void nfs_uuid_invalidate_clients(struct list_head *list); -void nfs_uuid_invalidate_one_client(nfs_uuid_t *nfs_uuid); + +void nfs_localio_disable_client(nfs_uuid_t *nfs_uuid); +void nfs_localio_invalidate_clients(struct list_head *list); /* localio needs to map filehandle -> struct nfsd_file */ extern struct nfsd_file * From patchwork Thu Nov 14 03:59:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874521 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D735546BF for ; Thu, 14 Nov 2024 04:00:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556800; cv=none; b=qJeKPCJbX+dTrQLHY6UigqRGIUkNmoXXWrBePDtkGpMm8HRiX5Hmxz97ZSW4suwM21XfQqJZgFSIOjxJAHv0rjVgdCDYVy8AwlOKmYx7q7S9BKHr9LfFiZ5aJ+4ZBgPvlTjOF5fF4rPaXx/VGeosDFIiNm6QJQErY6PhnVChyQs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556800; c=relaxed/simple; bh=8CoGL0Akh/2Q+GcWUxSQuMGv1n/TpBiS2QLvSRFCq8M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eRBYqEwwTn3SwjbrAZtQzPgqbE8Q8FjRkF130XMmznea14UhUQTAZocfR4V/P9IZzjnsgHZ76XBsX7TB5720qBB6aBS3WvCH2xI9q6ojtVzd4tqEI/ykuoB9KnQHFgufXhlx2+5q3gx4GTsqrKs+t+jLYpwEs1L5BjeALKJNJwI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S6F0Btc1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="S6F0Btc1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 25999C4CED0; Thu, 14 Nov 2024 04:00:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556800; bh=8CoGL0Akh/2Q+GcWUxSQuMGv1n/TpBiS2QLvSRFCq8M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S6F0Btc12bn1TxHY57FSBbJRhhuk62kJ2HZA4ZVWrxdDxXyrPAYJztjAgUpdYyQh1 ZlJNEpFgTOUWo9jqDS8aZ2YKnVrrMCTPTjaXQVVYKISILJSyrfcXPjVkot1L3W46J6 5frxTAoiVWG0MFLq1Sidmku26BPxGxWJdzT3DCUu2D0RJa9aMTVk/qjhqtedFLkRcH 2ML7l6KHvi7jUpwUlbugTloIO/WvznGQ4tTMhg44lpAY1pvgpuKQhhOpaTsWc08yh1 MZiX9Anb1PA7nJkPR418jY4jlk8lic5uNVrnS6Uc2eKDqn9NjWWPf2SLrxLG/n7uDw gI1C7+TTuuq4A== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 05/15] nfs_common: move localio_lock to new lock member of nfs_uuid_t Date: Wed, 13 Nov 2024 22:59:42 -0500 Message-ID: <20241114035952.13889-6-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Remove cl_localio_lock from 'struct nfs_client' in favor of adding a lock to the nfs_uuid_t struct (which is embedded in each nfs_client). Push nfs_local_{enable,disable} implementation down to nfs_common. Those methods now call nfs_localio_{enable,disable}_client. This allows implementing nfs_localio_invalidate_clients in terms of nfs_localio_disable_client. Signed-off-by: Mike Snitzer --- fs/nfs/client.c | 1 - fs/nfs/localio.c | 14 +++------- fs/nfs_common/nfslocalio.c | 57 ++++++++++++++++++++++++++------------ include/linux/nfs_fs_sb.h | 1 - include/linux/nfslocalio.h | 8 +++++- 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 550ca934c9cfc..e83e1ce046130 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -186,7 +186,6 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) seqlock_init(&clp->cl_boot_lock); ktime_get_real_ts64(&clp->cl_nfssvc_boot); nfs_uuid_init(&clp->cl_uuid); - spin_lock_init(&clp->cl_localio_lock); #endif /* CONFIG_NFS_LOCALIO */ clp->cl_principal = "*"; diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index 94af5d89bb996..7191135b47a42 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -126,10 +126,8 @@ const struct rpc_program nfslocalio_program = { */ static void nfs_local_enable(struct nfs_client *clp) { - spin_lock(&clp->cl_localio_lock); - set_bit(NFS_CS_LOCAL_IO, &clp->cl_flags); trace_nfs_local_enable(clp); - spin_unlock(&clp->cl_localio_lock); + nfs_localio_enable_client(clp); } /* @@ -137,12 +135,8 @@ static void nfs_local_enable(struct nfs_client *clp) */ void nfs_local_disable(struct nfs_client *clp) { - spin_lock(&clp->cl_localio_lock); - if (test_and_clear_bit(NFS_CS_LOCAL_IO, &clp->cl_flags)) { - trace_nfs_local_disable(clp); - nfs_localio_disable_client(&clp->cl_uuid); - } - spin_unlock(&clp->cl_localio_lock); + trace_nfs_local_disable(clp); + nfs_localio_disable_client(clp); } /* @@ -184,7 +178,7 @@ static bool nfs_server_uuid_is_local(struct nfs_client *clp) rpc_shutdown_client(rpcclient_localio); /* Server is only local if it initialized required struct members */ - if (status || !clp->cl_uuid.net || !clp->cl_uuid.dom) + if (status || !rcu_access_pointer(clp->cl_uuid.net) || !clp->cl_uuid.dom) return false; return true; diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index 904439e4bb859..abc132166742e 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include MODULE_LICENSE("GPL"); @@ -25,6 +28,7 @@ void nfs_uuid_init(nfs_uuid_t *nfs_uuid) nfs_uuid->net = NULL; nfs_uuid->dom = NULL; INIT_LIST_HEAD(&nfs_uuid->list); + spin_lock_init(&nfs_uuid->lock); } EXPORT_SYMBOL_GPL(nfs_uuid_init); @@ -94,12 +98,23 @@ void nfs_uuid_is_local(const uuid_t *uuid, struct list_head *list, } EXPORT_SYMBOL_GPL(nfs_uuid_is_local); +void nfs_localio_enable_client(struct nfs_client *clp) +{ + nfs_uuid_t *nfs_uuid = &clp->cl_uuid; + + spin_lock(&nfs_uuid->lock); + set_bit(NFS_CS_LOCAL_IO, &clp->cl_flags); + spin_unlock(&nfs_uuid->lock); +} +EXPORT_SYMBOL_GPL(nfs_localio_enable_client); + static void nfs_uuid_put_locked(nfs_uuid_t *nfs_uuid) { - if (nfs_uuid->net) { - module_put(nfsd_mod); - nfs_uuid->net = NULL; - } + if (!nfs_uuid->net) + return; + module_put(nfsd_mod); + RCU_INIT_POINTER(nfs_uuid->net, NULL); + if (nfs_uuid->dom) { auth_domain_put(nfs_uuid->dom); nfs_uuid->dom = NULL; @@ -107,27 +122,35 @@ static void nfs_uuid_put_locked(nfs_uuid_t *nfs_uuid) list_del_init(&nfs_uuid->list); } -void nfs_localio_invalidate_clients(struct list_head *list) +void nfs_localio_disable_client(struct nfs_client *clp) +{ + nfs_uuid_t *nfs_uuid = &clp->cl_uuid; + + spin_lock(&nfs_uuid->lock); + if (test_and_clear_bit(NFS_CS_LOCAL_IO, &clp->cl_flags)) { + spin_lock(&nfs_uuid_lock); + nfs_uuid_put_locked(nfs_uuid); + spin_unlock(&nfs_uuid_lock); + } + spin_unlock(&nfs_uuid->lock); +} +EXPORT_SYMBOL_GPL(nfs_localio_disable_client); + +void nfs_localio_invalidate_clients(struct list_head *cl_uuid_list) { nfs_uuid_t *nfs_uuid, *tmp; spin_lock(&nfs_uuid_lock); - list_for_each_entry_safe(nfs_uuid, tmp, list, list) - nfs_uuid_put_locked(nfs_uuid); + list_for_each_entry_safe(nfs_uuid, tmp, cl_uuid_list, list) { + struct nfs_client *clp = + container_of(nfs_uuid, struct nfs_client, cl_uuid); + + nfs_localio_disable_client(clp); + } spin_unlock(&nfs_uuid_lock); } EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients); -void nfs_localio_disable_client(nfs_uuid_t *nfs_uuid) -{ - if (nfs_uuid->net) { - spin_lock(&nfs_uuid_lock); - nfs_uuid_put_locked(nfs_uuid); - spin_unlock(&nfs_uuid_lock); - } -} -EXPORT_SYMBOL_GPL(nfs_localio_disable_client); - struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, struct rpc_clnt *rpc_clnt, const struct cred *cred, const struct nfs_fh *nfs_fh, const fmode_t fmode) diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index b804346a97419..239d86ef166c0 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -132,7 +132,6 @@ struct nfs_client { struct timespec64 cl_nfssvc_boot; seqlock_t cl_boot_lock; nfs_uuid_t cl_uuid; - spinlock_t cl_localio_lock; #endif /* CONFIG_NFS_LOCALIO */ }; diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index a05d1043f2b07..4d5583873f418 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -6,6 +6,7 @@ #ifndef __LINUX_NFSLOCALIO_H #define __LINUX_NFSLOCALIO_H + /* nfsd_file structure is purposely kept opaque to NFS client */ struct nfsd_file; @@ -19,6 +20,8 @@ struct nfsd_file; #include #include +struct nfs_client; + /* * Useful to allow a client to negotiate if localio * possible with its server. @@ -27,6 +30,8 @@ struct nfsd_file; */ typedef struct { uuid_t uuid; + /* sadly this struct is just over a cacheline, avoid bouncing */ + spinlock_t ____cacheline_aligned lock; struct list_head list; struct net __rcu *net; /* nfsd's network namespace */ struct auth_domain *dom; /* auth_domain for localio */ @@ -38,7 +43,8 @@ void nfs_uuid_end(nfs_uuid_t *); void nfs_uuid_is_local(const uuid_t *, struct list_head *, struct net *, struct auth_domain *, struct module *); -void nfs_localio_disable_client(nfs_uuid_t *nfs_uuid); +void nfs_localio_enable_client(struct nfs_client *clp); +void nfs_localio_disable_client(struct nfs_client *clp); void nfs_localio_invalidate_clients(struct list_head *list); /* localio needs to map filehandle -> struct nfsd_file */ From patchwork Thu Nov 14 03:59:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874522 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DDF371E3DE8 for ; Thu, 14 Nov 2024 04:00:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556801; cv=none; b=Gn1/muvSVvpbDHtY5euY/vTSEz7rXVCY1UQR6Q0H03NzlRAfUJVeCMjUSslFe0QY5nedMmDilX1KQlVW+QOS6hN+gx3eOwVXjdLBYAdODPCVPoeWOCBpm/nn/OD1KX50qQp/ctllChMeAdi3Cik8foZIkN0mci31+fvGynvW38w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556801; c=relaxed/simple; bh=ut6i+C3g19NIwj56RN4OI1hhxwOp/82D+lnQpVhBwiQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nf/b4w2RYtn9x8FjjF4pNWprxaVlIo5FYwpDUTUgq60oAm9Z5uXAtTALAtHsApESI85OOGXyCZke7/q5LDItMI5oA7DGtovGLyapUOCIwrUNeVc2u0Et+v+7z5IaVFWvsvarLiN4muR89u0uUGL3EoLymlnkpiVoqU+ZwghYrX0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=I4Hp7aQb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="I4Hp7aQb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8853EC4CED6; Thu, 14 Nov 2024 04:00:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556801; bh=ut6i+C3g19NIwj56RN4OI1hhxwOp/82D+lnQpVhBwiQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=I4Hp7aQbPiClIJINAwXGvjrVZeTaNFpbakjHT5WLpQmZ+9ie1GM0fPQJsEaq+3d/R 4m8chH4RqOqty4OZ+wuetmkwbAOBSAoTFJD/bgdAA8D2yxu/2ozyJbsGxqP2Xi6stm wmrKdcy0HLmS7U2MF4xbHM7i8kpd27/Nueo6ni9rkNIdOy2Ok8TnRlO0p8XtJ7hV6H G1P5JLbMgYyCxClpGmxuvCAeBoM9Qk1dpyGJHJy3wEw5YRs+xhLLJuadE3kZI1oY0a 5KEXoI+5goaNtFby8pqKliTntF9EsPrT1Mn7bwZxRAwNVKVeSBN5AI47j2YBAwp3X5 /ECmI0je0Pisw== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 06/15] nfs: cache all open LOCALIO nfsd_file(s) in client Date: Wed, 13 Nov 2024 22:59:43 -0500 Message-ID: <20241114035952.13889-7-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This commit switches from leaning heavily on NFSD's filecache (in terms of GC'd nfsd_files) back to caching nfsd_files in the client. A later commit will add the callback mechanism needed to allow NFSD to force the NFS client to cleanup all caches files. Add nfs_fh_localio_init() and 'struct nfs_fh_localio' to cache opened nfsd_file(s) (both a RO and RW nfsd_file is able to be opened and cached for a given nfs_fh). Update nfs_local_open_fh() to cache the nfsd_file once it is opened using __nfs_local_open_fh(). Introduce nfs_close_local_fh() to clear the cached open nfsd_files and call nfs_to_nfsd_file_put_local(). Refcounting is such that: - nfs_local_open_fh() is paired with nfs_close_local_fh(). - __nfs_local_open_fh() is paired with nfs_to_nfsd_file_put_local(). - nfs_local_file_get() is paired with nfs_local_file_put(). Signed-off-by: Mike Snitzer --- fs/nfs/flexfilelayout/flexfilelayout.c | 29 +++++---- fs/nfs/flexfilelayout/flexfilelayout.h | 1 + fs/nfs/inode.c | 3 + fs/nfs/internal.h | 4 +- fs/nfs/localio.c | 89 +++++++++++++++++++++----- fs/nfs/pagelist.c | 5 +- fs/nfs/write.c | 3 +- fs/nfs_common/nfslocalio.c | 52 ++++++++++++++- include/linux/nfs_fs.h | 22 ++++++- include/linux/nfslocalio.h | 18 +++--- 10 files changed, 181 insertions(+), 45 deletions(-) diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index f78115c6c2c12..451f168d882be 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -164,18 +164,17 @@ decode_name(struct xdr_stream *xdr, u32 *id) } static struct nfsd_file * -ff_local_open_fh(struct nfs_client *clp, const struct cred *cred, +ff_local_open_fh(struct pnfs_layout_segment *lseg, u32 ds_idx, + struct nfs_client *clp, const struct cred *cred, struct nfs_fh *fh, fmode_t mode) { - if (mode & FMODE_WRITE) { - /* - * Always request read and write access since this corresponds - * to a rw layout. - */ - mode |= FMODE_READ; - } +#if IS_ENABLED(CONFIG_NFS_LOCALIO) + struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, ds_idx); - return nfs_local_open_fh(clp, cred, fh, mode); + return nfs_local_open_fh(clp, cred, fh, &mirror->nfl, mode); +#else + return NULL; +#endif } static bool ff_mirror_match_fh(const struct nfs4_ff_layout_mirror *m1, @@ -247,6 +246,9 @@ static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags) spin_lock_init(&mirror->lock); refcount_set(&mirror->ref, 1); INIT_LIST_HEAD(&mirror->mirrors); +#if IS_ENABLED(CONFIG_NFS_LOCALIO) + nfs_localio_file_init(&mirror->nfl); +#endif } return mirror; } @@ -257,6 +259,9 @@ static void ff_layout_free_mirror(struct nfs4_ff_layout_mirror *mirror) ff_layout_remove_mirror(mirror); kfree(mirror->fh_versions); +#if IS_ENABLED(CONFIG_NFS_LOCALIO) + nfs_close_local_fh(&mirror->nfl); +#endif cred = rcu_access_pointer(mirror->ro_cred); put_cred(cred); cred = rcu_access_pointer(mirror->rw_cred); @@ -1820,7 +1825,7 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr) hdr->mds_offset = offset; /* Start IO accounting for local read */ - localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh, FMODE_READ); + localio = ff_local_open_fh(lseg, idx, ds->ds_clp, ds_cred, fh, FMODE_READ); if (localio) { hdr->task.tk_start = ktime_get(); ff_layout_read_record_layoutstats_start(&hdr->task, hdr); @@ -1896,7 +1901,7 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync) hdr->args.offset = offset; /* Start IO accounting for local write */ - localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh, + localio = ff_local_open_fh(lseg, idx, ds->ds_clp, ds_cred, fh, FMODE_READ|FMODE_WRITE); if (localio) { hdr->task.tk_start = ktime_get(); @@ -1981,7 +1986,7 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how) data->args.fh = fh; /* Start IO accounting for local commit */ - localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh, + localio = ff_local_open_fh(lseg, idx, ds->ds_clp, ds_cred, fh, FMODE_READ|FMODE_WRITE); if (localio) { data->task.tk_start = ktime_get(); diff --git a/fs/nfs/flexfilelayout/flexfilelayout.h b/fs/nfs/flexfilelayout/flexfilelayout.h index f84b3fb0dddd8..095df09017a57 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.h +++ b/fs/nfs/flexfilelayout/flexfilelayout.h @@ -83,6 +83,7 @@ struct nfs4_ff_layout_mirror { nfs4_stateid stateid; const struct cred __rcu *ro_cred; const struct cred __rcu *rw_cred; + struct nfs_file_localio nfl; refcount_t ref; spinlock_t lock; unsigned long flags; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 596f351701372..1aa67fca69b2f 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1137,6 +1137,8 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, ctx->lock_context.open_context = ctx; INIT_LIST_HEAD(&ctx->list); ctx->mdsthreshold = NULL; + nfs_localio_file_init(&ctx->nfl); + return ctx; } EXPORT_SYMBOL_GPL(alloc_nfs_open_context); @@ -1168,6 +1170,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) nfs_sb_deactive(sb); put_rpccred(rcu_dereference_protected(ctx->ll_cred, 1)); kfree(ctx->mdsthreshold); + nfs_close_local_fh(&ctx->nfl); kfree_rcu(ctx, rcu_head); } diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 430733e3eff26..57af3ab3adbe5 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -459,6 +459,7 @@ extern void nfs_local_probe(struct nfs_client *); extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *, const struct cred *, struct nfs_fh *, + struct nfs_file_localio *, const fmode_t); extern int nfs_local_doio(struct nfs_client *, struct nfsd_file *, @@ -474,7 +475,8 @@ static inline void nfs_local_disable(struct nfs_client *clp) {} static inline void nfs_local_probe(struct nfs_client *clp) {} static inline struct nfsd_file * nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, - struct nfs_fh *fh, const fmode_t mode) + struct nfs_fh *fh, struct nfs_file_localio *nfl, + const fmode_t mode) { return NULL; } diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index 7191135b47a42..7e432057c3a1f 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -211,27 +211,33 @@ void nfs_local_probe(struct nfs_client *clp) } EXPORT_SYMBOL_GPL(nfs_local_probe); +static inline struct nfsd_file *nfs_local_file_get(struct nfsd_file *nf) +{ + return nfs_to->nfsd_file_get(nf); +} + +static inline void nfs_local_file_put(struct nfsd_file *nf) +{ + nfs_to->nfsd_file_put(nf); +} + /* - * nfs_local_open_fh - open a local filehandle in terms of nfsd_file + * __nfs_local_open_fh - open a local filehandle in terms of nfsd_file. * - * Returns a pointer to a struct nfsd_file or NULL + * Returns a pointer to a struct nfsd_file or ERR_PTR. + * Caller must release returned nfsd_file with nfs_to_nfsd_file_put_local(). */ -struct nfsd_file * -nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, - struct nfs_fh *fh, const fmode_t mode) +static struct nfsd_file * +__nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, + struct nfs_fh *fh, struct nfs_file_localio *nfl, + const fmode_t mode) { struct nfsd_file *localio; - int status; - - if (!nfs_server_is_local(clp)) - return NULL; - if (mode & ~(FMODE_READ | FMODE_WRITE)) - return NULL; localio = nfs_open_local_fh(&clp->cl_uuid, clp->cl_rpcclient, - cred, fh, mode); + cred, fh, nfl, mode); if (IS_ERR(localio)) { - status = PTR_ERR(localio); + int status = PTR_ERR(localio); trace_nfs_local_open_fh(fh, mode, status); switch (status) { case -ENOMEM: @@ -240,10 +246,59 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, /* Revalidate localio, will disable if unsupported */ nfs_local_probe(clp); } - return NULL; } return localio; } + +/* + * nfs_local_open_fh - open a local filehandle in terms of nfsd_file. + * First checking if the open nfsd_file is already cached, otherwise + * must __nfs_local_open_fh and insert the nfsd_file in nfs_file_localio. + * + * Returns a pointer to a struct nfsd_file or NULL. + */ +struct nfsd_file * +nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, + struct nfs_fh *fh, struct nfs_file_localio *nfl, + const fmode_t mode) +{ + struct nfsd_file *nf, *new, __rcu **pnf; + + if (!nfs_server_is_local(clp)) + return NULL; + if (mode & ~(FMODE_READ | FMODE_WRITE)) + return NULL; + + if (mode & FMODE_WRITE) + pnf = &nfl->rw_file; + else + pnf = &nfl->ro_file; + + new = NULL; + rcu_read_lock(); + nf = rcu_dereference(*pnf); + if (!nf) { + rcu_read_unlock(); + new = __nfs_local_open_fh(clp, cred, fh, nfl, mode); + if (IS_ERR(new)) + return NULL; + /* try to swap in the pointer */ + spin_lock(&clp->cl_uuid.lock); + nf = rcu_dereference_protected(*pnf, 1); + if (!nf) { + nf = new; + new = NULL; + rcu_assign_pointer(*pnf, nf); + } + spin_unlock(&clp->cl_uuid.lock); + rcu_read_lock(); + } + nf = nfs_local_file_get(nf); + rcu_read_unlock(); + if (new) + nfs_to_nfsd_file_put_local(new); + return nf; +} EXPORT_SYMBOL_GPL(nfs_local_open_fh); static struct bio_vec * @@ -347,7 +402,7 @@ nfs_local_pgio_release(struct nfs_local_kiocb *iocb) { struct nfs_pgio_header *hdr = iocb->hdr; - nfs_to_nfsd_file_put_local(iocb->localio); + nfs_local_file_put(iocb->localio); nfs_local_iocb_free(iocb); nfs_local_hdr_release(hdr, hdr->task.tk_ops); } @@ -694,7 +749,7 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio, if (status != 0) { if (status == -EAGAIN) nfs_local_disable(clp); - nfs_to_nfsd_file_put_local(localio); + nfs_local_file_put(localio); hdr->task.tk_status = status; nfs_local_hdr_release(hdr, call_ops); } @@ -745,7 +800,7 @@ nfs_local_release_commit_data(struct nfsd_file *localio, struct nfs_commit_data *data, const struct rpc_call_ops *call_ops) { - nfs_to_nfsd_file_put_local(localio); + nfs_local_file_put(localio); call_ops->rpc_call_done(&data->task, data); call_ops->rpc_release(data); } diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index e27c07bd89290..11968dcb72431 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -961,8 +961,9 @@ static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc) struct nfs_client *clp = NFS_SERVER(hdr->inode)->nfs_client; struct nfsd_file *localio = - nfs_local_open_fh(clp, hdr->cred, - hdr->args.fh, hdr->args.context->mode); + nfs_local_open_fh(clp, hdr->cred, hdr->args.fh, + &hdr->args.context->nfl, + hdr->args.context->mode); if (NFS_SERVER(hdr->inode)->nfs_client->cl_minorversion) task_flags = RPC_TASK_MOVEABLE; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 2da00987d9ed4..75779e3cac16d 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1817,7 +1817,8 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how, task_flags = RPC_TASK_MOVEABLE; localio = nfs_local_open_fh(NFS_SERVER(inode)->nfs_client, data->cred, - data->args.fh, data->context->mode); + data->args.fh, &data->context->nfl, + data->context->mode); return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode), data->mds_ops, how, RPC_TASK_CRED_NOREF | task_flags, localio); diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index abc132166742e..35a2e48731df6 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include MODULE_LICENSE("GPL"); @@ -151,9 +151,18 @@ void nfs_localio_invalidate_clients(struct list_head *cl_uuid_list) } EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients); +static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl) +{ + spin_lock(&nfs_uuid_lock); + if (!nfl->nfs_uuid) + rcu_assign_pointer(nfl->nfs_uuid, nfs_uuid); + spin_unlock(&nfs_uuid_lock); +} + struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, struct rpc_clnt *rpc_clnt, const struct cred *cred, - const struct nfs_fh *nfs_fh, const fmode_t fmode) + const struct nfs_fh *nfs_fh, struct nfs_file_localio *nfl, + const fmode_t fmode) { struct net *net; struct nfsd_file *localio; @@ -180,11 +189,50 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, cred, nfs_fh, fmode); if (IS_ERR(localio)) nfs_to_nfsd_net_put(net); + else + nfs_uuid_add_file(uuid, nfl); return localio; } EXPORT_SYMBOL_GPL(nfs_open_local_fh); +void nfs_close_local_fh(struct nfs_file_localio *nfl) +{ + struct nfsd_file *ro_nf = NULL; + struct nfsd_file *rw_nf = NULL; + nfs_uuid_t *nfs_uuid; + + rcu_read_lock(); + nfs_uuid = rcu_dereference(nfl->nfs_uuid); + if (!nfs_uuid) { + /* regular (non-LOCALIO) NFS will hammer this */ + rcu_read_unlock(); + return; + } + + ro_nf = rcu_access_pointer(nfl->ro_file); + rw_nf = rcu_access_pointer(nfl->rw_file); + if (ro_nf || rw_nf) { + spin_lock(&nfs_uuid_lock); + if (ro_nf) + ro_nf = rcu_dereference_protected(xchg(&nfl->ro_file, NULL), 1); + if (rw_nf) + rw_nf = rcu_dereference_protected(xchg(&nfl->rw_file, NULL), 1); + + rcu_assign_pointer(nfl->nfs_uuid, NULL); + spin_unlock(&nfs_uuid_lock); + rcu_read_unlock(); + + if (ro_nf) + nfs_to_nfsd_file_put_local(ro_nf); + if (rw_nf) + nfs_to_nfsd_file_put_local(rw_nf); + return; + } + rcu_read_unlock(); +} +EXPORT_SYMBOL_GPL(nfs_close_local_fh); + /* * The NFS LOCALIO code needs to call into NFSD using various symbols, * but cannot be statically linked, because that will make the NFS diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 039898d70954f..67ae2c3f41d20 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -77,6 +77,23 @@ struct nfs_lock_context { struct rcu_head rcu_head; }; +struct nfs_file_localio { + struct nfsd_file __rcu *ro_file; + struct nfsd_file __rcu *rw_file; + struct list_head list; + void __rcu *nfs_uuid; /* opaque pointer to 'nfs_uuid_t' */ +}; + +static inline void nfs_localio_file_init(struct nfs_file_localio *nfl) +{ +#if IS_ENABLED(CONFIG_NFS_LOCALIO) + nfl->ro_file = NULL; + nfl->rw_file = NULL; + INIT_LIST_HEAD(&nfl->list); + nfl->nfs_uuid = NULL; +#endif +} + struct nfs4_state; struct nfs_open_context { struct nfs_lock_context lock_context; @@ -87,15 +104,16 @@ struct nfs_open_context { struct nfs4_state *state; fmode_t mode; + int error; unsigned long flags; #define NFS_CONTEXT_BAD (2) #define NFS_CONTEXT_UNLOCK (3) #define NFS_CONTEXT_FILE_OPEN (4) - int error; - struct list_head list; struct nfs4_threshold *mdsthreshold; + struct list_head list; struct rcu_head rcu_head; + struct nfs_file_localio nfl; }; struct nfs_open_dir_context { diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index 4d5583873f418..7cfc6720ed26d 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -6,10 +6,6 @@ #ifndef __LINUX_NFSLOCALIO_H #define __LINUX_NFSLOCALIO_H - -/* nfsd_file structure is purposely kept opaque to NFS client */ -struct nfsd_file; - #if IS_ENABLED(CONFIG_NFS_LOCALIO) #include @@ -21,6 +17,7 @@ struct nfsd_file; #include struct nfs_client; +struct nfs_file_localio; /* * Useful to allow a client to negotiate if localio @@ -52,6 +49,7 @@ extern struct nfsd_file * nfsd_open_local_fh(struct net *, struct auth_domain *, struct rpc_clnt *, const struct cred *, const struct nfs_fh *, const fmode_t) __must_hold(rcu); +void nfs_close_local_fh(struct nfs_file_localio *); struct nfsd_localio_operations { bool (*nfsd_serv_try_get)(struct net *); @@ -73,7 +71,8 @@ extern const struct nfsd_localio_operations *nfs_to; struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *, struct rpc_clnt *, const struct cred *, - const struct nfs_fh *, const fmode_t); + const struct nfs_fh *, struct nfs_file_localio *, + const fmode_t); static inline void nfs_to_nfsd_net_put(struct net *net) { @@ -100,12 +99,15 @@ static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) } #else /* CONFIG_NFS_LOCALIO */ + +struct nfs_file_localio; +static inline void nfs_close_local_fh(struct nfs_file_localio *nfl) +{ +} static inline void nfsd_localio_ops_init(void) { } -static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) -{ -} + #endif /* CONFIG_NFS_LOCALIO */ #endif /* __LINUX_NFSLOCALIO_H */ From patchwork Thu Nov 14 03:59:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874523 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 969DA1E909D for ; Thu, 14 Nov 2024 04:00:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556803; cv=none; b=ntVnPeZm+2LbngEJPLBJhXBip1PTdn6nsJ5gkjXuQg4tGoSx4fu26ey/7a1rHfeg3H9DjmdZP5o+v2jVjVC6Jk/T+Q/+xlMoJdZbK8gc81EbkqpuWu+dca8wTHaiN4/VW+9jdYnetKXC2ixuceJ/C6XmNZR9UysPeF2AemvgOo4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556803; c=relaxed/simple; bh=aLEZ2ZQJfuSiphNZJzZeGdxPt5oB5U2q09rbIDQg5w8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U58GfV5ohNI8QkTexyWdixlliO+7G+O2IpHWYZ41TLAatr/XYnNYbtPbUoZC4x5gJ+k1PbRQZggdwrRyznHIwZXLe3f0TS/dCXYbfpJWSHfhLHCmryR5WYXJL8DBstlVNLM7QvJ6CX2KxTCnvqkp++BC4GuNF0leYlMpp7nwvJc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MeL2zmlh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MeL2zmlh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D735AC4CED0; Thu, 14 Nov 2024 04:00:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556803; bh=aLEZ2ZQJfuSiphNZJzZeGdxPt5oB5U2q09rbIDQg5w8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MeL2zmlh/q8j9CJ9n6ia/bCEcvmJWt0Yipdgi/KCbo+YIO/JwCSesMckWf/McyWZ1 Ddg4ZiRp5PQKBoydg2X+10+pCrdAMCSIfqHL5cTnMaFRcor9lLsi/nLyuibA5Mri3O klDsQnZhQZHBCfK3MYGgZejdMATKfoOWH8/BaFdlRVQtOPs+34NwH/g01lHh2fSvOe 4VIfzSR5+qKh2QgmYRx1otKTJVonfIFXQ6BzWrT+h5RcY+Vz2dnULWF4lXrs2V9QV5 PNSioa1kNpYnwybO42ueqB8pd1XaVwk+08AutY9Y6MkzHMUTKQZ5qlHEOFT1efeXwJ 2DVWzUe2AgSPg== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 07/15] nfsd: update percpu_ref to manage references on nfsd_net Date: Wed, 13 Nov 2024 22:59:44 -0500 Message-ID: <20241114035952.13889-8-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Holding a reference on nfsd_net is what is required, it was never actually about ensuring nn->nfsd_serv available. Move waiting for outstanding percpu references from nfsd_destroy_serv() to nfsd_shutdown_net(). By moving it later it will be possible to invalidate localio clients during nfsd_file_cache_shutdown_net() via __nfsd_file_cache_purge(). Signed-off-by: Mike Snitzer --- fs/nfsd/nfssvc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 49e2f32102ab5..6ca5540424266 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -436,6 +436,10 @@ static void nfsd_shutdown_net(struct net *net) if (!nn->nfsd_net_up) return; + + percpu_ref_kill_and_confirm(&nn->nfsd_serv_ref, nfsd_serv_done); + wait_for_completion(&nn->nfsd_serv_confirm_done); + nfsd_export_flush(net); nfs4_state_shutdown_net(net); nfsd_reply_cache_shutdown(nn); @@ -444,7 +448,10 @@ static void nfsd_shutdown_net(struct net *net) lockd_down(net); nn->lockd_up = false; } + + wait_for_completion(&nn->nfsd_serv_free_done); percpu_ref_exit(&nn->nfsd_serv_ref); + nn->nfsd_net_up = false; nfsd_shutdown_generic(); } @@ -526,11 +533,6 @@ void nfsd_destroy_serv(struct net *net) lockdep_assert_held(&nfsd_mutex); - percpu_ref_kill_and_confirm(&nn->nfsd_serv_ref, nfsd_serv_done); - wait_for_completion(&nn->nfsd_serv_confirm_done); - wait_for_completion(&nn->nfsd_serv_free_done); - /* percpu_ref_exit is called in nfsd_shutdown_net */ - spin_lock(&nfsd_notifier_lock); nn->nfsd_serv = NULL; spin_unlock(&nfsd_notifier_lock); From patchwork Thu Nov 14 03:59:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874524 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D368C13D53E for ; Thu, 14 Nov 2024 04:00:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556804; cv=none; b=D7PqaCvj6EAVRcXJKmbnY5Ek7SaBWZ9I8aPVis6LI4cW+r5uKYE5UuWeWD6elxGHREDuW5h2n3gjjR43ZgNGcMM1Lo6wjihtWF2cjmbkxFU2Xnvz/Ud5xn2D2Ir2Ga2vIAJT6VwYmkMYEIm/N4TNreQrC/qDqxOUkfnR0u4Qlks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556804; c=relaxed/simple; bh=aUMSVApUmE4rxegSXSw9pqFLSppGiFwhNmHm0+PsQGo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pyXboJ5w33JiwKqsAQfokZ2f9Wu9Xz4Q0aBwpOz1nYNrzjxYDcZjs6vxHNtfP508Zu/BfiYrZO/7CGs7UvzDjehD8I6F5P/lD4ImqalI4aDTLxO1/mYqnMjmjHUzkOpl0/lOI6bu16dMKN/M82CdMRxqtb7c1374mCxND9qZRcM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Rp6fF+ei; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Rp6fF+ei" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 35BBFC4CED0; Thu, 14 Nov 2024 04:00:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556804; bh=aUMSVApUmE4rxegSXSw9pqFLSppGiFwhNmHm0+PsQGo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Rp6fF+eiAoQ33RmPLza57J3NuPEPrry0uP8e9AN2B5ZHTYTgzTm3x7VECWDT/3QMY X9lPhatBIPP4pDGAYIZx2/o5HAZJ+R5FosAILfKsNwiap96n3SeN6IinUxLGnjdPp0 3QwOGBZmNMDnfdVDqL9znSrVOzFczf0CgSzc3xMjE4zgi5E+ef4E5/A5qa4ff7gExK Z+GawIhgdqtfjasKGNDZSi9UK43C+QtZOkh/B8wJr4JO6dxCoh1QwmaXAnBKCe/KEW 9bJch6/pdwN7ZQmlgRjYSzGIoNU0fk8DeigEi6ZbTLeEYQ9ct1hOJO8M+jHUh0ksdt MaMMrJyqZ0ZDQ== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 08/15] nfsd: rename nfsd_serv_ prefixed methods and variables with nfsd_net_ Date: Wed, 13 Nov 2024 22:59:45 -0500 Message-ID: <20241114035952.13889-9-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Also update Documentation/filesystems/nfs/localio.rst accordingly and reduce the technical documentation debt that was previously captured in that document. Signed-off-by: Mike Snitzer --- Documentation/filesystems/nfs/localio.rst | 81 +++++++---------------- fs/nfs_common/nfslocalio.c | 10 ++- fs/nfsd/filecache.c | 2 +- fs/nfsd/localio.c | 4 +- fs/nfsd/netns.h | 11 +-- fs/nfsd/nfssvc.c | 34 +++++----- include/linux/nfslocalio.h | 12 ++-- 7 files changed, 64 insertions(+), 90 deletions(-) diff --git a/Documentation/filesystems/nfs/localio.rst b/Documentation/filesystems/nfs/localio.rst index eb3dc764cfce8..9d991a958c81c 100644 --- a/Documentation/filesystems/nfs/localio.rst +++ b/Documentation/filesystems/nfs/localio.rst @@ -218,64 +218,30 @@ NFS Client and Server Interlock =============================== LOCALIO provides the nfs_uuid_t object and associated interfaces to -allow proper network namespace (net-ns) and NFSD object refcounting: +allow proper network namespace (net-ns) and NFSD object refcounting. - We don't want to keep a long-term counted reference on each NFSD's - net-ns in the client because that prevents a server container from - completely shutting down. - - So we avoid taking a reference at all and rely on the per-cpu - reference to the server (detailed below) being sufficient to keep - the net-ns active. This involves allowing the NFSD's net-ns exit - code to iterate all active clients and clear their ->net pointers - (which are needed to find the per-cpu-refcount for the nfsd_serv). - - Details: - - - Embed nfs_uuid_t in nfs_client. nfs_uuid_t provides a list_head - that can be used to find the client. It does add the 16-byte - uuid_t to nfs_client so it is bigger than needed (given that - uuid_t is only used during the initial NFS client and server - LOCALIO handshake to determine if they are local to each other). - If that is really a problem we can find a fix. - - - When the nfs server confirms that the uuid_t is local, it moves - the nfs_uuid_t onto a per-net-ns list in NFSD's nfsd_net. - - - When each server's net-ns is shutting down - in a "pre_exit" - handler, all these nfs_uuid_t have their ->net cleared. There is - an rcu_synchronize() call between pre_exit() handlers and exit() - handlers so any caller that sees nfs_uuid_t ->net as not NULL can - safely manage the per-cpu-refcount for nfsd_serv. - - - The client's nfs_uuid_t is passed to nfsd_open_local_fh() so it - can safely dereference ->net in a private rcu_read_lock() section - to allow safe access to the associated nfsd_net and nfsd_serv. - -So LOCALIO required the introduction and use of NFSD's percpu_ref to -interlock nfsd_destroy_serv() and nfsd_open_local_fh(), to ensure each -nn->nfsd_serv is not destroyed while in use by nfsd_open_local_fh(), and +LOCALIO required the introduction and use of NFSD's percpu nfsd_net_ref +to interlock nfsd_shutdown_net() and nfsd_open_local_fh(), to ensure +each net-ns is not destroyed while in use by nfsd_open_local_fh(), and warrants a more detailed explanation: - nfsd_open_local_fh() uses nfsd_serv_try_get() before opening its + nfsd_open_local_fh() uses nfsd_net_try_get() before opening its nfsd_file handle and then the caller (NFS client) must drop the - reference for the nfsd_file and associated nn->nfsd_serv using - nfs_file_put_local() once it has completed its IO. + reference for the nfsd_file and associated net-ns using + nfsd_file_put_local() once it has completed its IO. This interlock working relies heavily on nfsd_open_local_fh() being afforded the ability to safely deal with the possibility that the NFSD's net-ns (and nfsd_net by association) may have been destroyed - by nfsd_destroy_serv() via nfsd_shutdown_net() -- which is only - possible given the nfs_uuid_t ->net pointer managemenet detailed - above. + by nfsd_destroy_serv() via nfsd_shutdown_net(). -All told, this elaborate interlock of the NFS client and server has been -verified to fix an easy to hit crash that would occur if an NFSD -instance running in a container, with a LOCALIO client mounted, is -shutdown. Upon restart of the container and associated NFSD the client -would go on to crash due to NULL pointer dereference that occurred due -to the LOCALIO client's attempting to nfsd_open_local_fh(), using -nn->nfsd_serv, without having a proper reference on nn->nfsd_serv. +This interlock of the NFS client and server has been verified to fix an +easy to hit crash that would occur if an NFSD instance running in a +container, with a LOCALIO client mounted, is shutdown. Upon restart of +the container and associated NFSD, the client would go on to crash due +to NULL pointer dereference that occurred due to the LOCALIO client's +attempting to nfsd_open_local_fh() without having a proper reference on +NFSD's net-ns. NFS Client issues IO instead of Server ====================================== @@ -308,14 +274,17 @@ fs/nfs/localio.c:nfs_local_commit(). With normal NFS that makes use of RPC to issue IO to the server, if an application uses O_DIRECT the NFS client will bypass the pagecache but -the NFS server will not. Because the NFS server's use of buffered IO -affords applications to be less precise with their alignment when -issuing IO to the NFS client. LOCALIO can be configured to use O_DIRECT -semantics by setting the 'localio_O_DIRECT_semantics' nfs module +the NFS server will not. The NFS server's use of buffered IO affords +applications to be less precise with their alignment when issuing IO to +the NFS client. But if all applications properly align their IO, LOCALIO +can be configured to use end-to-end O_DIRECT semantics from the NFS +client to the underlying local filesystem, that it is sharing with +the NFS server, by setting the 'localio_O_DIRECT_semantics' nfs module parameter to Y, e.g.: - echo Y > /sys/module/nfs/parameters/localio_O_DIRECT_semantics -Once enabled, it will cause LOCALIO to use O_DIRECT semantics (this may -cause IO to fail if applications do not properly align their IO). + echo Y > /sys/module/nfs/parameters/localio_O_DIRECT_semantics +Once enabled, it will cause LOCALIO to use end-to-end O_DIRECT semantics +(but again, this may cause IO to fail if applications do not properly +align their IO). Security ======== diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index 35a2e48731df6..e75cd21f4c8bc 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -159,6 +159,10 @@ static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl spin_unlock(&nfs_uuid_lock); } +/* + * Caller is responsible for calling nfsd_net_put and + * nfsd_file_put (via nfs_to_nfsd_file_put_local). + */ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, struct rpc_clnt *rpc_clnt, const struct cred *cred, const struct nfs_fh *nfs_fh, struct nfs_file_localio *nfl, @@ -171,7 +175,7 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, * Not running in nfsd context, so must safely get reference on nfsd_serv. * But the server may already be shutting down, if so disallow new localio. * uuid->net is NOT a counted reference, but rcu_read_lock() ensures that - * if uuid->net is not NULL, then calling nfsd_serv_try_get() is safe + * if uuid->net is not NULL, then calling nfsd_net_try_get() is safe * and if it succeeds we will have an implied reference to the net. * * Otherwise NFS may not have ref on NFSD and therefore cannot safely @@ -179,12 +183,12 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, */ rcu_read_lock(); net = rcu_dereference(uuid->net); - if (!net || !nfs_to->nfsd_serv_try_get(net)) { + if (!net || !nfs_to->nfsd_net_try_get(net)) { rcu_read_unlock(); return ERR_PTR(-ENXIO); } rcu_read_unlock(); - /* We have an implied reference to net thanks to nfsd_serv_try_get */ + /* We have an implied reference to net thanks to nfsd_net_try_get */ localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt, cred, nfs_fh, fmode); if (IS_ERR(localio)) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 9a62b4da89bb7..fac98b2cb463a 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -391,7 +391,7 @@ nfsd_file_put(struct nfsd_file *nf) } /** - * nfsd_file_put_local - put nfsd_file reference and arm nfsd_serv_put in caller + * nfsd_file_put_local - put nfsd_file reference and arm nfsd_net_put in caller * @nf: nfsd_file of which to put the reference * * First save the associated net to return to caller, then put diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c index 8beda4c851119..f9a91cd3b5ec7 100644 --- a/fs/nfsd/localio.c +++ b/fs/nfsd/localio.c @@ -25,8 +25,8 @@ #include "cache.h" static const struct nfsd_localio_operations nfsd_localio_ops = { - .nfsd_serv_try_get = nfsd_serv_try_get, - .nfsd_serv_put = nfsd_serv_put, + .nfsd_net_try_get = nfsd_net_try_get, + .nfsd_net_put = nfsd_net_put, .nfsd_open_local_fh = nfsd_open_local_fh, .nfsd_file_put_local = nfsd_file_put_local, .nfsd_file_get = nfsd_file_get, diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 26f7b34d1a030..8faef59d71229 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -140,9 +140,10 @@ struct nfsd_net { struct svc_info nfsd_info; #define nfsd_serv nfsd_info.serv - struct percpu_ref nfsd_serv_ref; - struct completion nfsd_serv_confirm_done; - struct completion nfsd_serv_free_done; + + struct percpu_ref nfsd_net_ref; + struct completion nfsd_net_confirm_done; + struct completion nfsd_net_free_done; /* * clientid and stateid data for construction of net unique COPY @@ -229,8 +230,8 @@ struct nfsd_net { extern bool nfsd_support_version(int vers); extern unsigned int nfsd_net_id; -bool nfsd_serv_try_get(struct net *net); -void nfsd_serv_put(struct net *net); +bool nfsd_net_try_get(struct net *net); +void nfsd_net_put(struct net *net); void nfsd_copy_write_verifier(__be32 verf[2], struct nfsd_net *nn); void nfsd_reset_write_verifier(struct nfsd_net *nn); diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 6ca5540424266..e937e2d0ce62c 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -214,32 +214,32 @@ int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change return 0; } -bool nfsd_serv_try_get(struct net *net) __must_hold(rcu) +bool nfsd_net_try_get(struct net *net) __must_hold(rcu) { struct nfsd_net *nn = net_generic(net, nfsd_net_id); - return (nn && percpu_ref_tryget_live(&nn->nfsd_serv_ref)); + return (nn && percpu_ref_tryget_live(&nn->nfsd_net_ref)); } -void nfsd_serv_put(struct net *net) __must_hold(rcu) +void nfsd_net_put(struct net *net) __must_hold(rcu) { struct nfsd_net *nn = net_generic(net, nfsd_net_id); - percpu_ref_put(&nn->nfsd_serv_ref); + percpu_ref_put(&nn->nfsd_net_ref); } -static void nfsd_serv_done(struct percpu_ref *ref) +static void nfsd_net_done(struct percpu_ref *ref) { - struct nfsd_net *nn = container_of(ref, struct nfsd_net, nfsd_serv_ref); + struct nfsd_net *nn = container_of(ref, struct nfsd_net, nfsd_net_ref); - complete(&nn->nfsd_serv_confirm_done); + complete(&nn->nfsd_net_confirm_done); } -static void nfsd_serv_free(struct percpu_ref *ref) +static void nfsd_net_free(struct percpu_ref *ref) { - struct nfsd_net *nn = container_of(ref, struct nfsd_net, nfsd_serv_ref); + struct nfsd_net *nn = container_of(ref, struct nfsd_net, nfsd_net_ref); - complete(&nn->nfsd_serv_free_done); + complete(&nn->nfsd_net_free_done); } /* @@ -437,8 +437,8 @@ static void nfsd_shutdown_net(struct net *net) if (!nn->nfsd_net_up) return; - percpu_ref_kill_and_confirm(&nn->nfsd_serv_ref, nfsd_serv_done); - wait_for_completion(&nn->nfsd_serv_confirm_done); + percpu_ref_kill_and_confirm(&nn->nfsd_net_ref, nfsd_net_done); + wait_for_completion(&nn->nfsd_net_confirm_done); nfsd_export_flush(net); nfs4_state_shutdown_net(net); @@ -449,8 +449,8 @@ static void nfsd_shutdown_net(struct net *net) nn->lockd_up = false; } - wait_for_completion(&nn->nfsd_serv_free_done); - percpu_ref_exit(&nn->nfsd_serv_ref); + wait_for_completion(&nn->nfsd_net_free_done); + percpu_ref_exit(&nn->nfsd_net_ref); nn->nfsd_net_up = false; nfsd_shutdown_generic(); @@ -654,12 +654,12 @@ int nfsd_create_serv(struct net *net) if (nn->nfsd_serv) return 0; - error = percpu_ref_init(&nn->nfsd_serv_ref, nfsd_serv_free, + error = percpu_ref_init(&nn->nfsd_net_ref, nfsd_net_free, 0, GFP_KERNEL); if (error) return error; - init_completion(&nn->nfsd_serv_free_done); - init_completion(&nn->nfsd_serv_confirm_done); + init_completion(&nn->nfsd_net_free_done); + init_completion(&nn->nfsd_net_confirm_done); if (nfsd_max_blksize == 0) nfsd_max_blksize = nfsd_get_default_max_blksize(); diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index 7cfc6720ed26d..aa2b5c6561ab0 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -52,8 +52,8 @@ nfsd_open_local_fh(struct net *, struct auth_domain *, struct rpc_clnt *, void nfs_close_local_fh(struct nfs_file_localio *); struct nfsd_localio_operations { - bool (*nfsd_serv_try_get)(struct net *); - void (*nfsd_serv_put)(struct net *); + bool (*nfsd_net_try_get)(struct net *); + void (*nfsd_net_put)(struct net *); struct nfsd_file *(*nfsd_open_local_fh)(struct net *, struct auth_domain *, struct rpc_clnt *, @@ -77,12 +77,12 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *, static inline void nfs_to_nfsd_net_put(struct net *net) { /* - * Once reference to nfsd_serv is dropped, NFSD could be - * unloaded, so ensure safe return from nfsd_file_put_local() - * by always taking RCU. + * Once reference to net (and associated nfsd_serv) is dropped, NFSD + * could be unloaded, so ensure safe return from nfsd_net_put() by + * always taking RCU. */ rcu_read_lock(); - nfs_to->nfsd_serv_put(net); + nfs_to->nfsd_net_put(net); rcu_read_unlock(); } From patchwork Thu Nov 14 03:59:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874525 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3344A1E22E4 for ; Thu, 14 Nov 2024 04:00:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556806; cv=none; b=MuDMOeLsteJOVOa2Z0fAjVcn7Eqzwmd+Fq8ZyysGBcXab1iJdG+iIGH0OHRZvDRnw3Bjgnatk0ruFK2Eo1d2cgQF8zw+8CfaGA782M653HNPw9GOfkxZAOQeeiFUJQO/gLuEgjLHNrPpHldOA/vLjZj0ViEeDYuf5yh95COHuZ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556806; c=relaxed/simple; bh=/UuCYvOSvt7cCffPKdRRc7N08KwkO0534EhYAUum0oE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LKxGVXA0N1XHHO2oxwtsG9aJB+39Bs52fb1NiJ6/OnAmG4IJVS4HlcgvgzOaxrzLOv8mcGsPWjMkUyhDfbuJOMmoy0K9D4h1CR/I6mLgSyY2JZq/cHPbBTiOM7tesomf4vh8/PN26h8whJsBhpEmz6jwSVaI0EDs6mQsjqKDCdQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VtAwlprt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VtAwlprt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7EEEFC4CED0; Thu, 14 Nov 2024 04:00:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556805; bh=/UuCYvOSvt7cCffPKdRRc7N08KwkO0534EhYAUum0oE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VtAwlprtI+J+0yRSdSo+31jpqd77xinsmhplPY7D9DWfdxD0cM3mHBe9rU0MeFfV4 IQTpcv+OTjRXVGP1ncf8l/wVZRtA1MlA+rdFgOKDmUc/ukpoQMEwscxZFxE7RqmJBv oKYvVFRZKHg2SB+Ct5BDpUvPnOpBcjmJFTDgGItJ99Xex6rlRcjnSVr3AJgYU3WkeJ f2lsFYl6bG86Po7Da0YtCNmF+EPJOvEGs7MYzg7lQzqyGNvHsoY8CcCT4QMonkG8fc i9MrKLPlYhvJJQ2vEDTYck7kKe+duE2dclkkrvukaKSTUI2O5jDRxt7NGNlu11veNo EnGtiviqvqEtw== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 09/15] nfsd: nfsd_file_acquire_local no longer returns GC'd nfsd_file Date: Wed, 13 Nov 2024 22:59:46 -0500 Message-ID: <20241114035952.13889-10-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Now that LOCALIO no longer leans on NFSD's filecache for caching open files (and instead uses NFS client-side open nfsd_file caching) there is no need to use NFSD filecache's GC feature. Avoiding GC will speed up nfsd_file initial opens. Signed-off-by: Mike Snitzer --- fs/nfsd/filecache.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index fac98b2cb463a..ab9942e420543 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -1225,10 +1225,9 @@ nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, * a file. The security implications of this should be carefully * considered before use. * - * The nfsd_file object returned by this API is reference-counted - * and garbage-collected. The object is retained for a few - * seconds after the final nfsd_file_put() in case the caller - * wants to re-use it. + * The nfsd_file_object returned by this API is reference-counted + * but not garbage-collected. The object is unhashed after the + * final nfsd_file_put(). * * Return values: * %nfs_ok - @pnf points to an nfsd_file with its reference @@ -1250,7 +1249,7 @@ nfsd_file_acquire_local(struct net *net, struct svc_cred *cred, __be32 beres; beres = nfsd_file_do_acquire(NULL, net, cred, client, - fhp, may_flags, NULL, pnf, true); + fhp, may_flags, NULL, pnf, false); revert_creds(save_cred); return beres; } From patchwork Thu Nov 14 03:59:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874526 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F98C1E7C15 for ; Thu, 14 Nov 2024 04:00:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556807; cv=none; b=nW0R/Q3+BCPVyRFH6Rk/+Q391e4qJZQ1la+ybxh5+cYN8hmtXr7kjUwn1U8qob7Cvk2WyJgA886vmfOX+Lp2KmsLqg0gZEhrOnB346LPCSBzf3A+R6Jm3jp4p3BZxAORz1TN5plSmmmL24Bre4UbKXF8zpyZjAU4gPJurtJ3t0w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556807; c=relaxed/simple; bh=Rg44joD30DU58lNMqd9vzqalbE/nDnh5v3G/nwCffaE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GkuRoCQFMzTvzWAYkeeC7hndezIpz5IHflFDLiN5oIFHYOnmkgfKF/g/VIDKcAo8FcFs3tN709iqEEF7GQlBHI8rQ+qJNeVlbywOZ1h0qqCtmdU/soaOvohi86wn2oIkiRYcRLRl77bvHGKHrRSX/NlhFKBRqjrkSSzWs46EDD4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YNOIKQ59; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YNOIKQ59" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D9499C4CED0; Thu, 14 Nov 2024 04:00:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556807; bh=Rg44joD30DU58lNMqd9vzqalbE/nDnh5v3G/nwCffaE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YNOIKQ59viXxA7Hs4QPjGtZfEfb+Xg3GgVdKBVXuvPJz7e8zu/2oVE2OBsWlOxIQM wkkYUGEWjYrMO1GLDqS+7Q/CnTwAVVgR5X9bGYB3Ok6n6DM3BqyDZ63lz1DMr3HA3n A7B8Ylyrkp/7QoY4Q7/VWeeTf8RP93cQz3g1Ou9nGYsSGcBrA79+YUknKnTvMIodG7 qjJKhzZ17cIu8fyPnNJine0hJ38wSZKE8K7ewehsfmuejcu4mxen3n4UUL3eqbCzZe VQG39looG60LiiWacFkAjOEIwBxDo6KxzYCni8U/4PmmkDWcG20n4yowH7LIIvBRdi Kra69WljbZRtA== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 10/15] nfs_common: rename nfslocalio nfs_uuid_lock to nfs_uuids_lock Date: Wed, 13 Nov 2024 22:59:47 -0500 Message-ID: <20241114035952.13889-11-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This global spinlock protects all nfs_uuid_t relative to the global nfs_uuids list. A later commit will split this global spinlock so prepare by renaming this lock to reflect its intended narrow scope. Signed-off-by: Mike Snitzer --- fs/nfs_common/nfslocalio.c | 34 +++++++++++++++++----------------- fs/nfsd/localio.c | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index e75cd21f4c8bc..5fa3f47b442e9 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -15,11 +15,11 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("NFS localio protocol bypass support"); -static DEFINE_SPINLOCK(nfs_uuid_lock); +static DEFINE_SPINLOCK(nfs_uuids_lock); /* * Global list of nfs_uuid_t instances - * that is protected by nfs_uuid_lock. + * that is protected by nfs_uuids_lock. */ static LIST_HEAD(nfs_uuids); @@ -34,15 +34,15 @@ EXPORT_SYMBOL_GPL(nfs_uuid_init); bool nfs_uuid_begin(nfs_uuid_t *nfs_uuid) { - spin_lock(&nfs_uuid_lock); + spin_lock(&nfs_uuids_lock); /* Is this nfs_uuid already in use? */ if (!list_empty(&nfs_uuid->list)) { - spin_unlock(&nfs_uuid_lock); + spin_unlock(&nfs_uuids_lock); return false; } uuid_gen(&nfs_uuid->uuid); list_add_tail(&nfs_uuid->list, &nfs_uuids); - spin_unlock(&nfs_uuid_lock); + spin_unlock(&nfs_uuids_lock); return true; } @@ -51,10 +51,10 @@ EXPORT_SYMBOL_GPL(nfs_uuid_begin); void nfs_uuid_end(nfs_uuid_t *nfs_uuid) { if (nfs_uuid->net == NULL) { - spin_lock(&nfs_uuid_lock); + spin_lock(&nfs_uuids_lock); if (nfs_uuid->net == NULL) list_del_init(&nfs_uuid->list); - spin_unlock(&nfs_uuid_lock); + spin_unlock(&nfs_uuids_lock); } } EXPORT_SYMBOL_GPL(nfs_uuid_end); @@ -78,7 +78,7 @@ void nfs_uuid_is_local(const uuid_t *uuid, struct list_head *list, { nfs_uuid_t *nfs_uuid; - spin_lock(&nfs_uuid_lock); + spin_lock(&nfs_uuids_lock); nfs_uuid = nfs_uuid_lookup_locked(uuid); if (nfs_uuid) { kref_get(&dom->ref); @@ -94,7 +94,7 @@ void nfs_uuid_is_local(const uuid_t *uuid, struct list_head *list, __module_get(mod); nfsd_mod = mod; } - spin_unlock(&nfs_uuid_lock); + spin_unlock(&nfs_uuids_lock); } EXPORT_SYMBOL_GPL(nfs_uuid_is_local); @@ -128,9 +128,9 @@ void nfs_localio_disable_client(struct nfs_client *clp) spin_lock(&nfs_uuid->lock); if (test_and_clear_bit(NFS_CS_LOCAL_IO, &clp->cl_flags)) { - spin_lock(&nfs_uuid_lock); + spin_lock(&nfs_uuids_lock); nfs_uuid_put_locked(nfs_uuid); - spin_unlock(&nfs_uuid_lock); + spin_unlock(&nfs_uuids_lock); } spin_unlock(&nfs_uuid->lock); } @@ -140,23 +140,23 @@ void nfs_localio_invalidate_clients(struct list_head *cl_uuid_list) { nfs_uuid_t *nfs_uuid, *tmp; - spin_lock(&nfs_uuid_lock); + spin_lock(&nfs_uuids_lock); list_for_each_entry_safe(nfs_uuid, tmp, cl_uuid_list, list) { struct nfs_client *clp = container_of(nfs_uuid, struct nfs_client, cl_uuid); nfs_localio_disable_client(clp); } - spin_unlock(&nfs_uuid_lock); + spin_unlock(&nfs_uuids_lock); } EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients); static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl) { - spin_lock(&nfs_uuid_lock); + spin_lock(&nfs_uuids_lock); if (!nfl->nfs_uuid) rcu_assign_pointer(nfl->nfs_uuid, nfs_uuid); - spin_unlock(&nfs_uuid_lock); + spin_unlock(&nfs_uuids_lock); } /* @@ -217,14 +217,14 @@ void nfs_close_local_fh(struct nfs_file_localio *nfl) ro_nf = rcu_access_pointer(nfl->ro_file); rw_nf = rcu_access_pointer(nfl->rw_file); if (ro_nf || rw_nf) { - spin_lock(&nfs_uuid_lock); + spin_lock(&nfs_uuids_lock); if (ro_nf) ro_nf = rcu_dereference_protected(xchg(&nfl->ro_file, NULL), 1); if (rw_nf) rw_nf = rcu_dereference_protected(xchg(&nfl->rw_file, NULL), 1); rcu_assign_pointer(nfl->nfs_uuid, NULL); - spin_unlock(&nfs_uuid_lock); + spin_unlock(&nfs_uuids_lock); rcu_read_unlock(); if (ro_nf) diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c index f9a91cd3b5ec7..2ae07161b9195 100644 --- a/fs/nfsd/localio.c +++ b/fs/nfsd/localio.c @@ -54,7 +54,7 @@ void nfsd_localio_ops_init(void) * avoid all the NFS overhead with reads, writes and commits. * * On successful return, returned nfsd_file will have its nf_net member - * set. Caller (NFS client) is responsible for calling nfsd_serv_put and + * set. Caller (NFS client) is responsible for calling nfsd_net_put and * nfsd_file_put (via nfs_to_nfsd_file_put_local). */ struct nfsd_file * From patchwork Thu Nov 14 03:59:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874527 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 983F01E22E4 for ; Thu, 14 Nov 2024 04:00:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556808; cv=none; b=JikTF1yiyrIizCz9CbTXV4T8Y2blxjeI5JE9++nQuoKcQC77sRMBTpm6Tdy1hojyj9aTkl142LwnJNZjCN8JeVx+IFO6LF7OwNWW9dzwi3jrX6t0wh/p070xYzKHw1cy7DlnC86cQ2ZHCyguiN4wUNX9RuoJcIMLIX56n6pvZoY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556808; c=relaxed/simple; bh=3ttQBIkjaCQ9n5j/9Os/A3KZl8ziuelaTPtXJdhcUmA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RdB2Ml7Ep5GHuzbhLTssB5oXej+WJ59vmDPeEQuATNoOepvPhqKiU4Z5/nq9594/Q73/LdvZRrB5rs1m3+mUsleUtO0B0RNHjO17DFkMh9xlH3J4q55VGZy5CkW3Wn3iS8EpE1LPd0hBUrrVlFM1rbjvB4uUusPFYCJE/Wumng0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LuynzYqR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LuynzYqR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 38070C4CED0; Thu, 14 Nov 2024 04:00:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556808; bh=3ttQBIkjaCQ9n5j/9Os/A3KZl8ziuelaTPtXJdhcUmA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LuynzYqRNACQOQDSG61OlI4yZ7brLKNdN86V6v+OZg2CUPKmvr8l5Dx6BMmQlKfOz MojVNNDIzBM9gRtYzBs7c5Zerbp4fLHpvry5yMpAlWmjmqkzUFe015CmLtJF5Qt3TN wWa3sOsmR8TahUFO2RTKcLRUsPDGcl4yr8gg6QgNZiWWiKm1m5shnA9FCw9w+wRdzE /3b13iL+H+rzG+sg1DtDvjlmjZHIAP5ZNi67yzR5SeZtCOaHHjeewxI65pYz/pc/st +SS3Qbdp9dAMVo0rgXB320Rh1+33aKvHxXwvczD3KIa9iVitFF6uXEH/9rF+xlSoNY XoGRGqNytqyYA== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 11/15] nfs_common: track all open nfsd_files per LOCALIO nfs_client Date: Wed, 13 Nov 2024 22:59:48 -0500 Message-ID: <20241114035952.13889-12-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This tracking enables __nfsd_file_cache_purge() to call nfs_localio_invalidate_clients(), upon shutdown or export change, to nfs_close_local_fh() all open nfsd_files that are still cached by the LOCALIO nfs clients associated with nfsd_net that is being shutdown. Now that the client must track all open nfsd_files there was more work than necessary being done with the global nfs_uuids_lock contended. This manifested in various RCU issues, e.g.: hrtimer: interrupt took 47969440 ns rcu: INFO: rcu_sched detected stalls on CPUs/tasks: Use nfs_uuid->lock to protect all nfs_uuid_t members, instead of nfs_uuids_lock, once nfs_uuid_is_local() adds the client to nn->local_clients. Also add 'local_clients_lock' to 'struct nfsd_net' to protect nn->local_clients. And store a pointer to spinlock in the 'list_lock' member of nfs_uuid_t so nfs_localio_disable_client() can use it to avoid taking the global nfs_uuids_lock. In combination, these split out locks eliminate the use of the single nfslocalio.c global nfs_uuids_lock in the IO paths (open and close). Also refactored associated fs/nfs_common/nfslocalio.c methods' locking to reduce work performed with spinlocks held in general. Signed-off-by: Mike Snitzer --- fs/nfs_common/nfslocalio.c | 166 +++++++++++++++++++++++++++---------- fs/nfsd/filecache.c | 9 ++ fs/nfsd/localio.c | 1 + fs/nfsd/netns.h | 1 + fs/nfsd/nfsctl.c | 4 +- include/linux/nfslocalio.h | 8 +- 6 files changed, 143 insertions(+), 46 deletions(-) diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index 5fa3f47b442e9..e5c0912b9a025 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -23,27 +23,49 @@ static DEFINE_SPINLOCK(nfs_uuids_lock); */ static LIST_HEAD(nfs_uuids); +/* + * Lock ordering: + * 1: nfs_uuid->lock + * 2: nfs_uuids_lock + * 3: nfs_uuid->list_lock (aka nn->local_clients_lock) + * + * May skip locks in select cases, but never hold multiple + * locks out of order. + */ + void nfs_uuid_init(nfs_uuid_t *nfs_uuid) { nfs_uuid->net = NULL; nfs_uuid->dom = NULL; + nfs_uuid->list_lock = NULL; INIT_LIST_HEAD(&nfs_uuid->list); + INIT_LIST_HEAD(&nfs_uuid->files); spin_lock_init(&nfs_uuid->lock); } EXPORT_SYMBOL_GPL(nfs_uuid_init); bool nfs_uuid_begin(nfs_uuid_t *nfs_uuid) { + spin_lock(&nfs_uuid->lock); + if (nfs_uuid->net) { + /* This nfs_uuid is already in use */ + spin_unlock(&nfs_uuid->lock); + return false; + } + spin_lock(&nfs_uuids_lock); - /* Is this nfs_uuid already in use? */ if (!list_empty(&nfs_uuid->list)) { + /* This nfs_uuid is already in use */ spin_unlock(&nfs_uuids_lock); + spin_unlock(&nfs_uuid->lock); return false; } - uuid_gen(&nfs_uuid->uuid); list_add_tail(&nfs_uuid->list, &nfs_uuids); spin_unlock(&nfs_uuids_lock); + uuid_gen(&nfs_uuid->uuid); + spin_unlock(&nfs_uuid->lock); + return true; } EXPORT_SYMBOL_GPL(nfs_uuid_begin); @@ -51,11 +73,15 @@ EXPORT_SYMBOL_GPL(nfs_uuid_begin); void nfs_uuid_end(nfs_uuid_t *nfs_uuid) { if (nfs_uuid->net == NULL) { - spin_lock(&nfs_uuids_lock); - if (nfs_uuid->net == NULL) + spin_lock(&nfs_uuid->lock); + if (nfs_uuid->net == NULL) { + /* Not local, remove from nfs_uuids */ + spin_lock(&nfs_uuids_lock); list_del_init(&nfs_uuid->list); - spin_unlock(&nfs_uuids_lock); - } + spin_unlock(&nfs_uuids_lock); + } + spin_unlock(&nfs_uuid->lock); + } } EXPORT_SYMBOL_GPL(nfs_uuid_end); @@ -73,28 +99,39 @@ static nfs_uuid_t * nfs_uuid_lookup_locked(const uuid_t *uuid) static struct module *nfsd_mod; void nfs_uuid_is_local(const uuid_t *uuid, struct list_head *list, - struct net *net, struct auth_domain *dom, - struct module *mod) + spinlock_t *list_lock, struct net *net, + struct auth_domain *dom, struct module *mod) { nfs_uuid_t *nfs_uuid; spin_lock(&nfs_uuids_lock); nfs_uuid = nfs_uuid_lookup_locked(uuid); - if (nfs_uuid) { - kref_get(&dom->ref); - nfs_uuid->dom = dom; - /* - * We don't hold a ref on the net, but instead put - * ourselves on a list so the net pointer can be - * invalidated. - */ - list_move(&nfs_uuid->list, list); - rcu_assign_pointer(nfs_uuid->net, net); - - __module_get(mod); - nfsd_mod = mod; + if (!nfs_uuid) { + spin_unlock(&nfs_uuids_lock); + return; } + + /* + * We don't hold a ref on the net, but instead put + * ourselves on @list (nn->local_clients) so the net + * pointer can be invalidated. + */ + spin_lock(list_lock); /* list_lock is nn->local_clients_lock */ + list_move(&nfs_uuid->list, list); + spin_unlock(list_lock); + spin_unlock(&nfs_uuids_lock); + /* Once nfs_uuid is parented to @list, avoid global nfs_uuids_lock */ + spin_lock(&nfs_uuid->lock); + + __module_get(mod); + nfsd_mod = mod; + + nfs_uuid->list_lock = list_lock; + kref_get(&dom->ref); + nfs_uuid->dom = dom; + rcu_assign_pointer(nfs_uuid->net, net); + spin_unlock(&nfs_uuid->lock); } EXPORT_SYMBOL_GPL(nfs_uuid_is_local); @@ -108,55 +145,96 @@ void nfs_localio_enable_client(struct nfs_client *clp) } EXPORT_SYMBOL_GPL(nfs_localio_enable_client); -static void nfs_uuid_put_locked(nfs_uuid_t *nfs_uuid) +/* + * Cleanup the nfs_uuid_t embedded in an nfs_client. + * This is the long-form of nfs_uuid_init(). + */ +static void nfs_uuid_put(nfs_uuid_t *nfs_uuid) { - if (!nfs_uuid->net) + LIST_HEAD(local_files); + struct nfs_file_localio *nfl, *tmp; + + spin_lock(&nfs_uuid->lock); + if (unlikely(!nfs_uuid->net)) { + spin_unlock(&nfs_uuid->lock); return; - module_put(nfsd_mod); + } RCU_INIT_POINTER(nfs_uuid->net, NULL); if (nfs_uuid->dom) { auth_domain_put(nfs_uuid->dom); nfs_uuid->dom = NULL; } - list_del_init(&nfs_uuid->list); + + list_splice_init(&nfs_uuid->files, &local_files); + spin_unlock(&nfs_uuid->lock); + + /* Walk list of files and ensure their last references dropped */ + list_for_each_entry_safe(nfl, tmp, &local_files, list) { + nfs_close_local_fh(nfl); + cond_resched(); + } + + spin_lock(&nfs_uuid->lock); + BUG_ON(!list_empty(&nfs_uuid->files)); + + /* Remove client from nn->local_clients */ + if (nfs_uuid->list_lock) { + spin_lock(nfs_uuid->list_lock); + BUG_ON(list_empty(&nfs_uuid->list)); + list_del_init(&nfs_uuid->list); + spin_unlock(nfs_uuid->list_lock); + nfs_uuid->list_lock = NULL; + } + + module_put(nfsd_mod); + spin_unlock(&nfs_uuid->lock); } void nfs_localio_disable_client(struct nfs_client *clp) { - nfs_uuid_t *nfs_uuid = &clp->cl_uuid; + nfs_uuid_t *nfs_uuid = NULL; - spin_lock(&nfs_uuid->lock); + spin_lock(&clp->cl_uuid.lock); /* aka &nfs_uuid->lock */ if (test_and_clear_bit(NFS_CS_LOCAL_IO, &clp->cl_flags)) { - spin_lock(&nfs_uuids_lock); - nfs_uuid_put_locked(nfs_uuid); - spin_unlock(&nfs_uuids_lock); + /* &clp->cl_uuid is always not NULL, using as bool here */ + nfs_uuid = &clp->cl_uuid; } - spin_unlock(&nfs_uuid->lock); + spin_unlock(&clp->cl_uuid.lock); + + if (nfs_uuid) + nfs_uuid_put(nfs_uuid); } EXPORT_SYMBOL_GPL(nfs_localio_disable_client); -void nfs_localio_invalidate_clients(struct list_head *cl_uuid_list) +void nfs_localio_invalidate_clients(struct list_head *nn_local_clients, + spinlock_t *nn_local_clients_lock) { + LIST_HEAD(local_clients); nfs_uuid_t *nfs_uuid, *tmp; + struct nfs_client *clp; - spin_lock(&nfs_uuids_lock); - list_for_each_entry_safe(nfs_uuid, tmp, cl_uuid_list, list) { - struct nfs_client *clp = - container_of(nfs_uuid, struct nfs_client, cl_uuid); - + spin_lock(nn_local_clients_lock); + list_splice_init(nn_local_clients, &local_clients); + spin_unlock(nn_local_clients_lock); + list_for_each_entry_safe(nfs_uuid, tmp, &local_clients, list) { + if (WARN_ON(nfs_uuid->list_lock != nn_local_clients_lock)) + break; + clp = container_of(nfs_uuid, struct nfs_client, cl_uuid); nfs_localio_disable_client(clp); } - spin_unlock(&nfs_uuids_lock); } EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients); static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl) { - spin_lock(&nfs_uuids_lock); - if (!nfl->nfs_uuid) + /* Add nfl to nfs_uuid->files if it isn't already */ + spin_lock(&nfs_uuid->lock); + if (list_empty(&nfl->list)) { rcu_assign_pointer(nfl->nfs_uuid, nfs_uuid); - spin_unlock(&nfs_uuids_lock); + list_add_tail(&nfl->list, &nfs_uuid->files); + } + spin_unlock(&nfs_uuid->lock); } /* @@ -217,14 +295,16 @@ void nfs_close_local_fh(struct nfs_file_localio *nfl) ro_nf = rcu_access_pointer(nfl->ro_file); rw_nf = rcu_access_pointer(nfl->rw_file); if (ro_nf || rw_nf) { - spin_lock(&nfs_uuids_lock); + spin_lock(&nfs_uuid->lock); if (ro_nf) ro_nf = rcu_dereference_protected(xchg(&nfl->ro_file, NULL), 1); if (rw_nf) rw_nf = rcu_dereference_protected(xchg(&nfl->rw_file, NULL), 1); + /* Remove nfl from nfs_uuid->files list */ rcu_assign_pointer(nfl->nfs_uuid, NULL); - spin_unlock(&nfs_uuids_lock); + list_del_init(&nfl->list); + spin_unlock(&nfs_uuid->lock); rcu_read_unlock(); if (ro_nf) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index ab9942e420543..c9ab64e3732ce 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "vfs.h" #include "nfsd.h" @@ -836,6 +837,14 @@ __nfsd_file_cache_purge(struct net *net) struct nfsd_file *nf; LIST_HEAD(dispose); +#if IS_ENABLED(CONFIG_NFS_LOCALIO) + if (net) { + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + nfs_localio_invalidate_clients(&nn->local_clients, + &nn->local_clients_lock); + } +#endif + rhltable_walk_enter(&nfsd_file_rhltable, &iter); do { rhashtable_walk_start(&iter); diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c index 2ae07161b9195..238647fa379e3 100644 --- a/fs/nfsd/localio.c +++ b/fs/nfsd/localio.c @@ -116,6 +116,7 @@ static __be32 localio_proc_uuid_is_local(struct svc_rqst *rqstp) struct nfsd_net *nn = net_generic(net, nfsd_net_id); nfs_uuid_is_local(&argp->uuid, &nn->local_clients, + &nn->local_clients_lock, net, rqstp->rq_client, THIS_MODULE); return rpc_success; diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 8faef59d71229..187c4140b1913 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -220,6 +220,7 @@ struct nfsd_net { #if IS_ENABLED(CONFIG_NFS_LOCALIO) /* Local clients to be invalidated when net is shut down */ + spinlock_t local_clients_lock; struct list_head local_clients; #endif }; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 727904d8a4d01..70347b0ecdc43 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2259,6 +2259,7 @@ static __net_init int nfsd_net_init(struct net *net) seqlock_init(&nn->writeverf_lock); nfsd_proc_stat_init(net); #if IS_ENABLED(CONFIG_NFS_LOCALIO) + spin_lock_init(&nn->local_clients_lock); INIT_LIST_HEAD(&nn->local_clients); #endif return 0; @@ -2283,7 +2284,8 @@ static __net_exit void nfsd_net_pre_exit(struct net *net) { struct nfsd_net *nn = net_generic(net, nfsd_net_id); - nfs_localio_invalidate_clients(&nn->local_clients); + nfs_localio_invalidate_clients(&nn->local_clients, + &nn->local_clients_lock); } #endif diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index aa2b5c6561ab0..c68a529230c14 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -30,19 +30,23 @@ typedef struct { /* sadly this struct is just over a cacheline, avoid bouncing */ spinlock_t ____cacheline_aligned lock; struct list_head list; + spinlock_t *list_lock; /* nn->local_clients_lock */ struct net __rcu *net; /* nfsd's network namespace */ struct auth_domain *dom; /* auth_domain for localio */ + /* Local files to close when net is shut down or exports change */ + struct list_head files; } nfs_uuid_t; void nfs_uuid_init(nfs_uuid_t *); bool nfs_uuid_begin(nfs_uuid_t *); void nfs_uuid_end(nfs_uuid_t *); -void nfs_uuid_is_local(const uuid_t *, struct list_head *, +void nfs_uuid_is_local(const uuid_t *, struct list_head *, spinlock_t *, struct net *, struct auth_domain *, struct module *); void nfs_localio_enable_client(struct nfs_client *clp); void nfs_localio_disable_client(struct nfs_client *clp); -void nfs_localio_invalidate_clients(struct list_head *list); +void nfs_localio_invalidate_clients(struct list_head *nn_local_clients, + spinlock_t *nn_local_clients_lock); /* localio needs to map filehandle -> struct nfsd_file */ extern struct nfsd_file * From patchwork Thu Nov 14 03:59:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874528 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E7401E8836 for ; Thu, 14 Nov 2024 04:00:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556810; cv=none; b=rmP3EKVyzbrd6k0I2iOjGkLp678qiTNeOLj6qBSiCDvAMClklXYqn3BA+2QJCBcdcjuF8iBDXnO/Tn1m7nST+t6uPfMEClDtymU8csjaBInwry1EG/WXQbLbGmT0lS/oikaE9OyzQqBHvVxv1GIRfeHfPPPy0sqjFMudyDqjZf4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556810; c=relaxed/simple; bh=+bDZZG5/acWtaXGTZCAKQhewps9Xs+9o6MFd51/d+Rk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sWu5cYyoaWMNRU+r5Py+64/pX82j7nP/FUclkrCXAxbk6zCNh/FHrB2B48jbACFmNRxVCUU4/h7f4wh0u9YfoJgaEJaAf5vHFIWesvfXtVRyyg8ZvmGqJHkMDRyBnaVRa5AtEJriDKTb8qkynmuoqHbeuU3B+9Ru+3WljWIurOA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YgBkmwef; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YgBkmwef" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 85581C4CED0; Thu, 14 Nov 2024 04:00:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556809; bh=+bDZZG5/acWtaXGTZCAKQhewps9Xs+9o6MFd51/d+Rk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YgBkmwefK7ZxwVphAAme82dSsd2Ej01ixmvJ80LL31CZEGYcY3+0frMa7Q1vl1IaL hp+5v4/qemgutUzjvSmxyI99CA0sXN6Mo2E4s16pJTLbUOBDL3Kdv0wT3UY3nrRsNM pSy0kF/vHU+Lu1X/VwfvjTaNNYNrzp0j4fdz7LnT/ChaOXgKTB1zCCOkoC5TQJqFyw 3IGqngZRUC1A8JR+k+7m4tXWkA1tT2Ap3qBm732PBHSGZXa+y5DIad07gE6z7MYdZZ cpXvPwUqfzvORz8zngMcKt7qSa8cQ+byKa2e1tmAXmB+0SAeetsM+rLM/7A5nOstiC hVBOLRvi3B19w== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 12/15] nfs_common: add nfs_localio trace events Date: Wed, 13 Nov 2024 22:59:49 -0500 Message-ID: <20241114035952.13889-13-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The nfs_localio.ko now exposes /sys/kernel/tracing/events/nfs_localio with nfs_localio_enable_client and nfs_localio_disable_client events. Signed-off-by: Mike Snitzer --- fs/nfs_common/Makefile | 3 +- fs/nfs_common/localio_trace.c | 10 +++++++ fs/nfs_common/localio_trace.h | 56 +++++++++++++++++++++++++++++++++++ fs/nfs_common/nfslocalio.c | 4 +++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 fs/nfs_common/localio_trace.c create mode 100644 fs/nfs_common/localio_trace.h diff --git a/fs/nfs_common/Makefile b/fs/nfs_common/Makefile index a5e54809701e3..c10ead273ff2c 100644 --- a/fs/nfs_common/Makefile +++ b/fs/nfs_common/Makefile @@ -6,8 +6,9 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o nfs_acl-objs := nfsacl.o +CFLAGS_localio_trace.o += -I$(src) obj-$(CONFIG_NFS_COMMON_LOCALIO_SUPPORT) += nfs_localio.o -nfs_localio-objs := nfslocalio.o +nfs_localio-objs := nfslocalio.o localio_trace.o obj-$(CONFIG_GRACE_PERIOD) += grace.o obj-$(CONFIG_NFS_V4_2_SSC_HELPER) += nfs_ssc.o diff --git a/fs/nfs_common/localio_trace.c b/fs/nfs_common/localio_trace.c new file mode 100644 index 0000000000000..7decfe57abebb --- /dev/null +++ b/fs/nfs_common/localio_trace.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2024 Trond Myklebust + * Copyright (C) 2024 Mike Snitzer + */ +#include +#include + +#define CREATE_TRACE_POINTS +#include "localio_trace.h" diff --git a/fs/nfs_common/localio_trace.h b/fs/nfs_common/localio_trace.h new file mode 100644 index 0000000000000..4055aec9ff8dc --- /dev/null +++ b/fs/nfs_common/localio_trace.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2024 Trond Myklebust + * Copyright (C) 2024 Mike Snitzer + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM nfs_localio + +#if !defined(_TRACE_NFS_COMMON_LOCALIO_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_NFS_COMMON_LOCALIO_H + +#include + +#include +#include +#include + +DECLARE_EVENT_CLASS(nfs_local_client_event, + TP_PROTO( + const struct nfs_client *clp + ), + + TP_ARGS(clp), + + TP_STRUCT__entry( + __field(unsigned int, protocol) + __string(server, clp->cl_hostname) + ), + + TP_fast_assign( + __entry->protocol = clp->rpc_ops->version; + __assign_str(server); + ), + + TP_printk( + "server=%s NFSv%u", __get_str(server), __entry->protocol + ) +); + +#define DEFINE_NFS_LOCAL_CLIENT_EVENT(name) \ + DEFINE_EVENT(nfs_local_client_event, name, \ + TP_PROTO( \ + const struct nfs_client *clp \ + ), \ + TP_ARGS(clp)) + +DEFINE_NFS_LOCAL_CLIENT_EVENT(nfs_localio_enable_client); +DEFINE_NFS_LOCAL_CLIENT_EVENT(nfs_localio_disable_client); + +#endif /* _TRACE_NFS_COMMON_LOCALIO_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE localio_trace +/* This part must be outside protection */ +#include diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index e5c0912b9a025..4e4991e059413 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -12,6 +12,8 @@ #include #include +#include "localio_trace.h" + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("NFS localio protocol bypass support"); @@ -141,6 +143,7 @@ void nfs_localio_enable_client(struct nfs_client *clp) spin_lock(&nfs_uuid->lock); set_bit(NFS_CS_LOCAL_IO, &clp->cl_flags); + trace_nfs_localio_enable_client(clp); spin_unlock(&nfs_uuid->lock); } EXPORT_SYMBOL_GPL(nfs_localio_enable_client); @@ -199,6 +202,7 @@ void nfs_localio_disable_client(struct nfs_client *clp) if (test_and_clear_bit(NFS_CS_LOCAL_IO, &clp->cl_flags)) { /* &clp->cl_uuid is always not NULL, using as bool here */ nfs_uuid = &clp->cl_uuid; + trace_nfs_localio_disable_client(clp); } spin_unlock(&clp->cl_uuid.lock); From patchwork Thu Nov 14 03:59:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874529 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20FE11E8836 for ; Thu, 14 Nov 2024 04:00:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556811; cv=none; b=QRpUmjZjFuZ97+Q/2w3QHHHjWXkxbnHArNpWgFbxCge7zazVe82ueSJy4+iHOxYYAO34tvxpCvhLDIGCXdVEl6bTP1Uss1w908am8UuvDzLliIUooSrObRdULclcRwoXxDoGdL3V5U3Jlrx357Cggrk/LV/1QksFJ89FMyy+uLk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556811; c=relaxed/simple; bh=3C3Xq0hxZ36iLjeQuzA/kkrrmPX01XR3AlW+rrMmhbQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WGOkxIRhngUKKf0st4xeWdxidNvr7/TfmkCnu4SmYXFM0VMvbO5OeH2vivpKpKxLUlzituUQm2aUnuES4v07o2M+TA+HwzFEYHdiXFl6Q6XDqX1eiBz9AgClbXvF9GBOjgLW+LLsx6Va+439LLRwM3LX88/VjJ6niJR9fQQADrE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bxfUi5aa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bxfUi5aa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3A7AC4CED0; Thu, 14 Nov 2024 04:00:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556811; bh=3C3Xq0hxZ36iLjeQuzA/kkrrmPX01XR3AlW+rrMmhbQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bxfUi5aaDMkJzCyfz04WYk8gZZnF3iS9OQzksWoCf7nWcp/h4KkZxmIru8h4+6QsE NP5utygvfoik4FVYKDFEyQRUe2Lne1gMNYByMbUUXYTE5jiw46xSBjlbSXTDx2fV4k rFJrYftNarCfiwfWBR+CG3ulqHaR6UsmMG0JWMOS3355dV2buEjt5aMOTiVi4xjvYQ AxnmJAM6DORQWN5ePzwfZxZaVtherVAK7M9fCyl4L+XDWPqhTiZWssDFA3gd81fRot M6/5v/glNrOMAwnO9Md+E8giPnQHVZ5OkGonPIAX92dHA1RJ1Vsb39LuxsvMQEj2xt 4pPF3bZ15fnzQ== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 13/15] nfs/localio: remove redundant code and simplify LOCALIO enablement Date: Wed, 13 Nov 2024 22:59:50 -0500 Message-ID: <20241114035952.13889-14-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Remove nfs_local_enable and nfs_local_disable, instead use nfs_localio_enable_client and nfs_localio_disable_client. Discontinue use of the NFS_CS_LOCAL_IO bit in the nfs_client struct's cl_flags to reflect that LOCALIO is enabled; instead just test if the net member of the nfs_uuid_t struct is set. Also remove trace_nfs_local_enable and trace_nfs_local_disable, comparable traces are available from nfs_localio.ko. Suggested-by: NeilBrown Signed-off-by: Mike Snitzer --- fs/nfs/client.c | 2 +- fs/nfs/internal.h | 2 -- fs/nfs/localio.c | 28 +++++----------------------- fs/nfs/nfstrace.h | 32 -------------------------------- fs/nfs_common/nfslocalio.c | 34 +++++++++++----------------------- 5 files changed, 17 insertions(+), 81 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index e83e1ce046130..a657318fede46 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -243,7 +243,7 @@ static void pnfs_init_server(struct nfs_server *server) */ void nfs_free_client(struct nfs_client *clp) { - nfs_local_disable(clp); + nfs_localio_disable_client(clp); /* -EIO all pending I/O */ if (!IS_ERR(clp->cl_rpcclient)) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 57af3ab3adbe5..a252191b9335c 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -454,7 +454,6 @@ extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); #if IS_ENABLED(CONFIG_NFS_LOCALIO) /* localio.c */ -extern void nfs_local_disable(struct nfs_client *); extern void nfs_local_probe(struct nfs_client *); extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *, const struct cred *, @@ -471,7 +470,6 @@ extern int nfs_local_commit(struct nfsd_file *, extern bool nfs_server_is_local(const struct nfs_client *clp); #else /* CONFIG_NFS_LOCALIO */ -static inline void nfs_local_disable(struct nfs_client *clp) {} static inline void nfs_local_probe(struct nfs_client *clp) {} static inline struct nfsd_file * nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index 7e432057c3a1f..4b6bf4ea7d7fc 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -56,7 +56,7 @@ MODULE_PARM_DESC(localio_O_DIRECT_semantics, static inline bool nfs_client_is_local(const struct nfs_client *clp) { - return !!test_bit(NFS_CS_LOCAL_IO, &clp->cl_flags); + return !!rcu_access_pointer(clp->cl_uuid.net); } bool nfs_server_is_local(const struct nfs_client *clp) @@ -121,24 +121,6 @@ const struct rpc_program nfslocalio_program = { .stats = &nfslocalio_rpcstat, }; -/* - * nfs_local_enable - enable local i/o for an nfs_client - */ -static void nfs_local_enable(struct nfs_client *clp) -{ - trace_nfs_local_enable(clp); - nfs_localio_enable_client(clp); -} - -/* - * nfs_local_disable - disable local i/o for an nfs_client - */ -void nfs_local_disable(struct nfs_client *clp) -{ - trace_nfs_local_disable(clp); - nfs_localio_disable_client(clp); -} - /* * nfs_init_localioclient - Initialise an NFS localio client connection */ @@ -194,19 +176,19 @@ void nfs_local_probe(struct nfs_client *clp) /* Disallow localio if disabled via sysfs or AUTH_SYS isn't used */ if (!localio_enabled || clp->cl_rpcclient->cl_auth->au_flavor != RPC_AUTH_UNIX) { - nfs_local_disable(clp); + nfs_localio_disable_client(clp); return; } if (nfs_client_is_local(clp)) { /* If already enabled, disable and re-enable */ - nfs_local_disable(clp); + nfs_localio_disable_client(clp); } if (!nfs_uuid_begin(&clp->cl_uuid)) return; if (nfs_server_uuid_is_local(clp)) - nfs_local_enable(clp); + nfs_localio_enable_client(clp); nfs_uuid_end(&clp->cl_uuid); } EXPORT_SYMBOL_GPL(nfs_local_probe); @@ -748,7 +730,7 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio, if (status != 0) { if (status == -EAGAIN) - nfs_local_disable(clp); + nfs_localio_disable_client(clp); nfs_local_file_put(localio); hdr->task.tk_status = status; nfs_local_hdr_release(hdr, call_ops); diff --git a/fs/nfs/nfstrace.h b/fs/nfs/nfstrace.h index 1eab98c277fab..7a058bd8c566e 100644 --- a/fs/nfs/nfstrace.h +++ b/fs/nfs/nfstrace.h @@ -1714,38 +1714,6 @@ TRACE_EVENT(nfs_local_open_fh, ) ); -DECLARE_EVENT_CLASS(nfs_local_client_event, - TP_PROTO( - const struct nfs_client *clp - ), - - TP_ARGS(clp), - - TP_STRUCT__entry( - __field(unsigned int, protocol) - __string(server, clp->cl_hostname) - ), - - TP_fast_assign( - __entry->protocol = clp->rpc_ops->version; - __assign_str(server); - ), - - TP_printk( - "server=%s NFSv%u", __get_str(server), __entry->protocol - ) -); - -#define DEFINE_NFS_LOCAL_CLIENT_EVENT(name) \ - DEFINE_EVENT(nfs_local_client_event, name, \ - TP_PROTO( \ - const struct nfs_client *clp \ - ), \ - TP_ARGS(clp)) - -DEFINE_NFS_LOCAL_CLIENT_EVENT(nfs_local_enable); -DEFINE_NFS_LOCAL_CLIENT_EVENT(nfs_local_disable); - DECLARE_EVENT_CLASS(nfs_xdr_event, TP_PROTO( const struct xdr_stream *xdr, diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index 4e4991e059413..0a26c0ca99c21 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -37,7 +37,7 @@ static LIST_HEAD(nfs_uuids); void nfs_uuid_init(nfs_uuid_t *nfs_uuid) { - nfs_uuid->net = NULL; + RCU_INIT_POINTER(nfs_uuid->net, NULL); nfs_uuid->dom = NULL; nfs_uuid->list_lock = NULL; INIT_LIST_HEAD(&nfs_uuid->list); @@ -49,7 +49,7 @@ EXPORT_SYMBOL_GPL(nfs_uuid_init); bool nfs_uuid_begin(nfs_uuid_t *nfs_uuid) { spin_lock(&nfs_uuid->lock); - if (nfs_uuid->net) { + if (rcu_access_pointer(nfs_uuid->net)) { /* This nfs_uuid is already in use */ spin_unlock(&nfs_uuid->lock); return false; @@ -74,9 +74,9 @@ EXPORT_SYMBOL_GPL(nfs_uuid_begin); void nfs_uuid_end(nfs_uuid_t *nfs_uuid) { - if (nfs_uuid->net == NULL) { + if (!rcu_access_pointer(nfs_uuid->net)) { spin_lock(&nfs_uuid->lock); - if (nfs_uuid->net == NULL) { + if (!rcu_access_pointer(nfs_uuid->net)) { /* Not local, remove from nfs_uuids */ spin_lock(&nfs_uuids_lock); list_del_init(&nfs_uuid->list); @@ -139,12 +139,8 @@ EXPORT_SYMBOL_GPL(nfs_uuid_is_local); void nfs_localio_enable_client(struct nfs_client *clp) { - nfs_uuid_t *nfs_uuid = &clp->cl_uuid; - - spin_lock(&nfs_uuid->lock); - set_bit(NFS_CS_LOCAL_IO, &clp->cl_flags); + /* nfs_uuid_is_local() does the actual enablement */ trace_nfs_localio_enable_client(clp); - spin_unlock(&nfs_uuid->lock); } EXPORT_SYMBOL_GPL(nfs_localio_enable_client); @@ -152,15 +148,15 @@ EXPORT_SYMBOL_GPL(nfs_localio_enable_client); * Cleanup the nfs_uuid_t embedded in an nfs_client. * This is the long-form of nfs_uuid_init(). */ -static void nfs_uuid_put(nfs_uuid_t *nfs_uuid) +static bool nfs_uuid_put(nfs_uuid_t *nfs_uuid) { LIST_HEAD(local_files); struct nfs_file_localio *nfl, *tmp; spin_lock(&nfs_uuid->lock); - if (unlikely(!nfs_uuid->net)) { + if (unlikely(!rcu_access_pointer(nfs_uuid->net))) { spin_unlock(&nfs_uuid->lock); - return; + return false; } RCU_INIT_POINTER(nfs_uuid->net, NULL); @@ -192,22 +188,14 @@ static void nfs_uuid_put(nfs_uuid_t *nfs_uuid) module_put(nfsd_mod); spin_unlock(&nfs_uuid->lock); + + return true; } void nfs_localio_disable_client(struct nfs_client *clp) { - nfs_uuid_t *nfs_uuid = NULL; - - spin_lock(&clp->cl_uuid.lock); /* aka &nfs_uuid->lock */ - if (test_and_clear_bit(NFS_CS_LOCAL_IO, &clp->cl_flags)) { - /* &clp->cl_uuid is always not NULL, using as bool here */ - nfs_uuid = &clp->cl_uuid; + if (nfs_uuid_put(&clp->cl_uuid)) trace_nfs_localio_disable_client(clp); - } - spin_unlock(&clp->cl_uuid.lock); - - if (nfs_uuid) - nfs_uuid_put(nfs_uuid); } EXPORT_SYMBOL_GPL(nfs_localio_disable_client); From patchwork Thu Nov 14 03:59:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874530 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 63F6B1E9076 for ; Thu, 14 Nov 2024 04:00:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556812; cv=none; b=NCnr2lG2tD8TTt2SEoSW24XSyNw+m3V+LEkR0ctSbsZC3fEwjoyNmbl0LQe/EMSLyyCpj8hNlqFalWBcp+JEnG8esdtza8DlzVci6CvMLaa2e8+foMxskMoywfw+oFpHSBlGU25dJyzaAcGWNDnUs9cF8zDAZP67h0j+cjlBbO4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556812; c=relaxed/simple; bh=h4sYR9GOomMUsWtu+kr79Nc160k0fnqRMvT+m4WeMDY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K9xBxwp92hgKN4VX1MFfMDDz7pMJYs9rdbNWxYJmZgCfJhuROm2+1Uem1ImwPR5E3DX4LNXsyK6zT/zWR4NLXEKfvBzBxwWl1XjEqYj4b+2OmhfEtxDz5U8YlrMLU8lNC42UlEasQy6tphKKbHlVp3jkWLifQn1gaHEDL2OFydY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZqiV/jXe; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZqiV/jXe" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0F307C4CED0; Thu, 14 Nov 2024 04:00:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556812; bh=h4sYR9GOomMUsWtu+kr79Nc160k0fnqRMvT+m4WeMDY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZqiV/jXeKNHS6MWKrhItwDneWjgzFTOmcD8xupAqq/uYGUmQQAH/i9xd14/GSyvhJ cq661ai2SxQ98whPDeGy7Q5m1UiEYdwaortKUkCj7XeoJ+ORSBjDlGLJSA+Nt19WYe 39Z+XxP6756PfMi35IplXk01obkrTuz2nHDDqzRSAwu0Nv7X93BdwOI/TLzWwY4yd2 ei348xO7ulUz3Oh3/4/Nv0ZjMZSslegFoiLjTkDUf0dz3EUyuuyy1kAu8tKFg7G7zP dQkyi0Ss20MDiAwjKDDHxgyMVzOEnEj5WMuJKICZ3XrqOw8RYSKPxqMtziZSB+n9XW WZHiAyrL4nyuA== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 14/15] nfs: probe for LOCALIO when v4 client reconnects to server Date: Wed, 13 Nov 2024 22:59:51 -0500 Message-ID: <20241114035952.13889-15-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce nfs_local_probe_async() for the NFS client to initiate if/when it reconnects with server. For NFSv4 it is a simple matter to call nfs_local_probe_async() from nfs4_do_reclaim (during NFSv4 grace). Signed-off-by: Mike Snitzer --- fs/nfs/client.c | 1 + fs/nfs/internal.h | 3 +++ fs/nfs/localio.c | 14 ++++++++++++++ fs/nfs/nfs4state.c | 1 + include/linux/nfs_fs_sb.h | 1 + 5 files changed, 20 insertions(+) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a657318fede46..9765aad6e3dab 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -186,6 +186,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) seqlock_init(&clp->cl_boot_lock); ktime_get_real_ts64(&clp->cl_nfssvc_boot); nfs_uuid_init(&clp->cl_uuid); + INIT_WORK(&clp->cl_local_probe_work, nfs_local_probe_async_work); #endif /* CONFIG_NFS_LOCALIO */ clp->cl_principal = "*"; diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index a252191b9335c..ad9c56bc977bf 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -455,6 +455,8 @@ extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); #if IS_ENABLED(CONFIG_NFS_LOCALIO) /* localio.c */ extern void nfs_local_probe(struct nfs_client *); +extern void nfs_local_probe_async(struct nfs_client *); +extern void nfs_local_probe_async_work(struct work_struct *); extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *, const struct cred *, struct nfs_fh *, @@ -471,6 +473,7 @@ extern bool nfs_server_is_local(const struct nfs_client *clp); #else /* CONFIG_NFS_LOCALIO */ static inline void nfs_local_probe(struct nfs_client *clp) {} +static inline void nfs_local_probe_async(struct nfs_client *clp) {} static inline struct nfsd_file * nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, struct nfs_fh *fh, struct nfs_file_localio *nfl, diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index 4b6bf4ea7d7fc..1eee5aac28843 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -193,6 +193,20 @@ void nfs_local_probe(struct nfs_client *clp) } EXPORT_SYMBOL_GPL(nfs_local_probe); +void nfs_local_probe_async_work(struct work_struct *work) +{ + struct nfs_client *clp = + container_of(work, struct nfs_client, cl_local_probe_work); + + nfs_local_probe(clp); +} + +void nfs_local_probe_async(struct nfs_client *clp) +{ + queue_work(nfsiod_workqueue, &clp->cl_local_probe_work); +} +EXPORT_SYMBOL_GPL(nfs_local_probe_async); + static inline struct nfsd_file *nfs_local_file_get(struct nfsd_file *nf) { return nfs_to->nfsd_file_get(nf); diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 9a9f60a2291b4..542cdf71229fe 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1955,6 +1955,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov } rcu_read_unlock(); nfs4_free_state_owners(&freeme); + nfs_local_probe_async(clp); if (lost_locks) pr_warn("NFS: %s: lost %d locks\n", clp->cl_hostname, lost_locks); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 239d86ef166c0..63d7e0f478d89 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -132,6 +132,7 @@ struct nfs_client { struct timespec64 cl_nfssvc_boot; seqlock_t cl_boot_lock; nfs_uuid_t cl_uuid; + struct work_struct cl_local_probe_work; #endif /* CONFIG_NFS_LOCALIO */ }; From patchwork Thu Nov 14 03:59:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 13874531 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 011A81E9076 for ; Thu, 14 Nov 2024 04:00:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556814; cv=none; b=nifbB5J19YZGVwiQjQImE59ZfVFe//Kikc9ZCPhGLr1BTQKSbvHIniQICms9qD5uO6ISNcXV0jCbQJatEP0Y+bSjDSeGxxh7gDnyBgerLcHyNI3V8C5Jyk5wdlUEydL6VBcY9wGbJ5MqOQ0PthCaD8kmnEu+lB5x3nNN3nrfKkw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731556814; c=relaxed/simple; bh=KyC2LAmrc9W9cAAgfHsl2reBdD/tZ2y7y0h1wnrUNRo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uc1JR+IJCut3IpMOLYhZGXvSJ3cqGcqR+UpOvU2BKnt1JCJMXiQ7l75f9KVgqA4wqJAPyu7ZSWqgEzusUVFPPAnVpjrxS7qUvzzKNRtz3UH5u3ZlKA6c5cERV+uTxwWfBm/M+mXR/Qh5aYLAALa5/YO6K0W+Q2YK413U20hjRNg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qHFH52/T; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qHFH52/T" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 59C4FC4CED0; Thu, 14 Nov 2024 04:00:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731556813; bh=KyC2LAmrc9W9cAAgfHsl2reBdD/tZ2y7y0h1wnrUNRo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qHFH52/TIkU4tap9Qb9e3b5Kkc3dmunZ01B2rk15obQaIMtbYB+sLinUGr89fSbBf hTebJryJlWLnK1LfJyB+rROGu617uqQOLGWFHuZWIcgEr4GMQSDX2nH1dn154oCTJR GwVqcJR5UkTLVTRTiQtaN+JGFvl80h7f0VFi03p2Rk+qSGcHAexx/Adl9sDPe1gmv6 w6HPkW5hvyb8pt2h7q7XT3DlmGs5GoCUU7wul5ryL6SpKZJSy1IjHxE8xUsIxCdh2f H2xEla5YG5t9ZGZqEKJrnkeoLl5jfQcG4SjWA19qI230bmuhCyrdNCcQbKNrOikZO2 S4N7GUiuH5R1g== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Anna Schumaker , Trond Myklebust , Chuck Lever , Jeff Layton , NeilBrown Subject: [for-6.13 PATCH v2 15/15] nfs: probe for LOCALIO when v3 client reconnects to server Date: Wed, 13 Nov 2024 22:59:52 -0500 Message-ID: <20241114035952.13889-16-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20241114035952.13889-1-snitzer@kernel.org> References: <20241114035952.13889-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Re-enabling NFSv3 LOCALIO is made more complex (than NFSv4) because v3 is stateless. As such, the hueristic used to identify a LOCALIO probe point is more adhoc by nature: if/when NFSv3 client IO begins to complete again in terms of normal RPC-based NFSv3 server IO, attempt nfs_local_probe_async(). Care is taken to throttle the frequency of nfs_local_probe_async(), otherwise there could be a flood of repeat calls to nfs_local_probe_async(). This approach works for most use-cases but it doesn't handle the possibility of using HA to migrate an NFS server local to the same host as an NFS client that is actively connected to the migrated NFS server. NFSv3 LOCALIO won't handle this case given it relies on the client having been flagged with NFS_CS_LOCAL_IO when the client was created on the host (e.g. mount time). Alternatve approaches have been discussed but there isn't clear consensus yet. Signed-off-by: Mike Snitzer --- fs/nfs/internal.h | 5 +++++ fs/nfs/localio.c | 18 +++++++++++++++++- fs/nfs/nfs3proc.c | 32 +++++++++++++++++++++++++++++--- fs/nfs_common/nfslocalio.c | 1 + include/linux/nfslocalio.h | 3 ++- 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index ad9c56bc977bf..14f4d871b6a30 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -470,6 +470,7 @@ extern int nfs_local_commit(struct nfsd_file *, struct nfs_commit_data *, const struct rpc_call_ops *, int); extern bool nfs_server_is_local(const struct nfs_client *clp); +extern bool nfs_server_was_local(const struct nfs_client *clp); #else /* CONFIG_NFS_LOCALIO */ static inline void nfs_local_probe(struct nfs_client *clp) {} @@ -498,6 +499,10 @@ static inline bool nfs_server_is_local(const struct nfs_client *clp) { return false; } +static inline bool nfs_server_was_local(const struct nfs_client *clp) +{ + return false; +} #endif /* CONFIG_NFS_LOCALIO */ /* super.c */ diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index 1eee5aac28843..d5152aa46813c 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -65,6 +65,17 @@ bool nfs_server_is_local(const struct nfs_client *clp) } EXPORT_SYMBOL_GPL(nfs_server_is_local); +static inline bool nfs_client_was_local(const struct nfs_client *clp) +{ + return !!test_bit(NFS_CS_LOCAL_IO, &clp->cl_flags); +} + +bool nfs_server_was_local(const struct nfs_client *clp) +{ + return nfs_client_was_local(clp) && localio_enabled; +} +EXPORT_SYMBOL_GPL(nfs_server_was_local); + /* * UUID_IS_LOCAL XDR functions */ @@ -187,8 +198,13 @@ void nfs_local_probe(struct nfs_client *clp) if (!nfs_uuid_begin(&clp->cl_uuid)) return; - if (nfs_server_uuid_is_local(clp)) + if (nfs_server_uuid_is_local(clp)) { nfs_localio_enable_client(clp); + /* Set hint that client and server are LOCALIO capable */ + spin_lock(&clp->cl_uuid.lock); + set_bit(NFS_CS_LOCAL_IO, &clp->cl_flags); + spin_unlock(&clp->cl_uuid.lock); + } nfs_uuid_end(&clp->cl_uuid); } EXPORT_SYMBOL_GPL(nfs_local_probe); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 1566163c6d85b..6ed2e4466002d 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -844,6 +844,27 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, return status; } +static void nfs3_local_probe(struct nfs_server *server) +{ +#if IS_ENABLED(CONFIG_NFS_LOCALIO) + struct nfs_client *clp = server->nfs_client; + nfs_uuid_t *nfs_uuid = &clp->cl_uuid; + + if (likely(!nfs_server_was_local(clp))) + return; + /* + * Try re-enabling LOCALIO if it was previously enabled, but + * was disabled due to server restart, and IO has successfully + * completed in terms of normal RPC. + */ + /* Arbitrary throttle to reduce nfs_local_probe_async() frequency */ + if ((nfs_uuid->local_probe_count++ & 511) == 0) { + if (unlikely(!nfs_server_is_local(clp) && nfs_server_was_local(clp))) + nfs_local_probe_async(clp); + } +#endif +} + static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr) { struct inode *inode = hdr->inode; @@ -855,8 +876,11 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr) if (nfs3_async_handle_jukebox(task, inode)) return -EAGAIN; - if (task->tk_status >= 0 && !server->read_hdrsize) - cmpxchg(&server->read_hdrsize, 0, hdr->res.replen); + if (task->tk_status >= 0) { + if (!server->read_hdrsize) + cmpxchg(&server->read_hdrsize, 0, hdr->res.replen); + nfs3_local_probe(server); + } nfs_invalidate_atime(inode); nfs_refresh_inode(inode, &hdr->fattr); @@ -886,8 +910,10 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) if (nfs3_async_handle_jukebox(task, inode)) return -EAGAIN; - if (task->tk_status >= 0) + if (task->tk_status >= 0) { nfs_writeback_update_inode(hdr); + nfs3_local_probe(NFS_SERVER(inode)); + } return 0; } diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index 0a26c0ca99c21..41c0077ead721 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -43,6 +43,7 @@ void nfs_uuid_init(nfs_uuid_t *nfs_uuid) INIT_LIST_HEAD(&nfs_uuid->list); INIT_LIST_HEAD(&nfs_uuid->files); spin_lock_init(&nfs_uuid->lock); + nfs_uuid->local_probe_count = 0; } EXPORT_SYMBOL_GPL(nfs_uuid_init); diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h index c68a529230c14..e05f1cf3cf476 100644 --- a/include/linux/nfslocalio.h +++ b/include/linux/nfslocalio.h @@ -27,7 +27,8 @@ struct nfs_file_localio; */ typedef struct { uuid_t uuid; - /* sadly this struct is just over a cacheline, avoid bouncing */ + unsigned local_probe_count; + /* sadly this struct is over a cacheline, avoid bouncing */ spinlock_t ____cacheline_aligned lock; struct list_head list; spinlock_t *list_lock; /* nn->local_clients_lock */