From nobody Fri Apr 3 01:22:51 2026 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 40E2C3EDAC6; Wed, 25 Mar 2026 14:40:52 +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=1774449652; cv=none; b=inczpcFfmeQqjk9wdN8A6jWsdC238gOuenjaq9DVuuIcuNDYP3GHnaaEDIJHHDlqq/dznm80h2w8nY6YQWx5YmL/5Frlv3XUVqGN0N/AOZjzwYTZ0DUakqZYkrjJmuD+yKrQTqx52AFVb3JVomkytYAFLb0Dq+dHcaygypqjeC0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449652; c=relaxed/simple; bh=N3IH110vSVveR9UotqARZCtiLBniRTymPztXiHOEEzM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WG2sn6dPGMXwXNt22CDD+dCYNNhJ+V4i4fbKKB3bPRO13KsJ4+5CjxWf4ImQS5v7Y9tEcokZZWwtMmasx3M/yZuNZ/z+NqvE8mEs4jfd5edOkIb9u2Yj/cCh8Go+Y42YOFQTIhjlR4rDb4hcC5x4w+wEHQZ+kH9yxFeSMK4u0DY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SuhgRz0v; 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="SuhgRz0v" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6BF0DC19423; Wed, 25 Mar 2026 14:40:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449651; bh=N3IH110vSVveR9UotqARZCtiLBniRTymPztXiHOEEzM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=SuhgRz0v4a+x7EWfdd2nGM99Pa7/IV7l5R1QTOSjrfUCQYK2JIiOmwtOC6EqqbX5g bh9KGCLecNi+etcTGaPGHZ5YRF3oZOEjOOjFC7r+yjZ3W95JimerTYT/HZNxwQbQwg 2OLS2qn3WrbVpB5BosWDU70LqheRoZCjRoPo37ygXeOO9r60ijqWOwKlbZVWVlZkvG /+gEy+CSHir5IDnk10xetRe4+3lmZKD8eTncV3QTWvZeT/fnjgO/DI/u9ZUaiOYs3o +CA4ur6gntznA0zHfyeD1CJFnUn/vkU4k+xMIYNEGnX5JFOZt/vNdpblKVqJa3eCEt G6Uc+G0pMaAKQ== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:22 -0400 Subject: [PATCH v2 01/13] nfsd: move struct nfsd_genl_rqstp to nfsctl.c Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-1-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1758; i=jlayton@kernel.org; h=from:subject:message-id; bh=N3IH110vSVveR9UotqARZCtiLBniRTymPztXiHOEEzM=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/Ptu9eJSTtSX7n2IzojIfKA0pDkCjJSBtIkf 9V30MsF5O6JAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7QAKCRAADmhBGVaC FdGPD/9LORuXiQdrzd+y0H8tj7gZXc4vKon3Vj5pYYoXysYH5CT9oEBp/tzEvBX9rxmPZVb6Xea D6DZb49KurODmJ1vWg9lI8n5WXo5jOgsdKyPzSlER5/GTOoskmf6DWh5ikCwHoCwKg5XtdwdhnY Q88e4AnYOAYOwA2z8iqTq1Hdusa+58lW1mfe8F2og8NH8oZlz2X6w02Rph0Lynz/Moi4X/hdPi7 BgJa/JqdQH1nVHlBqCBX4xz+zXerBprV6NXgpvph/sDbLJzZl1eeE3l+G8dNq4U6e2WmHrRQ+S5 L2+twvSaczsh5vVZGCfh5/WmYC8NVIPWoO+yLf4eRreAijVi2FW/RtqiJlDCMSdy1YAXf4uRx+F WNxbbMryQYFYLovnGDW4sjOESPXyjFcLtv3qpsgw9Pa0UCWNUjg7NUbxHE5ULRs374yGEHDr48H k/Ra6m7+o/ax6s9w7mC/M5NFDTWszTVdK8SfGwmTL3Pon5XzdWBNpo1teEQgT8KrdVsxIjLuQQe O2Hbuhly8QkQTuNiQkRFhNIW+yBNyP0VC/qSpYNKJQcUL9freiZZBRTQvgkC5UuaBvvC5h38/5p oOWBCAN8K/WdfHCJAFa6OTlpitUcLsobWc6ctLCMvfDeWyi0DuGOzg4TQEEdkPOTy3/nUzWF7h5 b98L3j8i7KrSE/w== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 It's not used outside of that file. Signed-off-by: Jeff Layton --- fs/nfsd/nfsctl.c | 15 +++++++++++++++ fs/nfsd/nfsd.h | 15 --------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 988a79ec4a79af2f9c9406be9740d1922c2b4ec8..dc294c4f8c58a6692b9dfbeb98f= edbd649ae1b95 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1412,6 +1412,21 @@ static int create_proc_exports_entry(void) =20 unsigned int nfsd_net_id; =20 +struct nfsd_genl_rqstp { + struct sockaddr rq_daddr; + struct sockaddr rq_saddr; + unsigned long rq_flags; + ktime_t rq_stime; + __be32 rq_xid; + u32 rq_vers; + u32 rq_prog; + u32 rq_proc; + + /* NFSv4 compound */ + u32 rq_opcnt; + u32 rq_opnum[16]; +}; + static int nfsd_genl_rpc_status_compose_msg(struct sk_buff *skb, struct netlink_callback *cb, struct nfsd_genl_rqstp *genl_rqstp) diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 7c009f07c90b50d7074695d4665a2eca85140eda..260bf8badb032de18f973556fa5= deabe7e67870d 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -60,21 +60,6 @@ struct readdir_cd { /* Maximum number of operations per session compound */ #define NFSD_MAX_OPS_PER_COMPOUND 200 =20 -struct nfsd_genl_rqstp { - struct sockaddr rq_daddr; - struct sockaddr rq_saddr; - unsigned long rq_flags; - ktime_t rq_stime; - __be32 rq_xid; - u32 rq_vers; - u32 rq_prog; - u32 rq_proc; - - /* NFSv4 compound */ - u32 rq_opcnt; - u32 rq_opnum[16]; -}; - extern struct svc_program nfsd_programs[]; extern const struct svc_version nfsd_version2, nfsd_version3, nfsd_version= 4; extern struct mutex nfsd_mutex; --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 E2C1F3E639C; Wed, 25 Mar 2026 14:40:53 +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=1774449654; cv=none; b=XZO4sgByHysJjkaThgta6SL7DWsSg/zKer4C0770q5WFYSgqlPyEFK7m/71MpYweohKgGq1m2a0wH9fsAAxpvf/iMK2Qe79pLN5+Up75nyY95hkhTLhSfiucwnPd+D61HI2silvsUjhNhAEM4DSuaU99g9iuMiLRJINjuy3R/pk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449654; c=relaxed/simple; bh=W0WCKgToW3dYYaxKd6T2t+Xr1kwru6qNqfGRBso4ZN8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TGXXZfytzfcHUTGH5W+Dt9tUslMjP0JLBYITX66Vw8YdvwnsE4fhyDeK5M7+ZBXX1IU9Dh9C66MHfmnkR0mVhkjbW5kWu+lKAP+Um/gsi5nTJ8RHAfM+yZXMuxJcHr1F0OTbEt2/3lDY87O9BGABKVZMKt2Kq7z+O2imMpYVJgA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LK6/Z+3E; 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="LK6/Z+3E" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 31236C4CEF7; Wed, 25 Mar 2026 14:40:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449653; bh=W0WCKgToW3dYYaxKd6T2t+Xr1kwru6qNqfGRBso4ZN8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LK6/Z+3Ew2vMzcH9Y3O8/lZZsYXW7Rh/2pzokcbhGGztIwDPFMgaqYwGBwdJS/WCH RWEQ/QPD+5wtuYs1TvrqNQ99UVJacHy/BRMKms5y2BdguIO14MnJTiD6Oq4wAbPGMK 1qT1Vy/sBPGE2YRuIDjdhFogWQbFwpgplRo+PlbU0BkJGyJ1iCWvAxYrt7Zw+Cl4Gk pk/c8J7hzPSQf7H+3vGFDh6kP4ZVWEpm5KOH6lhs08Spd/kaB66C9wBAxYrXegYlIl TtKYGXmEWjjVWnnHYrFZRvSAp3RIk27nCXrTlhNBG738L6LZfsBR3KJIi81xZgoa+u qAwsgGLqQ5hdQ== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:23 -0400 Subject: [PATCH v2 02/13] sunrpc: rename sunrpc_cache_pipe_upcall() to sunrpc_cache_upcall() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-2-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3407; i=jlayton@kernel.org; h=from:subject:message-id; bh=W0WCKgToW3dYYaxKd6T2t+Xr1kwru6qNqfGRBso4ZN8=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/Pt/NdiuKiRT8ZjEaqA96P6UIgCysMsOAMHM n5klb0qYcCJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7QAKCRAADmhBGVaC FUicD/9jLPzBHdNptiukdzhjpva4kktYxBVk+kzu8iPD6tVQV94SSZSRSg0DCX6pZqs+oouzZrq 3nmFQjcug+lC5/uNKazus+/1Dp0rKa3siD1mGZAt61fTv+CIJ0GivUjKHfGiLP3roF+y5Sv5OXi 60fdKEew1fwtsYqDVqiEpMghQacwbI8HlCLo6xmDqI4BmEwTqCscu2PsoJPMQWcpOUZY6VFDmYq wWIAC1hcWI++gUKDJMGe26d9YzN8dZpTwlCL7AZGiKYSi1C5swRvVWm831CErxidk6Z6xnHsXWM tv7iU/ZTjXXX3U81JoamYbuR7sKKNlUJefA1TsEe+TD2DEZmD66N9LrkeBEA32Fe+zv99/5nJC1 dXU8xRpxzIQj6Yfoh+IkRXh96FfY0kwLUhecqWE/eArJX67fXJ3yfgq6T4RsP+ULtQpud5w4Oo6 nP4u6H2u6Zwz/zVDhu31nRrGq34zoXjyUnigVeicFwgfhoCFomai9ZWFwu47OtzjwtUQHVxfJU5 kF+91rYTAVmp5dIr8MySGDUq90fdgY8hnjDlDE1thV5u+SxlqAig6VTX+Y2SspLQAfLXsRSR83K FYP2QxqFBi4Q86IWlIDjFV5yFLYSgkL/y0vYeV27HqYYsZ80EhGOpp/deEePFCGEZfF/jM466fH md9WDqDlhWT+MWw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Since it will soon also send an upcall via netlink, if configured. Signed-off-by: Jeff Layton --- fs/nfsd/export.c | 4 ++-- include/linux/sunrpc/cache.h | 2 +- net/sunrpc/cache.c | 6 +++--- net/sunrpc/svcauth_unix.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 7f4a51b832ef75f6ecf1b70e7ab4ca9da2e5a1dc..e83e88e69d90ab48c7aff58ac2b= 36cd1a6e1bb71 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -64,7 +64,7 @@ static void expkey_put(struct kref *ref) =20 static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) { - return sunrpc_cache_pipe_upcall(cd, h); + return sunrpc_cache_upcall(cd, h); } =20 static void expkey_request(struct cache_detail *cd, @@ -388,7 +388,7 @@ static void svc_export_put(struct kref *ref) =20 static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) { - return sunrpc_cache_pipe_upcall(cd, h); + return sunrpc_cache_upcall(cd, h); } =20 static void svc_export_request(struct cache_detail *cd, diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index b1e595c2615bd4be4d9ad19f71a8f4d08bd74a9b..981af830a0033f80090c5f6140e= 22e02f21ceccc 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -189,7 +189,7 @@ sunrpc_cache_update(struct cache_detail *detail, struct cache_head *new, struct cache_head *old, int hash); =20 extern int -sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h= ); +sunrpc_cache_upcall(struct cache_detail *detail, struct cache_head *h); extern int sunrpc_cache_pipe_upcall_timeout(struct cache_detail *detail, struct cache_head *h); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 7081c1214e6c3226f8ac82c8bc7ff6c36f598744..4729412ecd72241cb050dbed0ee= 2863629a8bef4 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1241,13 +1241,13 @@ static int cache_pipe_upcall(struct cache_detail *d= etail, struct cache_head *h) return ret; } =20 -int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_hea= d *h) +int sunrpc_cache_upcall(struct cache_detail *detail, struct cache_head *h) { if (test_and_set_bit(CACHE_PENDING, &h->flags)) return 0; return cache_pipe_upcall(detail, h); } -EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall); +EXPORT_SYMBOL_GPL(sunrpc_cache_upcall); =20 int sunrpc_cache_pipe_upcall_timeout(struct cache_detail *detail, struct cache_head *h) @@ -1257,7 +1257,7 @@ int sunrpc_cache_pipe_upcall_timeout(struct cache_det= ail *detail, trace_cache_entry_no_listener(detail, h); return -EINVAL; } - return sunrpc_cache_pipe_upcall(detail, h); + return sunrpc_cache_upcall(detail, h); } EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall_timeout); =20 diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 3be69c145d2a8055acd39ff5e0faacb1084936b7..9d5e07b900e11a8f6da767557eb= 6a46a65a57c26 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -152,7 +152,7 @@ static struct cache_head *ip_map_alloc(void) =20 static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h) { - return sunrpc_cache_pipe_upcall(cd, h); + return sunrpc_cache_upcall(cd, h); } =20 static void ip_map_request(struct cache_detail *cd, --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 DB9473EFD25; Wed, 25 Mar 2026 14:40: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=1774449655; cv=none; b=KCu2+dUSnm5sjrYfHHhy0nezd/rwXKF6+wVt+9DYjjwOmzPGDnBfWjf2EWyNAzTo0K5yzFDbJ7A0k1rs8U6dnaLtNh+ngbKx6lECuDoYpuggbulzBeG1ICr7MItbcPiBAg0ZY1C8Jy4kDpNb6+b3tk3aXwYEASe0b1S8pT4PKeQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449655; c=relaxed/simple; bh=7BXop0Fp9UyPm/+D9R6GkrQSaUlGooUSVMVmxCMPli4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kfI7t9qcDriIgMZeU1S6FvZjyJoeYn8nGKtsRYlgcPnh+CdNVjW+mtiBfElaS2HcC+XfC1ELw6nUT92n9lrP7CBsounuhLUc5krqUs75UQhN1u7kzIfLBGOF5Mx3touKcNLIb0zk7qw8Pg844xORWLcf1ltbxFyK5j8powegifg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AmmckKiX; 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="AmmckKiX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EA542C116C6; Wed, 25 Mar 2026 14:40:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449655; bh=7BXop0Fp9UyPm/+D9R6GkrQSaUlGooUSVMVmxCMPli4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=AmmckKiX6xiCFXxwHVYKE+UqSit1gsPLrE/hObogoZHof27XgchuaZCDYc+CmoYW3 2S2LW8pi6Qcz9E0MDOvbUyuXaT8eFEOpjcUCyfRn1mvD/8fvfH1POv89QIW4w4ASdi w1W03hftfBaF5xmhQrC42u/EFJo2ag0rEFS6pDRWfGx8jYESn7F7LGdU9JpgMgAhkG 6LHymTKN1WKmZZ4nVq80ZY4MqQ0x4AYxjZgFn1khJ8hXEa+u/60XSe/u8b3n/Tt+Nc rmLKX5Uz20pY3CQ1fw1p9q91CGj+k8Y/ZexjMbj9SzyCzsHNGyZY6gVJeL83dbmJhQ y5h3xhCabM4QQ== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:24 -0400 Subject: [PATCH v2 03/13] sunrpc: rename sunrpc_cache_pipe_upcall_timeout() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-3-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=4376; i=jlayton@kernel.org; h=from:subject:message-id; bh=7BXop0Fp9UyPm/+D9R6GkrQSaUlGooUSVMVmxCMPli4=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/Pt+jgSD4Kh3oSApgx1OTUEuzDfU/XcBJgvM lvC+vIbYheJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7QAKCRAADmhBGVaC FTLCEAC/pcWyPX2M5PmGYPtuuF1sHNuRJiH6W/fb8lVaciRQRh34hsjoBwYgdhNXc1jADhLYfq0 c8sWarYyJ1vpS5gIhblbCC4LF5XL5buI+O9uGZKCgl4cuEocvtkf7bRWsjFQofX1sZBrtVfw6mC FYxyUhuL11pWR2qj0dGHW3eX5KCCf/ovpHr7rsI5boVZc+cwynaYhFudAw3PMlZT1p1mZHOxJgY Kd/k6mus5mpT2y0cmKeKoeTZVUUWIJyfF3rK673ZX7kU26cDRyGwLXQlNHNZC9tTHc0hXEj/6rn tyZOJDkf0pvE41WSdj1VzwWGPtnIDsXgTY7qEQligcTNmSoS6zc3KGOw/GKY3CX+ECWNtlvGv3O HwK6mJEJ8o5KnwMzyn9W3Cwhovuh+0/mGTpYiN02jHaCZ1qAU1QxPUwfVNVJaljJLQI4jTIEWWh O1BhhXL3d8nYxdne62p273vLdI+3SBEEq6OsQ8GbpecBKEvR7ZM999soOkpQ8RZe1jdQFBj2Dkt nXyhfghV9P8JpIpMTQ5ISVfg1wdukKjjihrpWz2OEsmGJkQqS9x8MO320xAxHCML+4dXO2E3NSa pcJ5CtR/DCbmpUfe9xywvrCQ548ccRgndCJumrTf4Ms+wKiiEOfHQVnPKPLKGWh8pAj58xEMxqu I/TspdLNZ44pGsg== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 This function doesn't have anything to do with a timeout. The only difference is that it warns if there are no listeners. Rename it to sunrpc_cache_upcall_warn(). Signed-off-by: Jeff Layton --- fs/nfs/dns_resolve.c | 2 +- fs/nfsd/nfs4idmap.c | 4 ++-- include/linux/sunrpc/cache.h | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/cache.c | 6 +++--- net/sunrpc/svcauth_unix.c | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index 2ed2126201f4185fa9d6341f661e23be08d422ea..acd3511c04a6c74301c393e05e3= 9aa8fcd52b390 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -156,7 +156,7 @@ static int nfs_dns_upcall(struct cache_detail *cd, if (!nfs_cache_upcall(cd, key->hostname)) return 0; clear_bit(CACHE_PENDING, &ch->flags); - return sunrpc_cache_pipe_upcall_timeout(cd, ch); + return sunrpc_cache_upcall_warn(cd, ch); } =20 static int nfs_dns_match(struct cache_head *ca, diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index ba06d3d3e6dd9eeb368be42b5d1d83c05049a70c..71ba61b5d0a3aacfc196e8d3aa3= c06b00fe0765b 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -126,7 +126,7 @@ idtoname_hash(struct ent *ent) static int idtoname_upcall(struct cache_detail *cd, struct cache_head *h) { - return sunrpc_cache_pipe_upcall_timeout(cd, h); + return sunrpc_cache_upcall_warn(cd, h); } =20 static void @@ -306,7 +306,7 @@ nametoid_hash(struct ent *ent) static int nametoid_upcall(struct cache_detail *cd, struct cache_head *h) { - return sunrpc_cache_pipe_upcall_timeout(cd, h); + return sunrpc_cache_upcall_warn(cd, h); } =20 static void diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 981af830a0033f80090c5f6140e22e02f21ceccc..80a3f17731d8fbc1c5252a830b2= 02016faa41a18 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -191,7 +191,7 @@ sunrpc_cache_update(struct cache_detail *detail, extern int sunrpc_cache_upcall(struct cache_detail *detail, struct cache_head *h); extern int -sunrpc_cache_pipe_upcall_timeout(struct cache_detail *detail, +sunrpc_cache_upcall_warn(struct cache_detail *detail, struct cache_head *h); =20 =20 diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcaut= h_gss.c index 161d02cc1c2c97321f311815c0324fade1e703fe..d14209031e1807e4ec19de44a28= 29d48e81e4d6c 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -206,7 +206,7 @@ static struct cache_head *rsi_alloc(void) =20 static int rsi_upcall(struct cache_detail *cd, struct cache_head *h) { - return sunrpc_cache_pipe_upcall_timeout(cd, h); + return sunrpc_cache_upcall_warn(cd, h); } =20 static void rsi_request(struct cache_detail *cd, diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 4729412ecd72241cb050dbed0ee2863629a8bef4..1b97102790f6642fa649ad6aab9= 4fcba8158fa8e 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1249,8 +1249,8 @@ int sunrpc_cache_upcall(struct cache_detail *detail, = struct cache_head *h) } EXPORT_SYMBOL_GPL(sunrpc_cache_upcall); =20 -int sunrpc_cache_pipe_upcall_timeout(struct cache_detail *detail, - struct cache_head *h) +int sunrpc_cache_upcall_warn(struct cache_detail *detail, + struct cache_head *h) { if (!cache_listeners_exist(detail)) { warn_no_listener(detail); @@ -1259,7 +1259,7 @@ int sunrpc_cache_pipe_upcall_timeout(struct cache_det= ail *detail, } return sunrpc_cache_upcall(detail, h); } -EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall_timeout); +EXPORT_SYMBOL_GPL(sunrpc_cache_upcall_warn); =20 /* * parse a message from user-space and pass it diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 9d5e07b900e11a8f6da767557eb6a46a65a57c26..87732c4cb8383c64b440538a0d3= f3113a3009b4e 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -467,7 +467,7 @@ static struct cache_head *unix_gid_alloc(void) =20 static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h) { - return sunrpc_cache_pipe_upcall_timeout(cd, h); + return sunrpc_cache_upcall_warn(cd, h); } =20 static void unix_gid_request(struct cache_detail *cd, --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 B87953EE1E8; Wed, 25 Mar 2026 14:40: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=1774449657; cv=none; b=hhb8o8D6kky64VNLGPiGMWiGjpDLw+XCEYJudgCqwhySFef71h8RyLtshSjVnrZHY1gJ2JzLxYZMgTHS0voExGHoScI6jzRW8napcvkXRjSMRcuhPUTnhNgwj8nE0OASV2ktVYr6vdpbQnLwo25situEhFFVa7B8leNizhXoDGo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449657; c=relaxed/simple; bh=z1a50sShHbXLrt+MAFH1HTdDE4R/esAqUantftctegA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=W94Z1yDidCL87ZnVD+r10Sk3xIAFTX5XkuZ3V6vRXbfSmYas8sWMgWbdJZgpE1wZZ5ptlkWqJMB1Aj/OhBhR77AZOceQ9Pgim21owBWlFAV1WmdXpGoWJm/SBSvHEXXW/GzL7IdnLOSlwj9o0Y9gGoGy/ZC7W9mQh5tD/vVVEOQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IJ4rHGIK; 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="IJ4rHGIK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B077FC2BCB3; Wed, 25 Mar 2026 14:40:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449657; bh=z1a50sShHbXLrt+MAFH1HTdDE4R/esAqUantftctegA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IJ4rHGIK7luNIfUIam2SXp/QusjJDas8FuEwzNNI6qjAzD9xIQE8r17mUJeJL+sJy U8KpmltR3TiSBtIPYq2Z3u3QBhq2CofALLxvzPMmTZ8QEeigqJVFzEYRyRNIN2Fqct z+DnaEEY94t+Suw1OYWAUX9FyCQ7lGB0fB2A//d7qo7wzo0tBBIULCG926zVoBJaCX 2HO5v1Jle/vN2zRAmjeFcyjnVT4BBtq2f/M5bpI4TMkF2Bd9gkKwljzuIAkrbHvaML cFVaauHn8JQvUU3ACbx9CD8lYIfXrDbZF0XXOe9zPrplxZDmIahLtGKTmktCCXluIw 2OZ3JX4lCSzbw== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:25 -0400 Subject: [PATCH v2 04/13] sunrpc: rename cache_pipe_upcall() to cache_do_upcall() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-4-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1341; i=jlayton@kernel.org; h=from:subject:message-id; bh=z1a50sShHbXLrt+MAFH1HTdDE4R/esAqUantftctegA=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/Pu5Bmosu3oHpACj8X6c/3sAR5ou/9/BofGi TVlWGjGXHuJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7gAKCRAADmhBGVaC Fa2ND/0cd0zYxSIw/WofuLVh5mteBJGnl7fZsxcsW/1ifWmWnqZcOVCffpn7gy+QaXejzd+cSuM v9hV/nujKyI33H5h9eMiKj8SMK041dF+b/WdEN977TYoUwMM1aAAUwY/j8tZ7cG/3CLQQIHX5BO K/Fmp1OXH01rC3lUb/eXpuFwiXPbT0IuQtglzwK1EkAhH3mtALqzDOVGehP6+uAB+sHOWYQqOl6 xQWrTVH4tOarlhgtvPTTeQ8I0doCe6P7RAiuXNZLem9iaGXrrlUxPdH6FTWLoYKdI0o6+tAfj1c qC1QtFQPcHGTcF1HznCbZe7kdlHTRgHKARzilFn0USMvKs4JzFVHvJF3RRBokyv6riA7u2LZjQB wlLVoH18Ih1oO9npQUrC4m2vraQKEnOrw7qgL9uFoyjblOVAnyO5Tz6Uq8or77FQycBt94fizKh eS2O6MlxyBtOmiRKmcxcWPRZeD8sKMKeNBhK7J6Dci+NOheDGsOhWsVSJFcCpUHreV1FTb0xUvp 3HjhfuciEKBsNWSy1YDvk+gYtX2gpnv8jtCqA49DWf6KcAG/eM1DGesH/KpsXUONimVwgQXHiHy DIQkc1Hz441fszwsaIVWs11J5kKSKIMWeJS+kwG9Zd7ZFl2emH0pm3FYy5atGRIArG7P7uBnxVt ZhEZZArOyP5+d0g== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Rename cache_pipe_upcall() to cache_do_upcall() in anticipation of the addition of a netlink-based upcall mechanism. Signed-off-by: Jeff Layton --- net/sunrpc/cache.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 1b97102790f6642fa649ad6aab94fcba8158fa8e..8a66128a1bfabca42b52f274ea3= 4c1b594a5920b 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1195,12 +1195,12 @@ static bool cache_listeners_exist(struct cache_deta= il *detail) } =20 /* - * register an upcall request to user-space and queue it up for read() by = the - * upcall daemon. + * register an upcall request to user-space and queue it up to be fetched = by + * the upcall daemon. * * Each request is at most one page long. */ -static int cache_pipe_upcall(struct cache_detail *detail, struct cache_hea= d *h) +static int cache_do_upcall(struct cache_detail *detail, struct cache_head = *h) { char *buf; struct cache_request *crq; @@ -1245,7 +1245,7 @@ int sunrpc_cache_upcall(struct cache_detail *detail, = struct cache_head *h) { if (test_and_set_bit(CACHE_PENDING, &h->flags)) return 0; - return cache_pipe_upcall(detail, h); + return cache_do_upcall(detail, h); } EXPORT_SYMBOL_GPL(sunrpc_cache_upcall); =20 --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 610793EFD3B; Wed, 25 Mar 2026 14:40: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=1774449659; cv=none; b=UeTv/2a9+xH3ongYREhmjkvdXu/kBVf/oWZx7WTyXANtDRzd98vxma/H2TzaxgrUv/miEioNnbafI9mGZQcwDVVqK9AevzLo69fwnSxoob7Fi84iY5O8jUWO0LiQIICTBbxGg2ouPy/YVedszdKJzVdrms0f4PQOIqJKgU+8uSw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449659; c=relaxed/simple; bh=1AKPKcydftHop5CQp8Iwo1zeSc7b5Z2FWQsZ75X7nWw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QNFNRWC4kie40LlFev26UtT0V6JOZJ67nEUj44W/nD8uAFZVRpuAyQr04RJcLDRM8SLyqboyCdgq4/GXZFIQzqc5YhDXpqb6ydSC7DH4khajXVFr2wCSuCKyOoYvHqMl6rUhLRidQSdwj8REaLSegkmw7YjZyRA6BYdJR/2j5ks= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QtR0VpPk; 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="QtR0VpPk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 75B06C4CEF7; Wed, 25 Mar 2026 14:40:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449659; bh=1AKPKcydftHop5CQp8Iwo1zeSc7b5Z2FWQsZ75X7nWw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=QtR0VpPkyZjdoD4F1UG3c+2efbEQ4bCoWzZETMhvg7xyQUJhvx+Lk5JOcwEsJNX2I 0D2VH/1xcWLNJP+vQdxFZB0LSCLP1g0a0otQOJNJVKh9vvSHIVCkyO/Uao+4yvaxr8 QSGKSwLjHB/9w83xwmIkTt2do7l120WSXKz7PQBEdDfKCgFLtGHBu0501ZiiHFFHbs VKNN8yMHvTkT6H3Fxj1mhspjcMxS0X+EhOFpJlDVzFu2ggchW/SSGRudjaWlJ31xQ4 ntLFR3L3GhvpraLGIpwJa7NYrlT6XY+1+1idbh4J3rgVa8T+zxCGehVnk1ZjvfLvxD TXvvAC479yisg== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:26 -0400 Subject: [PATCH v2 05/13] sunrpc: add a cache_notify callback Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-5-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1517; i=jlayton@kernel.org; h=from:subject:message-id; bh=1AKPKcydftHop5CQp8Iwo1zeSc7b5Z2FWQsZ75X7nWw=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/PuMNLtOswekS40u/7k9/vOEW6PhAWumjoLR aUdI4T0eOGJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7gAKCRAADmhBGVaC Ff5QD/0d0j0M06Nq0/dYUOn/kGW93mmPkvDM6lNvqGW/aDIJTQLWXllEsmCLwgTtXLmutUOzQch lSVppYwI+huB2VUKcTfs4ZLSeEb0f8KZJFg6aBN1VG2m08A0TfpEZEVo3ccH126U90UeR2UoRL2 aRi0mtJbjMvY7Y3eLh3fb3LIjfkONklW5PhDhS2W9ppIXifpqHOc4l6fvWJ9Cncf0QqU6lk+TTs uc0YttDh+oVYa4SUGRYKd3u9AopYiMQ3HPnaZBdxBrpLwHujqs46j7g+31KNCgZXN9zxqEwwuqa A2RM1emehdUo/1mHwMuTH4mEsFMEKhPVpmMhgZ2q+S89cpsmhrAHY3GXvhItbvMHnYPKVilUUcj LdJs+2VMnUThVVApaJGNTMooMgnMLrA7aQDu+xRm7B4/Bg/akkJqJ3DUINvowMBM2i9GDIb8xx1 sTj5MjyDU0tgEC5/8ocnB/6pNs+oTRJTkympkL7X1TTanR88jCxMWnsWlVblgWZXN1cadv/QG2x IX20zPYSj5Z6fFWuIwQeoA7EzMDy2YhkQG5LWCMYiUbeZOFHn/0PJz3S38ufSpFI0NbERn0DG7V VxZXMR4rhn2Lksi36t8Jk1FG0WaqI5xk1foOQk4khRX0zXJgS1jucNMi9FPwWukEjO5GvwiYxlK kjmkq+mEF1q9d2A== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 A later patch will be changing the kernel to send a netlink notification when there is a pending cache_request. Add a new cache_notify operation to struct cache_detail for this purpose. Signed-off-by: Jeff Layton --- include/linux/sunrpc/cache.h | 3 +++ net/sunrpc/cache.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 80a3f17731d8fbc1c5252a830b202016faa41a18..c358151c23950ab48e83991c613= 8bb7d0e049ace 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -80,6 +80,9 @@ struct cache_detail { int (*cache_upcall)(struct cache_detail *, struct cache_head *); =20 + int (*cache_notify)(struct cache_detail *cd, + struct cache_head *h); + void (*cache_request)(struct cache_detail *cd, struct cache_head *ch, char **bpp, int *blen); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 8a66128a1bfabca42b52f274ea34c1b594a5920b..a182a179a1bfdb883ceda417a58= 09d967659be5d 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1233,6 +1233,8 @@ static int cache_do_upcall(struct cache_detail *detai= l, struct cache_head *h) /* Lost a race, no longer PENDING, so don't enqueue */ ret =3D -EAGAIN; spin_unlock(&detail->queue_lock); + if (ret !=3D -EAGAIN && detail->cache_notify) + detail->cache_notify(detail, h); wake_up(&detail->queue_wait); if (ret =3D=3D -EAGAIN) { kfree(buf); --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 7D29A3F2105; Wed, 25 Mar 2026 14:41: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=1774449661; cv=none; b=Cl4aqjJcqzypqvZlt0mU0ayZe4AQ63+0TR4ACByBM9omWunCmKwEE+QPvr5cO1kLJd25hPjeoaKW/bTXAto7KfCQT0o5IQUaFNvJmLVZemxTF44uAPvtNx3jMH1Ch0a+L2fSMJj+61VwiaZcthISwJ7fJ9HgLvOHPL58FkfwGTU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449661; c=relaxed/simple; bh=xHH5cRLi+97NSkxpPLYe0sdarAUIo3BqhkjHWnScunA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oBM95Jjqt5Y48g+E1jICD8hi4NhEXYwNYDAYf9xGZZqCWkKkpp5n1xOXVypK9iBzbqROUsrmJiQo4Rn6ivbuCGB1Zgw+htYG/Ln1AMTKePekZMmdzeJDswPr7fw/pLOYFNgLKWJuyJOmHjWwKedA6HTfUUA+vHS7g/ghQBaUZsk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i108c/H1; 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="i108c/H1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3AF04C116C6; Wed, 25 Mar 2026 14:40:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449660; bh=xHH5cRLi+97NSkxpPLYe0sdarAUIo3BqhkjHWnScunA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=i108c/H1M4MaRbEu49YXKv1HRfRgVU4wCc07vJCFY8z5VjeMDCAC14MaGRTU00h4x qbINSn05GS0ZO3U+H/duc9j87311bp7QIgfJ6C70I/Zs1PeUjmUGjONnAGuZDqK1MH jhGmI1UcjLr8pDRtWuSe2bHAN3XGOXRrVucw9eO+RutxdDGJoNh4Fq8KjTnFqphFlg ph2eabcr5BVYlVgUP9eG/fXLyraLv+ba6LirRxPBdTtZLH/ERBMlWB4cLCrsgwhvvY Nc41qCcEIKvhb6TMSPja9z3cY+jREDSOE1fTXCH+KgJ1Ls9l286wdFTDhcf7F++Zca ZmiX5CphQYdOQ== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:27 -0400 Subject: [PATCH v2 06/13] sunrpc: add helpers to count and snapshot pending cache requests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-6-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3858; i=jlayton@kernel.org; h=from:subject:message-id; bh=xHH5cRLi+97NSkxpPLYe0sdarAUIo3BqhkjHWnScunA=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/PuvlI5IZsC/pehjII95piczodTsmbgnpypX 5V8xjha2J+JAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7gAKCRAADmhBGVaC FdZ7D/4p7zHkcMjKDNqf2i9yG+NocFs5MbxnhVjtFRG1wmhNyeUgivdSPztvbKXpMtbZgmCnYVv jiNFfi5/EmoYGcxClUL+D5r9pqjj8J8d/fwExmA9/U43CbHBiDhBY0WDmmAM5lkIJWJg0OxsCt/ 50syNb9nF+ggRy/UPrrG9oqSiyWQFThFT9w4GtP9bSLEL+Rpz8F8HDVhF5C4AHfqyuvEW4xBaeZ ABwzkCXsjwSNZlPTOjlWz6kZ/Dckn5aVW3fbxS/s8TFipxpdavGhWI9VGQIkwboCS1Z1UxCLVj0 Lk0n4JfkZ+hge/hXg3UTqQnEaYLFFM0VpMwdGGx1bMhTMteNA0mB5j2xypEl+bKxOon3Qxke3Qd mgG6a3fWBUJLdgzaUVuUhtCWdEByQyM+yLwvhgrPYZ6N+qHxMu8IMDnlOZ0thR4xHhYNm7S/iol I8c60v2AkK/nKBG2AdxNwSOApGcDZH8/5KvIpHS6+i4EN40av43nxm5EuJJLRJGu4eMWIb7bTho 9G5ino74hYWj6WacyM80/Ga97BvP6bDghROhvWAJnBcmoYl6qlIhEQRAKEqBEwhKSjK2TC0JICv jvVBFb7z4DSFZif3tLPVJj62BqbPqZA42QWcBbi+No8u3zigWeCAWMBuiCxvpEM86nZ+57hT8q3 NuA2gNzHvjv+g9w== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add sunrpc_cache_requests_count() and sunrpc_cache_requests_snapshot() to allow callers to count and snapshot the pending upcall request list without exposing struct cache_request outside of cache.c. Both functions skip entries that no longer have CACHE_PENDING set. The snapshot function takes a cache_get() reference on each item so the caller can safely use them after the queue_lock is released. These will be used by the nfsd generic netlink dumpit handler for svc_export upcall requests. Signed-off-by: Jeff Layton --- include/linux/sunrpc/cache.h | 6 +++++ net/sunrpc/cache.c | 61 ++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 67 insertions(+) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index c358151c23950ab48e83991c6138bb7d0e049ace..f88dc6bb17c7078781b3cf7e037= 1f369eddcb563 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -251,6 +251,12 @@ extern int sunrpc_cache_register_pipefs(struct dentry = *parent, const char *, extern void sunrpc_cache_unregister_pipefs(struct cache_detail *); extern void sunrpc_cache_unhash(struct cache_detail *, struct cache_head *= ); =20 +int sunrpc_cache_requests_count(struct cache_detail *cd); +int sunrpc_cache_requests_snapshot(struct cache_detail *cd, + struct cache_head **items, + u64 *seqnos, int max, + u64 min_seqno); + /* Must store cache_detail in seq_file->private if using next three functi= ons */ extern void *cache_seq_start_rcu(struct seq_file *file, loff_t *pos); extern void *cache_seq_next_rcu(struct seq_file *file, void *p, loff_t *po= s); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index a182a179a1bfdb883ceda417a5809d967659be5d..1282c61030d35efd924072e2739= 109cfae3472e2 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1899,3 +1899,64 @@ void sunrpc_cache_unhash(struct cache_detail *cd, st= ruct cache_head *h) spin_unlock(&cd->hash_lock); } EXPORT_SYMBOL_GPL(sunrpc_cache_unhash); + +/** + * sunrpc_cache_requests_count - count pending upcall requests + * @cd: cache_detail to query + * + * Returns the number of requests on the cache's request list that + * still have CACHE_PENDING set. + */ +int sunrpc_cache_requests_count(struct cache_detail *cd) +{ + struct cache_request *crq; + int cnt =3D 0; + + spin_lock(&cd->queue_lock); + list_for_each_entry(crq, &cd->requests, list) { + if (test_bit(CACHE_PENDING, &crq->item->flags)) + cnt++; + } + spin_unlock(&cd->queue_lock); + return cnt; +} +EXPORT_SYMBOL_GPL(sunrpc_cache_requests_count); + +/** + * sunrpc_cache_requests_snapshot - snapshot pending upcall requests + * @cd: cache_detail to query + * @items: array to fill with cache_head pointers (caller-allocated) + * @seqnos: array to fill with sequence numbers (caller-allocated) + * @max: size of the arrays + * @min_seqno: only include entries with seqno > min_seqno (0 for all) + * + * Only entries with CACHE_PENDING set are included. Takes a reference + * on each cache_head via cache_get(). Caller must call cache_put() + * on each returned item when done. + * + * Returns the number of entries filled. + */ +int sunrpc_cache_requests_snapshot(struct cache_detail *cd, + struct cache_head **items, + u64 *seqnos, int max, + u64 min_seqno) +{ + struct cache_request *crq; + int i =3D 0; + + spin_lock(&cd->queue_lock); + list_for_each_entry(crq, &cd->requests, list) { + if (i >=3D max) + break; + if (!test_bit(CACHE_PENDING, &crq->item->flags)) + continue; + if (crq->seqno <=3D min_seqno) + continue; + items[i] =3D cache_get(crq->item); + seqnos[i] =3D crq->seqno; + i++; + } + spin_unlock(&cd->queue_lock); + return i; +} +EXPORT_SYMBOL_GPL(sunrpc_cache_requests_snapshot); --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 D47E63F54CA; Wed, 25 Mar 2026 14:41:02 +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=1774449662; cv=none; b=SR/B7QAbKuDYVzei/HYsleK737oaD2nog0koq1/sQ3KPBGiZ2HgAYO4dDkqXUVds3DAabrVVizlP1HRzcqShw+kqsmUK/HQdoRL2dTlCARVxOvVveOImdYEp32wpL0m7PmyOtCduTDzsND3Acy3+31zT2FyotzO1NNzdnS1+DbQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449662; c=relaxed/simple; bh=R95s6KprQ4g2IpY1Qnm+S/XyNYljJLg3MP0mx52dOMk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rVdhlZkh8UPUo4cnFlsbQSSjKSohSjlXfXgvtIVtW4J1gF8wrHsoq05wOzoJcs/XhM+XbT+MBj+JOQMwoBLL9Vaop0TIK8PIuVmsAJHPWJ+WSvSAXm6rQQ30gHm5QQj8d2VxttfHIl6cdnnZM62OQi/FASxac7zk3uOxO71D914= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ACPYGFXL; 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="ACPYGFXL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32976C4CEF7; Wed, 25 Mar 2026 14:41:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449662; bh=R95s6KprQ4g2IpY1Qnm+S/XyNYljJLg3MP0mx52dOMk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ACPYGFXLxabf3oY46V3ufPEIgSpHiqfjYUXrwMqmr+ZS26HyNSi/GGOHnBf9VCvPf eUVTxF9eqLXhgQJky0h93jLcgf6CeG0SzaxHMH3hBro4LvY2qZcCwO0TwwN9QjhCv3 zCYwDIr0Y7lI+Fd8YiWlx0DjIRpkld15WuvMOFWnvi0C7CGZ0XXHKovyd5g4u3tX+1 gHPCuGF5NpLGm940xA4ulmKNg+hExHuz+etraFFLGwOjYz6PePbYmRBBOH7b7Ggi1A QNrjbz3/fpb9Kht4YhOZZj1Vh+6aQ5UtGD7Ye8CmA9yyOEUTlexJB02owRgSAMzkf4 9j03HqnqPZ1Jw== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:28 -0400 Subject: [PATCH v2 07/13] sunrpc: add a generic netlink family for cache upcalls Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-7-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=10109; i=jlayton@kernel.org; h=from:subject:message-id; bh=R95s6KprQ4g2IpY1Qnm+S/XyNYljJLg3MP0mx52dOMk=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/PujPDyYjGHj2OXIqviuGAfsl5x4LJA70VHY DvGXAho2BuJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7gAKCRAADmhBGVaC FSR+EAC/KbEU4/KLRYprUuXVyN8zEsYMovgI1ANRUWFMefScDZUdcj5hezUuYicpEw9ijjFaer/ CYbdzeNggCqVB6AA/3gJ3cmaJbZ7YzVKvYudRfBXDRwmxRbKY3MSrnJ1gx3v2uIV1L7ykxrpd4Y 8tfy1fq2UToKWF5zQhoFHsqU721O6ss+LSm0GG+W/v4aJnSfI5lxGqMRNEikLK43oiJy8I+2C3O UP4v0SNPJ4La+ADA64hnYgjVYZ9TGtJM54TGxlC6WLtCibIcm3PauCPRzQCl4TOY4yUqdQZJeuM 54T5xyyB6Pg+NJI1fiKTZ5BmluNHEtBn/AwMw0SIfmBYh5/Rw1PJQjl0QxYViZwKEsFQarkfMve kv+83keMVs0+SEc4vSQmKnEz+tMxFrtyH/BAJAD8WTcKh/MfiHATYRCPbbodEt8GkHS3r/cv2Qv h1W9be5JieVR7yeRuwW/51IeNHbg6HY4olrQw5k8/tN0DFMCSOBKiRp3kO1FPDCyryfZjd5HZ74 y8BeMMO7v3EX7stoKzESFxFnUS0wTXdYj2vF+WfExT2S00shPe1NLZlR6jITz81fmGfjlvs9h7p uq3oIrR3PM+ntOZ3Jr5Enl3rXTQ8NmEm17+39B+K2UVDm5N0jNVDVaqGTZt9eJqcA4cgvuJ46uL 2sq07CfFqfBZfEg== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 The auth.unix.ip and auth.unix.gid caches live in the sunrpc module, so they cannot use the nfsd generic netlink family. Create a new "sunrpc" generic netlink family with its own "exportd" multicast group to support cache upcall notifications for sunrpc-resident caches. Define a YAML spec (sunrpc_cache.yaml) with a cache-type enum (ip_map, unix_gid), a cache-notify multicast event, and the corresponding uapi header. Implement sunrpc_cache_notify() in cache.c, which checks for listeners on the exportd multicast group, builds and sends a SUNRPC_CMD_CACHE_NOTIFY message with the cache-type attribute. Register/unregister the sunrpc_nl_family in init_sunrpc() and cleanup_sunrpc(). Signed-off-by: Jeff Layton --- Documentation/netlink/specs/sunrpc_cache.yaml | 40 ++++++++++++++++++++++++ include/linux/sunrpc/cache.h | 2 ++ include/uapi/linux/sunrpc_netlink.h | 35 +++++++++++++++++++++ net/sunrpc/Makefile | 2 +- net/sunrpc/cache.c | 44 +++++++++++++++++++++++= ++++ net/sunrpc/netlink.c | 34 +++++++++++++++++++++ net/sunrpc/netlink.h | 22 ++++++++++++++ net/sunrpc/sunrpc_syms.c | 10 ++++++ 8 files changed, 188 insertions(+), 1 deletion(-) diff --git a/Documentation/netlink/specs/sunrpc_cache.yaml b/Documentation/= netlink/specs/sunrpc_cache.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f4aa699598bca9ce0215bbc418d= 9ddcae25c0110 --- /dev/null +++ b/Documentation/netlink/specs/sunrpc_cache.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Cla= use) +--- +name: sunrpc +protocol: genetlink +uapi-header: linux/sunrpc_netlink.h + +doc: SUNRPC cache upcall support over generic netlink. + +definitions: + - + type: flags + name: cache-type + entries: [ip_map, unix_gid] + +attribute-sets: + - + name: cache-notify + attributes: + - + name: cache-type + type: u32 + enum: cache-type + +operations: + list: + - + name: cache-notify + doc: Notification that there are cache requests that need servicing + attribute-set: cache-notify + mcgrp: exportd + event: + attributes: + - cache-type + +mcast-groups: + list: + - + name: none + - + name: exportd diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index f88dc6bb17c7078781b3cf7e0371f369eddcb563..2735c332ddb736ef043f811b5e9= e6ad2f57c9ce7 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -256,6 +256,8 @@ int sunrpc_cache_requests_snapshot(struct cache_detail = *cd, struct cache_head **items, u64 *seqnos, int max, u64 min_seqno); +int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h, + u32 cache_type); =20 /* Must store cache_detail in seq_file->private if using next three functi= ons */ extern void *cache_seq_start_rcu(struct seq_file *file, loff_t *pos); diff --git a/include/uapi/linux/sunrpc_netlink.h b/include/uapi/linux/sunrp= c_netlink.h new file mode 100644 index 0000000000000000000000000000000000000000..6135d9b3eef155a9192d9710c8c= 690283ec49073 --- /dev/null +++ b/include/uapi/linux/sunrpc_netlink.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Cl= ause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/sunrpc_cache.yaml */ +/* YNL-GEN uapi header */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ + +#ifndef _UAPI_LINUX_SUNRPC_NETLINK_H +#define _UAPI_LINUX_SUNRPC_NETLINK_H + +#define SUNRPC_FAMILY_NAME "sunrpc" +#define SUNRPC_FAMILY_VERSION 1 + +enum sunrpc_cache_type { + SUNRPC_CACHE_TYPE_IP_MAP =3D 1, + SUNRPC_CACHE_TYPE_UNIX_GID =3D 2, +}; + +enum { + SUNRPC_A_CACHE_NOTIFY_CACHE_TYPE =3D 1, + + __SUNRPC_A_CACHE_NOTIFY_MAX, + SUNRPC_A_CACHE_NOTIFY_MAX =3D (__SUNRPC_A_CACHE_NOTIFY_MAX - 1) +}; + +enum { + SUNRPC_CMD_CACHE_NOTIFY =3D 1, + + __SUNRPC_CMD_MAX, + SUNRPC_CMD_MAX =3D (__SUNRPC_CMD_MAX - 1) +}; + +#define SUNRPC_MCGRP_NONE "none" +#define SUNRPC_MCGRP_EXPORTD "exportd" + +#endif /* _UAPI_LINUX_SUNRPC_NETLINK_H */ diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile index f89c10fe7e6acc71d47273200d85425a2891a08a..96727df3aa85435a2de63a8483e= ab9d75d5b3495 100644 --- a/net/sunrpc/Makefile +++ b/net/sunrpc/Makefile @@ -14,7 +14,7 @@ sunrpc-y :=3D clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o sysfs.o \ svc_xprt.o \ - xprtmultipath.o + xprtmultipath.o netlink.o sunrpc-$(CONFIG_SUNRPC_DEBUG) +=3D debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) +=3D backchannel_rqst.o sunrpc-$(CONFIG_PROC_FS) +=3D stats.o diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 1282c61030d35efd924072e2739109cfae3472e2..d477b19dbfa15fdff71f946ade2= 643b56c35d491 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -33,9 +33,11 @@ #include #include #include +#include #include =20 #include "netns.h" +#include "netlink.h" #include "fail.h" =20 #define RPCDBG_FACILITY RPCDBG_CACHE @@ -1960,3 +1962,45 @@ int sunrpc_cache_requests_snapshot(struct cache_deta= il *cd, return i; } EXPORT_SYMBOL_GPL(sunrpc_cache_requests_snapshot); + +/** + * sunrpc_cache_notify - send a netlink notification for a cache event + * @cd: cache_detail for the cache + * @h: cache_head entry (unused, reserved for future use) + * @cache_type: cache type identifier (e.g. SUNRPC_CACHE_TYPE_UNIX_GID) + * + * Sends a SUNRPC_CMD_CACHE_NOTIFY multicast message on the "exportd" + * group if any listeners are present. Returns 0 on success or a + * negative errno. + */ +int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h, + u32 cache_type) +{ + struct genlmsghdr *hdr; + struct sk_buff *msg; + + if (!genl_has_listeners(&sunrpc_nl_family, cd->net, + SUNRPC_NLGRP_EXPORTD)) + return -ENOLINK; + + msg =3D genlmsg_new(nla_total_size(sizeof(u32)), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + hdr =3D genlmsg_put(msg, 0, 0, &sunrpc_nl_family, 0, + SUNRPC_CMD_CACHE_NOTIFY); + if (!hdr) { + nlmsg_free(msg); + return -ENOMEM; + } + + if (nla_put_u32(msg, SUNRPC_A_CACHE_NOTIFY_CACHE_TYPE, cache_type)) { + nlmsg_free(msg); + return -ENOMEM; + } + + genlmsg_end(msg, hdr); + return genlmsg_multicast_netns(&sunrpc_nl_family, cd->net, msg, 0, + SUNRPC_NLGRP_EXPORTD, GFP_KERNEL); +} +EXPORT_SYMBOL_GPL(sunrpc_cache_notify); diff --git a/net/sunrpc/netlink.c b/net/sunrpc/netlink.c new file mode 100644 index 0000000000000000000000000000000000000000..952de6de85e3f647ef9bc9c1e99= 651a247649abb --- /dev/null +++ b/net/sunrpc/netlink.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Cl= ause) +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/sunrpc_cache.yaml */ +/* YNL-GEN kernel source */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ + +#include +#include +#include + +#include "netlink.h" + +#include + +/* Ops table for sunrpc */ +static const struct genl_split_ops sunrpc_nl_ops[] =3D { +}; + +static const struct genl_multicast_group sunrpc_nl_mcgrps[] =3D { + [SUNRPC_NLGRP_NONE] =3D { "none", }, + [SUNRPC_NLGRP_EXPORTD] =3D { "exportd", }, +}; + +struct genl_family sunrpc_nl_family __ro_after_init =3D { + .name =3D SUNRPC_FAMILY_NAME, + .version =3D SUNRPC_FAMILY_VERSION, + .netnsok =3D true, + .parallel_ops =3D true, + .module =3D THIS_MODULE, + .split_ops =3D sunrpc_nl_ops, + .n_split_ops =3D ARRAY_SIZE(sunrpc_nl_ops), + .mcgrps =3D sunrpc_nl_mcgrps, + .n_mcgrps =3D ARRAY_SIZE(sunrpc_nl_mcgrps), +}; diff --git a/net/sunrpc/netlink.h b/net/sunrpc/netlink.h new file mode 100644 index 0000000000000000000000000000000000000000..74cf5183d745d778174abbbfed9= 514c4b6693e30 --- /dev/null +++ b/net/sunrpc/netlink.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Cl= ause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/sunrpc_cache.yaml */ +/* YNL-GEN kernel header */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ + +#ifndef _LINUX_SUNRPC_GEN_H +#define _LINUX_SUNRPC_GEN_H + +#include +#include + +#include + +enum { + SUNRPC_NLGRP_NONE, + SUNRPC_NLGRP_EXPORTD, +}; + +extern struct genl_family sunrpc_nl_family; + +#endif /* _LINUX_SUNRPC_GEN_H */ diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index bab6cab2940524a970422b62b3fa4212c61c4f43..ab88ce46afb556cb0a397fe5c9d= f3901813ad01e 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -23,9 +23,12 @@ #include #include =20 +#include + #include "sunrpc.h" #include "sysfs.h" #include "netns.h" +#include "netlink.h" =20 unsigned int sunrpc_net_id; EXPORT_SYMBOL_GPL(sunrpc_net_id); @@ -108,6 +111,10 @@ init_sunrpc(void) if (err) goto out5; =20 + err =3D genl_register_family(&sunrpc_nl_family); + if (err) + goto out6; + sunrpc_debugfs_init(); #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) rpc_register_sysctl(); @@ -116,6 +123,8 @@ init_sunrpc(void) init_socket_xprt(); /* clnt sock transport */ return 0; =20 +out6: + rpc_sysfs_exit(); out5: unregister_rpc_pipefs(); out4: @@ -131,6 +140,7 @@ init_sunrpc(void) static void __exit cleanup_sunrpc(void) { + genl_unregister_family(&sunrpc_nl_family); rpc_sysfs_exit(); rpc_cleanup_clids(); xprt_cleanup_ids(); --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 DEE8F3E6382; Wed, 25 Mar 2026 14:41: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=1774449665; cv=none; b=ReX3WrOY7XLxmwnqPm1RqWbC0ohwKlh2T2MXRB0dv3+tNFWl5nvBprRvPeZBzbr5jrmuF2pCA4rsmAkbW0u+VuXj8m9dWXLUmhKnkn12+jjNX7cMXIzScwdaRE92Qh0PA/xZUeEMsQXNsqv1d0DqhPJ0JrsAj4m/HlJUdqQ8vrs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449665; c=relaxed/simple; bh=5qctYXYnp9Nz5wFLETx7EoyDobcifJ2gXNp6E0nJVhA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XhXmNc81FQNy1x6n2KwGDQm5EYzZzpd+NuzVMAkKTP+oM7RhWdMRT3ZqQ5KyHMql/0BV35JeGFq2GOBc5DaniP3G4vfdKcgNGil4uDoR7ArKUiW0n/M5kscedo3o9uuTIicNTb9Eg3lVX/XFF6ojlqgpHFqR+nk/NrN1v8naJzg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ig7k17Og; 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="Ig7k17Og" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ECDEBC116C6; Wed, 25 Mar 2026 14:41:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449664; bh=5qctYXYnp9Nz5wFLETx7EoyDobcifJ2gXNp6E0nJVhA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Ig7k17OgWjTsEvcZrApt5bUTA+V9DVqrqUmt23o/uUyx3ny8WNnRmL+w/yJ7kgUzE Zl9eKNH9akufYTaHybUuGv6Tx4KLMtg3S8AlRFjj+yL08MGuJ7Ob9j6MzA2WBABiPY Z6iVEzCjqvSCiI3Za59QrvTtzBiyVxzi+/u6kg7uJxBUw7VG0NOEzITQAkoFBICP3F Eqhb+a+0jYxAhOlxE8NrMJQEjYkchspagiPkcminisom7RXo80qQmyXaPJ2ohOzrsB BLHXSNHgw3lww8QMAIQg7IpAwYPy96Tw3c79RRnXIoiiG6XtskVA9WSJSsIf53QudY Pj3rpmJZEbYuA== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:29 -0400 Subject: [PATCH v2 08/13] sunrpc: add netlink upcall for the auth.unix.ip cache Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-8-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=13519; i=jlayton@kernel.org; h=from:subject:message-id; bh=5qctYXYnp9Nz5wFLETx7EoyDobcifJ2gXNp6E0nJVhA=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/PvYQzXGa4f0QEpZSXdNwYJRx2xuJl5mCvtj 1CM700NVHmJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7wAKCRAADmhBGVaC FYF3D/4lobuzDgha/RTWY/tJTMW3q7MvkP7Iw2me/1NhCo8vH7zxKzhkR/jhw3ocm7DIV9jsCsO jHkvMrENnyKyIwc5xhzPA2+UTgZbPNxMj42cU2HrHV6M/WJa7ss5BS6dvZHO8hgwm5TAp7E41Hk Fnw5qOUIC9rYn4rgVrz2YcRGInKdVAJaG+RTqiEzxEdgq572iJQoHtBXXrIzrpvpp68V/uIszc2 jPCbCCRCtpjTJ5RIkNewPzPGcXCbyQWZr8Ysrh4/fLd5t8JjLlEOR2rvht4a7n5n6AdM7DhgXkT axr+GDtegQAbbNh/2wDlkEezk2OB5GG2zpyMHZYPDk6bTwb3bQyYVZ5LzVSvo2i6R2dw/QSTANP gmbN4zRSC1KK8PCnG1MlIRGXLhsMO2RLd/onwTKUMJYg6U6QnIVYZyr14R3Uz2+3KcV/o59Xwkp AQ0mnsv7A9cPUjRP5mPgA4gss076HWu1OedbDXGp0JwAV9c5XStB6MIp/PJGP1Xu4cD3bJNWGEC s/rH+W5DvZn8pV9czKG5F4aeQfJ3Q4xO9ca+FpHl0EUgMXMUyLgOstxyE8gFTPwrIHnTvs8YwGu PbUS2atf2Tk3dUscGISMqwpNVfP9B+I3+pjwpLdWIk5E9gDLeeWj22n4eRjh10lT5REei5TnY/w 5p7MiAWUQ41cVAQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add netlink-based cache upcall support for the ip_map (auth.unix.ip) cache, using the sunrpc generic netlink family. Add ip-map attribute-set (seqno, class, addr, domain, negative, expiry), ip-map-reqs wrapper, and ip-map-get-reqs / ip-map-set-reqs operations to the sunrpc_cache YAML spec and generated headers. Implement sunrpc_nl_ip_map_get_reqs_dumpit() which snapshots pending ip_map cache requests and sends each entry's seqno, class name, and IP address over netlink. Implement sunrpc_nl_ip_map_set_reqs_doit() which parses ip_map cache responses from userspace (class, addr, expiry, and domain name or negative flag) and updates the cache via __ip_map_lookup() / __ip_map_update(). Wire up ip_map_notify() callback in ip_map_cache_template so cache misses trigger SUNRPC_CMD_CACHE_NOTIFY multicast events with SUNRPC_CACHE_TYPE_IP_MAP. Signed-off-by: Jeff Layton --- Documentation/netlink/specs/sunrpc_cache.yaml | 47 +++++ include/uapi/linux/sunrpc_netlink.h | 21 +++ net/sunrpc/netlink.c | 34 ++++ net/sunrpc/netlink.h | 8 + net/sunrpc/svcauth_unix.c | 246 ++++++++++++++++++++++= ++++ 5 files changed, 356 insertions(+) diff --git a/Documentation/netlink/specs/sunrpc_cache.yaml b/Documentation/= netlink/specs/sunrpc_cache.yaml index f4aa699598bca9ce0215bbc418d9ddcae25c0110..8bcd43f65f3258ba43df4f80a7c= fda5f09f2f13e 100644 --- a/Documentation/netlink/specs/sunrpc_cache.yaml +++ b/Documentation/netlink/specs/sunrpc_cache.yaml @@ -20,6 +20,35 @@ attribute-sets: name: cache-type type: u32 enum: cache-type + - + name: ip-map + attributes: + - + name: seqno + type: u64 + - + name: class + type: string + - + name: addr + type: string + - + name: domain + type: string + - + name: negative + type: flag + - + name: expiry + type: u64 + - + name: ip-map-reqs + attributes: + - + name: requests + type: nest + nested-attributes: ip-map + multi-attr: true =20 operations: list: @@ -31,6 +60,24 @@ operations: event: attributes: - cache-type + - + name: ip-map-get-reqs + doc: Dump all pending ip_map requests + attribute-set: ip-map-reqs + flags: [admin-perm] + dump: + request: + attributes: + - requests + - + name: ip-map-set-reqs + doc: Respond to one or more ip_map requests + attribute-set: ip-map-reqs + flags: [admin-perm] + do: + request: + attributes: + - requests =20 mcast-groups: list: diff --git a/include/uapi/linux/sunrpc_netlink.h b/include/uapi/linux/sunrp= c_netlink.h index 6135d9b3eef155a9192d9710c8c690283ec49073..b44befb5a34b956e70065e0e12b= 816e2943da66e 100644 --- a/include/uapi/linux/sunrpc_netlink.h +++ b/include/uapi/linux/sunrpc_netlink.h @@ -22,8 +22,29 @@ enum { SUNRPC_A_CACHE_NOTIFY_MAX =3D (__SUNRPC_A_CACHE_NOTIFY_MAX - 1) }; =20 +enum { + SUNRPC_A_IP_MAP_SEQNO =3D 1, + SUNRPC_A_IP_MAP_CLASS, + SUNRPC_A_IP_MAP_ADDR, + SUNRPC_A_IP_MAP_DOMAIN, + SUNRPC_A_IP_MAP_NEGATIVE, + SUNRPC_A_IP_MAP_EXPIRY, + + __SUNRPC_A_IP_MAP_MAX, + SUNRPC_A_IP_MAP_MAX =3D (__SUNRPC_A_IP_MAP_MAX - 1) +}; + +enum { + SUNRPC_A_IP_MAP_REQS_REQUESTS =3D 1, + + __SUNRPC_A_IP_MAP_REQS_MAX, + SUNRPC_A_IP_MAP_REQS_MAX =3D (__SUNRPC_A_IP_MAP_REQS_MAX - 1) +}; + enum { SUNRPC_CMD_CACHE_NOTIFY =3D 1, + SUNRPC_CMD_IP_MAP_GET_REQS, + SUNRPC_CMD_IP_MAP_SET_REQS, =20 __SUNRPC_CMD_MAX, SUNRPC_CMD_MAX =3D (__SUNRPC_CMD_MAX - 1) diff --git a/net/sunrpc/netlink.c b/net/sunrpc/netlink.c index 952de6de85e3f647ef9bc9c1e99651a247649abb..f57eb17fc27dfb958bcb29a171e= a6b88834042e3 100644 --- a/net/sunrpc/netlink.c +++ b/net/sunrpc/netlink.c @@ -12,8 +12,42 @@ =20 #include =20 +/* Common nested types */ +const struct nla_policy sunrpc_ip_map_nl_policy[SUNRPC_A_IP_MAP_EXPIRY + 1= ] =3D { + [SUNRPC_A_IP_MAP_SEQNO] =3D { .type =3D NLA_U64, }, + [SUNRPC_A_IP_MAP_CLASS] =3D { .type =3D NLA_NUL_STRING, }, + [SUNRPC_A_IP_MAP_ADDR] =3D { .type =3D NLA_NUL_STRING, }, + [SUNRPC_A_IP_MAP_DOMAIN] =3D { .type =3D NLA_NUL_STRING, }, + [SUNRPC_A_IP_MAP_NEGATIVE] =3D { .type =3D NLA_FLAG, }, + [SUNRPC_A_IP_MAP_EXPIRY] =3D { .type =3D NLA_U64, }, +}; + +/* SUNRPC_CMD_IP_MAP_GET_REQS - dump */ +static const struct nla_policy sunrpc_ip_map_get_reqs_nl_policy[SUNRPC_A_I= P_MAP_REQS_REQUESTS + 1] =3D { + [SUNRPC_A_IP_MAP_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_ip_map_nl_po= licy), +}; + +/* SUNRPC_CMD_IP_MAP_SET_REQS - do */ +static const struct nla_policy sunrpc_ip_map_set_reqs_nl_policy[SUNRPC_A_I= P_MAP_REQS_REQUESTS + 1] =3D { + [SUNRPC_A_IP_MAP_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_ip_map_nl_po= licy), +}; + /* Ops table for sunrpc */ static const struct genl_split_ops sunrpc_nl_ops[] =3D { + { + .cmd =3D SUNRPC_CMD_IP_MAP_GET_REQS, + .dumpit =3D sunrpc_nl_ip_map_get_reqs_dumpit, + .policy =3D sunrpc_ip_map_get_reqs_nl_policy, + .maxattr =3D SUNRPC_A_IP_MAP_REQS_REQUESTS, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + }, + { + .cmd =3D SUNRPC_CMD_IP_MAP_SET_REQS, + .doit =3D sunrpc_nl_ip_map_set_reqs_doit, + .policy =3D sunrpc_ip_map_set_reqs_nl_policy, + .maxattr =3D SUNRPC_A_IP_MAP_REQS_REQUESTS, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, }; =20 static const struct genl_multicast_group sunrpc_nl_mcgrps[] =3D { diff --git a/net/sunrpc/netlink.h b/net/sunrpc/netlink.h index 74cf5183d745d778174abbbfed9514c4b6693e30..68b773960b3972536a9aa77861c= e332721f2819e 100644 --- a/net/sunrpc/netlink.h +++ b/net/sunrpc/netlink.h @@ -12,6 +12,14 @@ =20 #include =20 +/* Common nested types */ +extern const struct nla_policy sunrpc_ip_map_nl_policy[SUNRPC_A_IP_MAP_EXP= IRY + 1]; + +int sunrpc_nl_ip_map_get_reqs_dumpit(struct sk_buff *skb, + struct netlink_callback *cb); +int sunrpc_nl_ip_map_set_reqs_doit(struct sk_buff *skb, + struct genl_info *info); + enum { SUNRPC_NLGRP_NONE, SUNRPC_NLGRP_EXPORTD, diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 87732c4cb8383c64b440538a0d3f3113a3009b4e..b09b911c532a46bc629b720e71d= 5c6113d158b1a 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -17,11 +17,14 @@ #include #include #include +#include +#include #include =20 #define RPCDBG_FACILITY RPCDBG_AUTH =20 #include "netns.h" +#include "netlink.h" =20 /* * AUTHUNIX and AUTHNULL credentials are both handled here. @@ -1017,12 +1020,255 @@ struct auth_ops svcauth_unix =3D { .set_client =3D svcauth_unix_set_client, }; =20 +static int ip_map_notify(struct cache_detail *cd, struct cache_head *h) +{ + return sunrpc_cache_notify(cd, h, SUNRPC_CACHE_TYPE_IP_MAP); +} + +/** + * sunrpc_nl_ip_map_get_reqs_dumpit - dump pending ip_map requests + * @skb: reply buffer + * @cb: netlink metadata and command arguments + * + * Walk the ip_map cache's pending request list and create a netlink + * message with a nested entry for each cache_request, containing the + * seqno, class and addr. + * + * Uses cb->args[0] as a seqno cursor for dump continuation across + * multiple netlink messages. + * + * Returns the size of the reply or a negative errno. + */ +int sunrpc_nl_ip_map_get_reqs_dumpit(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct sunrpc_net *sn; + struct cache_detail *cd; + struct cache_head **items; + u64 *seqnos; + int cnt, i, emitted; + void *hdr; + int ret; + + sn =3D net_generic(sock_net(skb->sk), sunrpc_net_id); + + cd =3D sn->ip_map_cache; + if (!cd) + return -ENODEV; + + cnt =3D sunrpc_cache_requests_count(cd); + if (!cnt) + return 0; + + items =3D kcalloc(cnt, sizeof(*items), GFP_KERNEL); + seqnos =3D kcalloc(cnt, sizeof(*seqnos), GFP_KERNEL); + if (!items || !seqnos) { + ret =3D -ENOMEM; + goto out_alloc; + } + + cnt =3D sunrpc_cache_requests_snapshot(cd, items, seqnos, cnt, + cb->args[0]); + if (!cnt) { + ret =3D 0; + goto out_alloc; + } + + hdr =3D genlmsg_put(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, &sunrpc_nl_family, + NLM_F_MULTI, SUNRPC_CMD_IP_MAP_GET_REQS); + if (!hdr) { + ret =3D -ENOBUFS; + goto out_put; + } + + emitted =3D 0; + for (i =3D 0; i < cnt; i++) { + struct ip_map *im; + struct nlattr *nest; + char text_addr[40]; + + im =3D container_of(items[i], struct ip_map, h); + + if (ipv6_addr_v4mapped(&im->m_addr)) + snprintf(text_addr, 20, "%pI4", + &im->m_addr.s6_addr32[3]); + else + snprintf(text_addr, 40, "%pI6", &im->m_addr); + + nest =3D nla_nest_start(skb, SUNRPC_A_IP_MAP_REQS_REQUESTS); + if (!nest) + break; + + if (nla_put_u64_64bit(skb, SUNRPC_A_IP_MAP_SEQNO, + seqnos[i], 0) || + nla_put_string(skb, SUNRPC_A_IP_MAP_CLASS, + im->m_class) || + nla_put_string(skb, SUNRPC_A_IP_MAP_ADDR, text_addr)) { + nla_nest_cancel(skb, nest); + break; + } + + nla_nest_end(skb, nest); + cb->args[0] =3D seqnos[i]; + emitted++; + } + + if (!emitted) { + genlmsg_cancel(skb, hdr); + ret =3D -EMSGSIZE; + goto out_put; + } + + genlmsg_end(skb, hdr); + ret =3D skb->len; +out_put: + for (i =3D 0; i < cnt; i++) + cache_put(items[i], cd); +out_alloc: + kfree(seqnos); + kfree(items); + return ret; +} + +/** + * sunrpc_nl_parse_one_ip_map - parse one ip_map entry from netlink + * @cd: cache_detail for the ip_map cache + * @attr: nested attribute containing ip_map fields + * + * Parses one ip_map entry from a netlink message and updates the + * cache. Mirrors the logic in ip_map_parse(). + * + * Returns 0 on success or a negative errno. + */ +static int sunrpc_nl_parse_one_ip_map(struct cache_detail *cd, + struct nlattr *attr) +{ + struct nlattr *tb[SUNRPC_A_IP_MAP_EXPIRY + 1]; + union { + struct sockaddr sa; + struct sockaddr_in s4; + struct sockaddr_in6 s6; + } address; + struct sockaddr_in6 sin6; + struct ip_map *ipmp; + struct auth_domain *dom =3D NULL; + struct unix_domain *udom =3D NULL; + struct timespec64 boot; + time64_t expiry; + char class[8]; + int err; + int len; + + err =3D nla_parse_nested(tb, SUNRPC_A_IP_MAP_EXPIRY, attr, + sunrpc_ip_map_nl_policy, NULL); + if (err) + return err; + + /* class (required) */ + if (!tb[SUNRPC_A_IP_MAP_CLASS]) + return -EINVAL; + len =3D nla_len(tb[SUNRPC_A_IP_MAP_CLASS]); + if (len <=3D 0 || len > sizeof(class)) + return -EINVAL; + nla_strscpy(class, tb[SUNRPC_A_IP_MAP_CLASS], sizeof(class)); + + /* addr (required) */ + if (!tb[SUNRPC_A_IP_MAP_ADDR]) + return -EINVAL; + if (rpc_pton(cd->net, nla_data(tb[SUNRPC_A_IP_MAP_ADDR]), + nla_len(tb[SUNRPC_A_IP_MAP_ADDR]) - 1, + &address.sa, sizeof(address)) =3D=3D 0) + return -EINVAL; + + switch (address.sa.sa_family) { + case AF_INET: + sin6.sin6_family =3D AF_INET6; + ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr, + &sin6.sin6_addr); + break; +#if IS_ENABLED(CONFIG_IPV6) + case AF_INET6: + memcpy(&sin6, &address.s6, sizeof(sin6)); + break; +#endif + default: + return -EINVAL; + } + + /* expiry (required, wallclock seconds) */ + if (!tb[SUNRPC_A_IP_MAP_EXPIRY]) + return -EINVAL; + getboottime64(&boot); + expiry =3D nla_get_u64(tb[SUNRPC_A_IP_MAP_EXPIRY]) - boot.tv_sec; + + /* domain name or negative */ + if (tb[SUNRPC_A_IP_MAP_NEGATIVE]) { + udom =3D NULL; + } else if (tb[SUNRPC_A_IP_MAP_DOMAIN]) { + dom =3D unix_domain_find(nla_data(tb[SUNRPC_A_IP_MAP_DOMAIN])); + if (!dom) + return -ENOENT; + udom =3D container_of(dom, struct unix_domain, h); + } else { + return -EINVAL; + } + + ipmp =3D __ip_map_lookup(cd, class, &sin6.sin6_addr); + if (ipmp) + err =3D __ip_map_update(cd, ipmp, udom, expiry); + else + err =3D -ENOMEM; + + if (dom) + auth_domain_put(dom); + + cache_flush(); + return err; +} + +/** + * sunrpc_nl_ip_map_set_reqs_doit - respond to ip_map requests + * @skb: reply buffer + * @info: netlink metadata and command arguments + * + * Parse one or more ip_map cache responses from userspace and + * update the ip_map cache accordingly. + * + * Returns 0 on success or a negative errno. + */ +int sunrpc_nl_ip_map_set_reqs_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct sunrpc_net *sn; + struct cache_detail *cd; + const struct nlattr *attr; + int rem, ret =3D 0; + + sn =3D net_generic(genl_info_net(info), sunrpc_net_id); + + cd =3D sn->ip_map_cache; + if (!cd) + return -ENODEV; + + nlmsg_for_each_attr_type(attr, SUNRPC_A_IP_MAP_REQS_REQUESTS, + info->nlhdr, GENL_HDRLEN, rem) { + ret =3D sunrpc_nl_parse_one_ip_map(cd, + (struct nlattr *)attr); + if (ret) + break; + } + + return ret; +} + static const struct cache_detail ip_map_cache_template =3D { .owner =3D THIS_MODULE, .hash_size =3D IP_HASHMAX, .name =3D "auth.unix.ip", .cache_put =3D ip_map_put, .cache_upcall =3D ip_map_upcall, + .cache_notify =3D ip_map_notify, .cache_request =3D ip_map_request, .cache_parse =3D ip_map_parse, .cache_show =3D ip_map_show, --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 5C9833F7A95; Wed, 25 Mar 2026 14:41:06 +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=1774449666; cv=none; b=b7V4/un3w1aM3UFgsfD4N8b+YY0HnI85qCpCfAzGHraXPk9Ny6Z0wDIshk+xORAI9+jTsW5SR1TtcShxxkE52TDW1kO/9f5cpm9Knvvb1SzMLoM4pC4pDfPpgl9MPH9ahyqErgz30MBybRqY9ZyHBlBJavwKn7ZwHiP/ccu+aFc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449666; c=relaxed/simple; bh=/mt4gKosJj3BcJbidWFckn0BJqaQFNCdus9Eklhuclw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lBR6LO6HgEDZyjUw6MlelrXjQT273vWnSzJBVJCurOa4PlRRtLHn8sqb7mRvyiX0T3QXihdu1XramnhzzHYp4qx3mNQGyMcpjzb33YmMDvcUN7aDmhnQnnAhurCLB/aPV8B+jgUX0x2tGxWp4FCOfJpdIDSZEhZNCElarzk/P7Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bDfi1zHa; 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="bDfi1zHa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B468BC19423; Wed, 25 Mar 2026 14:41:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449666; bh=/mt4gKosJj3BcJbidWFckn0BJqaQFNCdus9Eklhuclw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bDfi1zHariN/u1X/Bornoj0D7IhJkbk6BlPfjk8m+tips73PAsQTMVXMqXOy9KK50 JqzqicUOuMVjW63h8Vk9dPIlFPaDu7ajuxvRkOpGRRGFziaMYQMv6GxQxaAStvtObS 0OdJNmMYXR6PWa+nK2I534Bwj/wEvLL2uMvnQ3v7VZRUQwfLS8yHpZYd57zGWfEyZr KQLl6K6BM7EEBURGpZOamrf03bMkysv1vzJE9Nth4T7mp1JypC33nV3A2N7rUG0y8F dlt4odEI1WLCdnbsDIcIduROYcjC88k/v4w1OOJj0rd2C3irvUHJsvsaUstvkQ78dP 9SbGmDBDPjIfg== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:30 -0400 Subject: [PATCH v2 09/13] sunrpc: add netlink upcall for the auth.unix.gid cache Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-9-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=13178; i=jlayton@kernel.org; h=from:subject:message-id; bh=/mt4gKosJj3BcJbidWFckn0BJqaQFNCdus9Eklhuclw=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/PvXsoiVCygdfEaurQZpIp3+bkUnK4IA22J0 Ze+Be1BelSJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7wAKCRAADmhBGVaC FY1sD/9YU9/P9tlcbtuO4DMLZ+u+WKV/AxPPmM7mMb+LajgGrqH6W+XEXIZj+UKWUTI9wVJ1ye9 QOyZXY7xRnLStwCIa36yIa+lrsGkLNjDOFGej5BmCQ2ioBuxub8CdvqyGz7o1/9afwedF/Rd5lf Rfv831RMfON1rWbFOOupeHGs7c67sNKE5OOsNOihOr8Yv5oUS8IKuPcOhkKjIdN0FJBJh+AGwXt qmLKFU/YdnUXmO49hXp3SuuyOX8Qcu42NWzZhinnIHwFr5qTwesrbmgyRRBaPMZNL0sYcN4GK/F +sKM6vQuFA9PLVniz7CKDWedL3/WwDtpw25t0R0SQt+KasTS+f+ojX8lR2c/sVbFvTnXAjF+WoR coM18PkoScY/sAdcvEFPXkEJGcdGpxiG0uuibnEe1FO9xh6Iwz49tyPG9zUYoS5B8TpovfJNnGR MWzjhn7iSlo2Jv3jWzckDk1ym5TElvGvl3WNarJ5z09bA/Dsh1F57AF1ACGsSO6478W6XObI2xY Y6359sGR/S9mC7ULMVBM839V15GQQAu6tuH1TjOQE7wEvYeIZasOyGf0yUH8oT/vQ8QuppCsHX6 IiD4EJOZT+1YCmj5v3G4JWo48N4otSGbo96uIxRhhMky67kdt+2cVY6CBfOzt+egFZryxwVZymY h5PFK8YMU55Ye0A== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add netlink-based cache upcall support for the unix_gid (auth.unix.gid) cache, using the sunrpc generic netlink family. Add unix-gid attribute-set (seqno, uid, gids multi-attr, negative, expiry), unix-gid-reqs wrapper, and unix-gid-get-reqs / unix-gid-set-reqs operations to the sunrpc_cache YAML spec and generated headers. Implement sunrpc_nl_unix_gid_get_reqs_dumpit() which snapshots pending unix_gid cache requests and sends each entry's seqno and uid over netlink. Implement sunrpc_nl_unix_gid_set_reqs_doit() which parses unix_gid cache responses from userspace (uid, expiry, gids as u32 multi-attr or negative flag) and updates the cache via unix_gid_lookup() / sunrpc_cache_update(). Wire up unix_gid_notify() callback in unix_gid_cache_template so cache misses trigger SUNRPC_CMD_CACHE_NOTIFY multicast events with SUNRPC_CACHE_TYPE_UNIX_GID. Signed-off-by: Jeff Layton --- Documentation/netlink/specs/sunrpc_cache.yaml | 45 +++++ include/uapi/linux/sunrpc_netlink.h | 20 +++ net/sunrpc/netlink.c | 32 ++++ net/sunrpc/netlink.h | 5 + net/sunrpc/svcauth_unix.c | 234 ++++++++++++++++++++++= ++++ 5 files changed, 336 insertions(+) diff --git a/Documentation/netlink/specs/sunrpc_cache.yaml b/Documentation/= netlink/specs/sunrpc_cache.yaml index 8bcd43f65f3258ba43df4f80a7cfda5f09f2f13e..ed0ddb61ebcf22b6ad889b0760f= 8a6f470295dbd 100644 --- a/Documentation/netlink/specs/sunrpc_cache.yaml +++ b/Documentation/netlink/specs/sunrpc_cache.yaml @@ -49,6 +49,33 @@ attribute-sets: type: nest nested-attributes: ip-map multi-attr: true + - + name: unix-gid + attributes: + - + name: seqno + type: u64 + - + name: uid + type: u32 + - + name: gids + type: u32 + multi-attr: true + - + name: negative + type: flag + - + name: expiry + type: u64 + - + name: unix-gid-reqs + attributes: + - + name: requests + type: nest + nested-attributes: unix-gid + multi-attr: true =20 operations: list: @@ -78,6 +105,24 @@ operations: request: attributes: - requests + - + name: unix-gid-get-reqs + doc: Dump all pending unix_gid requests + attribute-set: unix-gid-reqs + flags: [admin-perm] + dump: + request: + attributes: + - requests + - + name: unix-gid-set-reqs + doc: Respond to one or more unix_gid requests + attribute-set: unix-gid-reqs + flags: [admin-perm] + do: + request: + attributes: + - requests =20 mcast-groups: list: diff --git a/include/uapi/linux/sunrpc_netlink.h b/include/uapi/linux/sunrp= c_netlink.h index b44befb5a34b956e70065e0e12b816e2943da66e..d71c623e92aba4566e3114cc23d= 0aa553cbdb885 100644 --- a/include/uapi/linux/sunrpc_netlink.h +++ b/include/uapi/linux/sunrpc_netlink.h @@ -41,10 +41,30 @@ enum { SUNRPC_A_IP_MAP_REQS_MAX =3D (__SUNRPC_A_IP_MAP_REQS_MAX - 1) }; =20 +enum { + SUNRPC_A_UNIX_GID_SEQNO =3D 1, + SUNRPC_A_UNIX_GID_UID, + SUNRPC_A_UNIX_GID_GIDS, + SUNRPC_A_UNIX_GID_NEGATIVE, + SUNRPC_A_UNIX_GID_EXPIRY, + + __SUNRPC_A_UNIX_GID_MAX, + SUNRPC_A_UNIX_GID_MAX =3D (__SUNRPC_A_UNIX_GID_MAX - 1) +}; + +enum { + SUNRPC_A_UNIX_GID_REQS_REQUESTS =3D 1, + + __SUNRPC_A_UNIX_GID_REQS_MAX, + SUNRPC_A_UNIX_GID_REQS_MAX =3D (__SUNRPC_A_UNIX_GID_REQS_MAX - 1) +}; + enum { SUNRPC_CMD_CACHE_NOTIFY =3D 1, SUNRPC_CMD_IP_MAP_GET_REQS, SUNRPC_CMD_IP_MAP_SET_REQS, + SUNRPC_CMD_UNIX_GID_GET_REQS, + SUNRPC_CMD_UNIX_GID_SET_REQS, =20 __SUNRPC_CMD_MAX, SUNRPC_CMD_MAX =3D (__SUNRPC_CMD_MAX - 1) diff --git a/net/sunrpc/netlink.c b/net/sunrpc/netlink.c index f57eb17fc27dfb958bcb29a171ea6b88834042e3..41843f007c37a3ccb6480d11ec3= 1de201c5aa5e7 100644 --- a/net/sunrpc/netlink.c +++ b/net/sunrpc/netlink.c @@ -32,6 +32,24 @@ static const struct nla_policy sunrpc_ip_map_set_reqs_nl= _policy[SUNRPC_A_IP_MAP_ [SUNRPC_A_IP_MAP_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_ip_map_nl_po= licy), }; =20 +const struct nla_policy sunrpc_unix_gid_nl_policy[SUNRPC_A_UNIX_GID_EXPIRY= + 1] =3D { + [SUNRPC_A_UNIX_GID_SEQNO] =3D { .type =3D NLA_U64, }, + [SUNRPC_A_UNIX_GID_UID] =3D { .type =3D NLA_U32, }, + [SUNRPC_A_UNIX_GID_GIDS] =3D { .type =3D NLA_U32, }, + [SUNRPC_A_UNIX_GID_NEGATIVE] =3D { .type =3D NLA_FLAG, }, + [SUNRPC_A_UNIX_GID_EXPIRY] =3D { .type =3D NLA_U64, }, +}; + +/* SUNRPC_CMD_UNIX_GID_GET_REQS - dump */ +static const struct nla_policy sunrpc_unix_gid_get_reqs_nl_policy[SUNRPC_A= _UNIX_GID_REQS_REQUESTS + 1] =3D { + [SUNRPC_A_UNIX_GID_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_unix_gid_n= l_policy), +}; + +/* SUNRPC_CMD_UNIX_GID_SET_REQS - do */ +static const struct nla_policy sunrpc_unix_gid_set_reqs_nl_policy[SUNRPC_A= _UNIX_GID_REQS_REQUESTS + 1] =3D { + [SUNRPC_A_UNIX_GID_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_unix_gid_n= l_policy), +}; + /* Ops table for sunrpc */ static const struct genl_split_ops sunrpc_nl_ops[] =3D { { @@ -48,6 +66,20 @@ static const struct genl_split_ops sunrpc_nl_ops[] =3D { .maxattr =3D SUNRPC_A_IP_MAP_REQS_REQUESTS, .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, + { + .cmd =3D SUNRPC_CMD_UNIX_GID_GET_REQS, + .dumpit =3D sunrpc_nl_unix_gid_get_reqs_dumpit, + .policy =3D sunrpc_unix_gid_get_reqs_nl_policy, + .maxattr =3D SUNRPC_A_UNIX_GID_REQS_REQUESTS, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + }, + { + .cmd =3D SUNRPC_CMD_UNIX_GID_SET_REQS, + .doit =3D sunrpc_nl_unix_gid_set_reqs_doit, + .policy =3D sunrpc_unix_gid_set_reqs_nl_policy, + .maxattr =3D SUNRPC_A_UNIX_GID_REQS_REQUESTS, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, }; =20 static const struct genl_multicast_group sunrpc_nl_mcgrps[] =3D { diff --git a/net/sunrpc/netlink.h b/net/sunrpc/netlink.h index 68b773960b3972536a9aa77861ce332721f2819e..16b87519a4096a72798e686dc20= d2702ef329e52 100644 --- a/net/sunrpc/netlink.h +++ b/net/sunrpc/netlink.h @@ -14,11 +14,16 @@ =20 /* Common nested types */ extern const struct nla_policy sunrpc_ip_map_nl_policy[SUNRPC_A_IP_MAP_EXP= IRY + 1]; +extern const struct nla_policy sunrpc_unix_gid_nl_policy[SUNRPC_A_UNIX_GID= _EXPIRY + 1]; =20 int sunrpc_nl_ip_map_get_reqs_dumpit(struct sk_buff *skb, struct netlink_callback *cb); int sunrpc_nl_ip_map_set_reqs_doit(struct sk_buff *skb, struct genl_info *info); +int sunrpc_nl_unix_gid_get_reqs_dumpit(struct sk_buff *skb, + struct netlink_callback *cb); +int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *skb, + struct genl_info *info); =20 enum { SUNRPC_NLGRP_NONE, diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index b09b911c532a46bc629b720e71d5c6113d158b1a..7703523d424617a6033fa7ab48e= 25728b4c14abb 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -585,12 +585,246 @@ static int unix_gid_show(struct seq_file *m, return 0; } =20 +static int unix_gid_notify(struct cache_detail *cd, struct cache_head *h) +{ + return sunrpc_cache_notify(cd, h, SUNRPC_CACHE_TYPE_UNIX_GID); +} + +/** + * sunrpc_nl_unix_gid_get_reqs_dumpit - dump pending unix_gid requests + * @skb: reply buffer + * @cb: netlink metadata and command arguments + * + * Walk the unix_gid cache's pending request list and create a netlink + * message with a nested entry for each cache_request, containing the + * seqno and uid. + * + * Uses cb->args[0] as a seqno cursor for dump continuation across + * multiple netlink messages. + * + * Returns the size of the reply or a negative errno. + */ +int sunrpc_nl_unix_gid_get_reqs_dumpit(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct sunrpc_net *sn; + struct cache_detail *cd; + struct cache_head **items; + u64 *seqnos; + int cnt, i, emitted; + void *hdr; + int ret; + + sn =3D net_generic(sock_net(skb->sk), sunrpc_net_id); + + cd =3D sn->unix_gid_cache; + if (!cd) + return -ENODEV; + + cnt =3D sunrpc_cache_requests_count(cd); + if (!cnt) + return 0; + + items =3D kcalloc(cnt, sizeof(*items), GFP_KERNEL); + seqnos =3D kcalloc(cnt, sizeof(*seqnos), GFP_KERNEL); + if (!items || !seqnos) { + ret =3D -ENOMEM; + goto out_alloc; + } + + cnt =3D sunrpc_cache_requests_snapshot(cd, items, seqnos, cnt, + cb->args[0]); + if (!cnt) { + ret =3D 0; + goto out_alloc; + } + + hdr =3D genlmsg_put(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, &sunrpc_nl_family, + NLM_F_MULTI, SUNRPC_CMD_UNIX_GID_GET_REQS); + if (!hdr) { + ret =3D -ENOBUFS; + goto out_put; + } + + emitted =3D 0; + for (i =3D 0; i < cnt; i++) { + struct unix_gid *ug; + struct nlattr *nest; + + ug =3D container_of(items[i], struct unix_gid, h); + + nest =3D nla_nest_start(skb, + SUNRPC_A_UNIX_GID_REQS_REQUESTS); + if (!nest) + break; + + if (nla_put_u64_64bit(skb, SUNRPC_A_UNIX_GID_SEQNO, + seqnos[i], 0) || + nla_put_u32(skb, SUNRPC_A_UNIX_GID_UID, + from_kuid(&init_user_ns, ug->uid))) { + nla_nest_cancel(skb, nest); + break; + } + + nla_nest_end(skb, nest); + cb->args[0] =3D seqnos[i]; + emitted++; + } + + if (!emitted) { + genlmsg_cancel(skb, hdr); + ret =3D -EMSGSIZE; + goto out_put; + } + + genlmsg_end(skb, hdr); + ret =3D skb->len; +out_put: + for (i =3D 0; i < cnt; i++) + cache_put(items[i], cd); +out_alloc: + kfree(seqnos); + kfree(items); + return ret; +} + +/** + * sunrpc_nl_parse_one_unix_gid - parse one unix_gid entry from netlink + * @cd: cache_detail for the unix_gid cache + * @attr: nested attribute containing unix_gid fields + * + * Parses one unix_gid entry from a netlink message and updates the + * cache. Mirrors the logic in unix_gid_parse(). + * + * Returns 0 on success or a negative errno. + */ +static int sunrpc_nl_parse_one_unix_gid(struct cache_detail *cd, + struct nlattr *attr) +{ + struct nlattr *tb[SUNRPC_A_UNIX_GID_EXPIRY + 1]; + struct unix_gid ug, *ugp; + struct timespec64 boot; + struct nlattr *gid_attr; + int err, rem, gids =3D 0; + kuid_t uid; + + err =3D nla_parse_nested(tb, SUNRPC_A_UNIX_GID_EXPIRY, attr, + sunrpc_unix_gid_nl_policy, NULL); + if (err) + return err; + + /* uid (required) */ + if (!tb[SUNRPC_A_UNIX_GID_UID]) + return -EINVAL; + uid =3D make_kuid(current_user_ns(), + nla_get_u32(tb[SUNRPC_A_UNIX_GID_UID])); + ug.uid =3D uid; + + /* expiry (required, wallclock seconds) */ + if (!tb[SUNRPC_A_UNIX_GID_EXPIRY]) + return -EINVAL; + getboottime64(&boot); + ug.h.flags =3D 0; + ug.h.expiry_time =3D nla_get_u64(tb[SUNRPC_A_UNIX_GID_EXPIRY]) - + boot.tv_sec; + + if (tb[SUNRPC_A_UNIX_GID_NEGATIVE]) { + ug.gi =3D groups_alloc(0); + if (!ug.gi) + return -ENOMEM; + } else { + /* Count gids */ + nla_for_each_nested_type(gid_attr, SUNRPC_A_UNIX_GID_GIDS, + attr, rem) + gids++; + + if (gids > 8192) + return -EINVAL; + + ug.gi =3D groups_alloc(gids); + if (!ug.gi) + return -ENOMEM; + + gids =3D 0; + nla_for_each_nested_type(gid_attr, SUNRPC_A_UNIX_GID_GIDS, + attr, rem) { + kgid_t kgid; + + kgid =3D make_kgid(current_user_ns(), + nla_get_u32(gid_attr)); + if (!gid_valid(kgid)) { + err =3D -EINVAL; + goto out; + } + ug.gi->gid[gids++] =3D kgid; + } + groups_sort(ug.gi); + } + + ugp =3D unix_gid_lookup(cd, uid); + if (ugp) { + struct cache_head *ch; + + ch =3D sunrpc_cache_update(cd, &ug.h, &ugp->h, + unix_gid_hash(uid)); + if (!ch) { + err =3D -ENOMEM; + } else { + err =3D 0; + cache_put(ch, cd); + } + } else { + err =3D -ENOMEM; + } +out: + if (ug.gi) + put_group_info(ug.gi); + return err; +} + +/** + * sunrpc_nl_unix_gid_set_reqs_doit - respond to unix_gid requests + * @skb: reply buffer + * @info: netlink metadata and command arguments + * + * Parse one or more unix_gid cache responses from userspace and + * update the unix_gid cache accordingly. + * + * Returns 0 on success or a negative errno. + */ +int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct sunrpc_net *sn; + struct cache_detail *cd; + const struct nlattr *attr; + int rem, ret =3D 0; + + sn =3D net_generic(genl_info_net(info), sunrpc_net_id); + + cd =3D sn->unix_gid_cache; + if (!cd) + return -ENODEV; + + nlmsg_for_each_attr_type(attr, SUNRPC_A_UNIX_GID_REQS_REQUESTS, + info->nlhdr, GENL_HDRLEN, rem) { + ret =3D sunrpc_nl_parse_one_unix_gid(cd, + (struct nlattr *)attr); + if (ret) + break; + } + + return ret; +} + static const struct cache_detail unix_gid_cache_template =3D { .owner =3D THIS_MODULE, .hash_size =3D GID_HASHMAX, .name =3D "auth.unix.gid", .cache_put =3D unix_gid_put, .cache_upcall =3D unix_gid_upcall, + .cache_notify =3D unix_gid_notify, .cache_request =3D unix_gid_request, .cache_parse =3D unix_gid_parse, .cache_show =3D unix_gid_show, --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 AEA1A3E92B8; Wed, 25 Mar 2026 14:41: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=1774449668; cv=none; b=FLHw2TDioqJHaw7hq34cn6LhRchTbhziU0Tk/ayk1/z6FH9IkJAI+zeWtVtL9SNTjrIuo2+oacOPKTuXWIeKWLdmLBHVndSJftKHuWNW2W/KW/T3juNoCAvbfvRExDxJ456mVm8LiWqnVUXv+mFlPTmX5SIAK5rpbddJdj5ifiw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449668; c=relaxed/simple; bh=B5cTEaTEQdv9Xn8c4Db3TBkvHKsiNik7N964sW/pSBU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=P1AEtU5b0CdEmyKM5meRfHpUT9uPXkI2hOq9XXXsejmF9gv+XioR0SFfIgxPO4S+5Jnk+OnkMhWTz4i1r7a6QD/JWxYyOX3PqFl7FA66q+5gVPkEInQXZ4wLM0/Cl+Ahz6aFULgb5v7kp2AXWr559GqWWllBgfHi0x+dP58tJ5U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IKfLt3zn; 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="IKfLt3zn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A37DC2BCB2; Wed, 25 Mar 2026 14:41:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449668; bh=B5cTEaTEQdv9Xn8c4Db3TBkvHKsiNik7N964sW/pSBU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IKfLt3znCubLoBKGVsyJJ/VRvshQEUkFM3/reAdF4h/XLeiM+Z9ZLK4i5twq0h+H7 8B7diqjCrQM/cVT5t4JOYMLFZz0pTSQQHHTBiwYWh1XWJWAmrcpi3ZmoY5BriLHO9R Op2n9cVWClvahFPB/A1tR4GRKh7sy81wBcR9evIWe/8oXBil5b1DEP4/jhLUK4iY1o 1bAO2pKaEfyq3mc31yhWEeiajfqKN5K6gp2/1POi3pnR//dq20pLhxQf13Xm81me2d mKLnzZbmNM8KOA5ZYEaP+CthgSIEOVn5Oei2WnCpWPfKk9C5ZWW5XV/yBX/ScaOGc5 zkkpdIcu7kvug== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:31 -0400 Subject: [PATCH v2 10/13] nfsd: add netlink upcall for the svc_export cache Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-10-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=32341; i=jlayton@kernel.org; h=from:subject:message-id; bh=B5cTEaTEQdv9Xn8c4Db3TBkvHKsiNik7N964sW/pSBU=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/PvUSU32e3ZytmElrEvuvrOaPMP/9olcgvhf CWIQp1Ni52JAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7wAKCRAADmhBGVaC FeFAD/9EKCZk7Wuvno5gmLbSetNpNNQNjWWQB3yje8NBMQa3Q+3mM6izjoPl+qMegm7DvmUhbUI lMtRvZxOTKeWlKQglwwjwdYuIbqosZd2CmmGcdi0GDNSiUDa9cM2gdS4IKiOREG/uPMF5NgQ5bu OLWLfQxR1i71IUifCtrdODaYMnaJoSBtqmA9F6wlq+fxXCCBNtwc9DDkJv/9SaVKC71Z/xyUsP/ kX3gGZxq14yY3gzugm8ybGg6aA6PNFLigAwZzFIpUI3jQhAj3qxQl18ZKvFvlZGdJrQSS+Kt9+f 4Z47sbPV6PdAwgbYPTh3mIuxkwNwKZFJcDo5PKZj3N6iA2saHs/SiYY8wmQ+5o20DZJT/ehq/tq eLVWf/piFlvLjFd7n6YLjh+/2wJ6s4YjwDTUw5C3K7279HP7N5u1wA4XQpknBT7JsiqiDBmIQuR PDTk0WShC/sALGuDrtvX3P6Odj6agCdkulCu3darURAB1YPRNfHz6XpLoqOvv2amPxY+RwpvRgM iDTgphbr9nclr+rL9d9tXD7hNvoy1bo0cN2aN1cUjqc8ZvXD6VH3wVFuDlczbb+HE0mJLs36mJd +o20iB0rMPgGM0OGb0AKodz2P79EN5toYQbuQOE9MvLUum8TEzEZdqdI+DFrMC0rP3lm4DTHsRn c99lW5mhslwbamw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add netlink-based cache upcall support for the svc_export (nfsd.export) cache to Documentation/netlink/specs/nfsd.yaml and regenerate the resulting files. Implement nfsd_cache_notify() which sends a NFSD_CMD_CACHE_NOTIFY multicast event to the "exportd" group, carrying the cache type so userspace knows which cache has pending requests. Implement nfsd_nl_svc_export_get_reqs_dumpit() which snapshots pending svc_export cache requests and sends each entry's seqno, client name, and path over netlink. Implement nfsd_nl_svc_export_set_reqs_doit() which parses svc_export cache responses from userspace (client, path, expiry, flags, anon uid/gid, fslocations, uuid, secinfo, xprtsec, fsid, or negative flag) and updates the cache via svc_export_lookup() / svc_export_update(). Wire up the svc_export_notify() callback in svc_export_cache_template so cache misses trigger NFSD_CMD_CACHE_NOTIFY multicast events with NFSD_CACHE_TYPE_SVC_EXPORT. Note that the export-flags and xprtsec-mode enums are organized to match their counterparts in include/uapi/linux/nfsd/export.h. The intent is that future export options will only be added to the netlink headers, which should eliminate the need to keep so much in sync. Signed-off-by: Jeff Layton --- Documentation/netlink/specs/nfsd.yaml | 174 +++++++++++++ fs/nfsd/export.c | 443 ++++++++++++++++++++++++++++++= +++- fs/nfsd/netlink.c | 61 +++++ fs/nfsd/netlink.h | 13 + fs/nfsd/nfsctl.c | 28 +++ fs/nfsd/nfsd.h | 2 +- include/uapi/linux/nfsd_netlink.h | 110 +++++++++ net/sunrpc/netlink.c | 17 +- net/sunrpc/netlink.h | 3 +- 9 files changed, 835 insertions(+), 16 deletions(-) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index 8ab43c8253b2e83bcc178c3f4fe8c41c2997d153..709751502f8b56bd4b68462fa15= 337df5e3e035e 100644 --- a/Documentation/netlink/specs/nfsd.yaml +++ b/Documentation/netlink/specs/nfsd.yaml @@ -6,7 +6,51 @@ uapi-header: linux/nfsd_netlink.h =20 doc: NFSD configuration over generic netlink. =20 +definitions: + - + type: flags + name: cache-type + entries: [svc_export] + - + type: flags + name: export-flags + doc: These flags are ordered to match the NFSEXP_* flags in include/li= nux/nfsd/export.h + entries: + - readonly + - insecure-port + - rootsquash + - allsquash + - async + - gathered-writes + - noreaddirplus + - security-label + - sign-fh + - nohide + - nosubtreecheck + - noauthnlm + - msnfs + - fsid + - crossmount + - noacl + - v4root + - pnfs + - + type: flags + name: xprtsec-mode + doc: These flags are ordered to match the NFSEXP_XPRTSEC_* flags in in= clude/linux/nfsd/export.h + entries: + - none + - tls + - mtls + attribute-sets: + - + name: cache-notify + attributes: + - + name: cache-type + type: u32 + enum: cache-type - name: rpc-status attributes: @@ -132,6 +176,103 @@ attribute-sets: - name: npools type: u32 + - + name: fslocation + attributes: + - + name: host + type: string + - + name: path + type: string + - + name: fslocations + attributes: + - + name: location + type: nest + nested-attributes: fslocation + multi-attr: true + - + name: auth-flavor + attributes: + - + name: pseudoflavor + type: u32 + - + name: flags + type: u32 + enum: export-flags + enum-as-flags: true + - + name: svc-export-req + attributes: + - + name: seqno + type: u64 + - + name: client + type: string + - + name: path + type: string + - + name: svc-export + attributes: + - + name: seqno + type: u64 + - + name: client + type: string + - + name: path + type: string + - + name: negative + type: flag + - + name: expiry + type: u64 + - + name: anon-uid + type: u32 + - + name: anon-gid + type: u32 + - + name: fslocations + type: nest + nested-attributes: fslocations + - + name: uuid + type: binary + - + name: secinfo + type: nest + nested-attributes: auth-flavor + multi-attr: true + - + name: xprtsec + type: u32 + enum: xprtsec-mode + multi-attr: true + - + name: flags + type: u32 + enum: export-flags + enum-as-flags: true + - + name: fsid + type: s32 + - + name: svc-export-reqs + attributes: + - + name: requests + type: nest + nested-attributes: svc-export + multi-attr: true =20 operations: list: @@ -233,3 +374,36 @@ operations: attributes: - mode - npools + - + name: cache-notify + doc: Notification that there are cache requests that need servicing + attribute-set: cache-notify + mcgrp: exportd + event: + attributes: + - cache-type + - + name: svc-export-get-reqs + doc: Dump all pending svc_export requests + attribute-set: svc-export-reqs + flags: [admin-perm] + dump: + request: + attributes: + - requests + - + name: svc-export-set-reqs + doc: Respond to one or more svc_export requests + attribute-set: svc-export-reqs + flags: [admin-perm] + do: + request: + attributes: + - requests + +mcast-groups: + list: + - + name: none + - + name: exportd diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index e83e88e69d90ab48c7aff58ac2b36cd1a6e1bb71..cfe542fd7b22e27a7971a1f7920= 61767068ac439 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include =20 #include "nfsd.h" #include "nfsfh.h" @@ -24,6 +26,7 @@ #include "pnfs.h" #include "filecache.h" #include "trace.h" +#include "netlink.h" =20 #define NFSDDBG_FACILITY NFSDDBG_EXPORT =20 @@ -386,11 +389,446 @@ static void svc_export_put(struct kref *ref) queue_rcu_work(nfsd_export_wq, &exp->ex_rwork); } =20 +/** + * nfsd_nl_svc_export_get_reqs_dumpit - dump pending svc_export requests + * @skb: reply buffer + * @cb: netlink metadata and command arguments + * + * Walk the svc_export cache's pending request list and create a netlink + * message with a nested entry for each cache_request, containing the + * seqno, client string, and path. + * + * Uses cb->args[0] as a seqno cursor for dump continuation across + * multiple netlink messages. + * + * Returns the size of the reply or a negative errno. + */ +int nfsd_nl_svc_export_get_reqs_dumpit(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct nfsd_net *nn; + struct cache_detail *cd; + struct cache_head **items; + u64 *seqnos; + int cnt, i, emitted; + char *pathbuf; + void *hdr; + int ret; + + nn =3D net_generic(sock_net(skb->sk), nfsd_net_id); + + mutex_lock(&nfsd_mutex); + + cd =3D nn->svc_export_cache; + if (!cd) { + ret =3D -ENODEV; + goto out_unlock; + } + + cnt =3D sunrpc_cache_requests_count(cd); + if (!cnt) { + ret =3D 0; + goto out_unlock; + } + + items =3D kcalloc(cnt, sizeof(*items), GFP_KERNEL); + seqnos =3D kcalloc(cnt, sizeof(*seqnos), GFP_KERNEL); + pathbuf =3D kmalloc(PATH_MAX, GFP_KERNEL); + if (!items || !seqnos || !pathbuf) { + ret =3D -ENOMEM; + goto out_alloc; + } + + cnt =3D sunrpc_cache_requests_snapshot(cd, items, seqnos, cnt, + cb->args[0]); + if (!cnt) { + ret =3D 0; + goto out_alloc; + } + + hdr =3D genlmsg_put(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, &nfsd_nl_family, + NLM_F_MULTI, NFSD_CMD_SVC_EXPORT_GET_REQS); + if (!hdr) { + ret =3D -ENOBUFS; + goto out_put; + } + + emitted =3D 0; + for (i =3D 0; i < cnt; i++) { + struct svc_export *exp; + struct nlattr *nest; + char *pth; + + exp =3D container_of(items[i], struct svc_export, h); + + pth =3D d_path(&exp->ex_path, pathbuf, PATH_MAX); + if (IS_ERR(pth)) + continue; + + nest =3D nla_nest_start(skb, + NFSD_A_SVC_EXPORT_REQS_REQUESTS); + if (!nest) + break; + + if (nla_put_u64_64bit(skb, NFSD_A_SVC_EXPORT_SEQNO, + seqnos[i], 0) || + nla_put_string(skb, NFSD_A_SVC_EXPORT_CLIENT, + exp->ex_client->name) || + nla_put_string(skb, NFSD_A_SVC_EXPORT_PATH, pth)) { + nla_nest_cancel(skb, nest); + break; + } + + nla_nest_end(skb, nest); + cb->args[0] =3D seqnos[i]; + emitted++; + } + + if (!emitted) { + genlmsg_cancel(skb, hdr); + ret =3D -EMSGSIZE; + goto out_put; + } + + genlmsg_end(skb, hdr); + ret =3D skb->len; +out_put: + for (i =3D 0; i < cnt; i++) + cache_put(items[i], cd); +out_alloc: + kfree(pathbuf); + kfree(seqnos); + kfree(items); +out_unlock: + mutex_unlock(&nfsd_mutex); + return ret; +} + +/** + * nfsd_nl_parse_fslocations - parse fslocations from netlink + * @attr: NFSD_A_SVC_EXPORT_FSLOCATIONS nested attribute + * @fsloc: fslocations struct to fill in + * + * Returns 0 on success or a negative errno. + */ +static int nfsd_nl_parse_fslocations(struct nlattr *attr, + struct nfsd4_fs_locations *fsloc) +{ + struct nlattr *loc_attr; + int rem, count =3D 0; + int err; + + if (fsloc->locations) + return -EINVAL; + + /* Count locations first */ + nla_for_each_nested_type(loc_attr, NFSD_A_FSLOCATIONS_LOCATION, + attr, rem) + count++; + + if (count > MAX_FS_LOCATIONS) + return -EINVAL; + if (!count) + return 0; + + fsloc->locations =3D kcalloc(count, sizeof(struct nfsd4_fs_location), + GFP_KERNEL); + if (!fsloc->locations) + return -ENOMEM; + + nla_for_each_nested_type(loc_attr, NFSD_A_FSLOCATIONS_LOCATION, + attr, rem) { + struct nlattr *tb[NFSD_A_FSLOCATION_PATH + 1]; + struct nfsd4_fs_location *loc; + + err =3D nla_parse_nested(tb, NFSD_A_FSLOCATION_PATH, loc_attr, + nfsd_fslocation_nl_policy, NULL); + if (err) + goto out_free; + + if (!tb[NFSD_A_FSLOCATION_HOST] || + !tb[NFSD_A_FSLOCATION_PATH]) { + err =3D -EINVAL; + goto out_free; + } + + loc =3D &fsloc->locations[fsloc->locations_count++]; + loc->hosts =3D kstrdup(nla_data(tb[NFSD_A_FSLOCATION_HOST]), + GFP_KERNEL); + loc->path =3D kstrdup(nla_data(tb[NFSD_A_FSLOCATION_PATH]), + GFP_KERNEL); + if (!loc->hosts || !loc->path) { + err =3D -ENOMEM; + goto out_free; + } + } + + return 0; +out_free: + nfsd4_fslocs_free(fsloc); + return err; +} + +static struct svc_export *svc_export_update(struct svc_export *new, + struct svc_export *old); +static struct svc_export *svc_export_lookup(struct svc_export *); +static int check_export(const struct path *path, int *flags, + unsigned char *uuid); + +/** + * @cd: cache_detail for the svc_export cache + * @attr: nested attribute containing svc-export fields + * + * Parses one svc-export entry from a netlink message and updates the + * cache. Mirrors the logic in svc_export_parse(). + * + * Returns 0 on success or a negative errno. + */ +static int nfsd_nl_parse_one_export(struct cache_detail *cd, + struct nlattr *attr) +{ + struct nlattr *tb[NFSD_A_SVC_EXPORT_FSID + 1]; + struct auth_domain *dom =3D NULL; + struct svc_export exp =3D {}, *expp; + struct nlattr *secinfo_attr; + struct timespec64 boot; + int err, rem; + + err =3D nla_parse_nested(tb, NFSD_A_SVC_EXPORT_FSID, attr, + nfsd_svc_export_nl_policy, NULL); + if (err) + return err; + + /* client (required) */ + if (!tb[NFSD_A_SVC_EXPORT_CLIENT]) + return -EINVAL; + + dom =3D auth_domain_find(nla_data(tb[NFSD_A_SVC_EXPORT_CLIENT])); + if (!dom) + return -ENOENT; + + /* path (required) */ + if (!tb[NFSD_A_SVC_EXPORT_PATH]) { + err =3D -EINVAL; + goto out_dom; + } + + err =3D kern_path(nla_data(tb[NFSD_A_SVC_EXPORT_PATH]), 0, + &exp.ex_path); + if (err) + goto out_dom; + + exp.ex_client =3D dom; + exp.cd =3D cd; + exp.ex_devid_map =3D NULL; + exp.ex_xprtsec_modes =3D NFSEXP_XPRTSEC_ALL; + + /* expiry (required, wallclock seconds) */ + if (!tb[NFSD_A_SVC_EXPORT_EXPIRY]) { + err =3D -EINVAL; + goto out_path; + } + getboottime64(&boot); + exp.h.expiry_time =3D nla_get_u64(tb[NFSD_A_SVC_EXPORT_EXPIRY]) - + boot.tv_sec; + + if (tb[NFSD_A_SVC_EXPORT_NEGATIVE]) { + set_bit(CACHE_NEGATIVE, &exp.h.flags); + } else { + /* flags */ + if (tb[NFSD_A_SVC_EXPORT_FLAGS]) + exp.ex_flags =3D nla_get_u32(tb[NFSD_A_SVC_EXPORT_FLAGS]); + + /* anon uid */ + if (tb[NFSD_A_SVC_EXPORT_ANON_UID]) { + u32 uid =3D nla_get_u32(tb[NFSD_A_SVC_EXPORT_ANON_UID]); + + exp.ex_anon_uid =3D make_kuid(current_user_ns(), uid); + } + + /* anon gid */ + if (tb[NFSD_A_SVC_EXPORT_ANON_GID]) { + u32 gid =3D nla_get_u32(tb[NFSD_A_SVC_EXPORT_ANON_GID]); + + exp.ex_anon_gid =3D make_kgid(current_user_ns(), gid); + } + + /* fsid */ + if (tb[NFSD_A_SVC_EXPORT_FSID]) + exp.ex_fsid =3D nla_get_s32(tb[NFSD_A_SVC_EXPORT_FSID]); + + /* fslocations */ + if (tb[NFSD_A_SVC_EXPORT_FSLOCATIONS]) { + struct nlattr *fsl =3D tb[NFSD_A_SVC_EXPORT_FSLOCATIONS]; + + err =3D nfsd_nl_parse_fslocations(fsl, + &exp.ex_fslocs); + if (err) + goto out_path; + } + + /* uuid */ + if (tb[NFSD_A_SVC_EXPORT_UUID]) { + if (nla_len(tb[NFSD_A_SVC_EXPORT_UUID]) !=3D + EX_UUID_LEN) { + err =3D -EINVAL; + goto out_fslocs; + } + exp.ex_uuid =3D kmemdup(nla_data(tb[NFSD_A_SVC_EXPORT_UUID]), + EX_UUID_LEN, GFP_KERNEL); + if (!exp.ex_uuid) { + err =3D -ENOMEM; + goto out_fslocs; + } + } + + /* secinfo (multi-attr) */ + nla_for_each_nested_type(secinfo_attr, + NFSD_A_SVC_EXPORT_SECINFO, + attr, rem) { + struct nlattr *ftb[NFSD_A_AUTH_FLAVOR_FLAGS + 1]; + struct exp_flavor_info *f; + + if (exp.ex_nflavors >=3D MAX_SECINFO_LIST) { + err =3D -EINVAL; + goto out_uuid; + } + + err =3D nla_parse_nested(ftb, + NFSD_A_AUTH_FLAVOR_FLAGS, + secinfo_attr, + nfsd_auth_flavor_nl_policy, + NULL); + if (err) + goto out_uuid; + + f =3D &exp.ex_flavors[exp.ex_nflavors++]; + + if (ftb[NFSD_A_AUTH_FLAVOR_PSEUDOFLAVOR]) + f->pseudoflavor =3D nla_get_u32(ftb[NFSD_A_AUTH_FLAVOR_PSEUDOFLAVOR]); + + if (ftb[NFSD_A_AUTH_FLAVOR_FLAGS]) + f->flags =3D nla_get_u32(ftb[NFSD_A_AUTH_FLAVOR_FLAGS]); + + /* Only some flags are allowed to differ between flavors: */ + if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp.ex_flags)) { + err =3D -EINVAL; + goto out_uuid; + } + } + + /* xprtsec (multi-attr u32) */ + if (tb[NFSD_A_SVC_EXPORT_XPRTSEC]) { + struct nlattr *xp_attr; + + exp.ex_xprtsec_modes =3D 0; + nla_for_each_nested_type(xp_attr, + NFSD_A_SVC_EXPORT_XPRTSEC, + attr, rem) { + u32 mode =3D nla_get_u32(xp_attr); + + if (mode > NFSEXP_XPRTSEC_MTLS) { + err =3D -EINVAL; + goto out_uuid; + } + exp.ex_xprtsec_modes |=3D mode; + } + } + + err =3D check_export(&exp.ex_path, &exp.ex_flags, + exp.ex_uuid); + if (err) + goto out_uuid; + + if (exp.h.expiry_time < seconds_since_boot()) + goto out_uuid; + + err =3D -EINVAL; + if (!uid_valid(exp.ex_anon_uid)) + goto out_uuid; + if (!gid_valid(exp.ex_anon_gid)) + goto out_uuid; + err =3D 0; + + nfsd4_setup_layout_type(&exp); + } + + expp =3D svc_export_lookup(&exp); + if (!expp) { + err =3D -ENOMEM; + goto out_uuid; + } + expp =3D svc_export_update(&exp, expp); + if (expp) { + trace_nfsd_export_update(expp); + cache_flush(); + exp_put(expp); + } else { + err =3D -ENOMEM; + } + +out_uuid: + kfree(exp.ex_uuid); +out_fslocs: + nfsd4_fslocs_free(&exp.ex_fslocs); +out_path: + path_put(&exp.ex_path); +out_dom: + auth_domain_put(dom); + return err; +} + +/** + * nfsd_nl_svc_export_set_reqs_doit - respond to svc_export requests + * @skb: reply buffer + * @info: netlink metadata and command arguments + * + * Parse one or more svc_export cache responses from userspace and + * update the export cache accordingly. + * + * Returns 0 on success or a negative errno. + */ +int nfsd_nl_svc_export_set_reqs_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct nfsd_net *nn; + struct cache_detail *cd; + const struct nlattr *attr; + int rem, ret =3D 0; + + nn =3D net_generic(genl_info_net(info), nfsd_net_id); + + mutex_lock(&nfsd_mutex); + + cd =3D nn->svc_export_cache; + if (!cd) { + ret =3D -ENODEV; + goto out_unlock; + } + + nlmsg_for_each_attr_type(attr, NFSD_A_SVC_EXPORT_REQS_REQUESTS, + info->nlhdr, GENL_HDRLEN, rem) { + ret =3D nfsd_nl_parse_one_export(cd, (struct nlattr *)attr); + if (ret) + break; + } + +out_unlock: + mutex_unlock(&nfsd_mutex); + return ret; +} + static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) { return sunrpc_cache_upcall(cd, h); } =20 +static int svc_export_notify(struct cache_detail *cd, struct cache_head *h) +{ + return nfsd_cache_notify(cd, h, NFSD_CACHE_TYPE_SVC_EXPORT); +} + static void svc_export_request(struct cache_detail *cd, struct cache_head *h, char **bpp, int *blen) @@ -410,10 +848,6 @@ static void svc_export_request(struct cache_detail *cd, (*bpp)[-1] =3D '\n'; } =20 -static struct svc_export *svc_export_update(struct svc_export *new, - struct svc_export *old); -static struct svc_export *svc_export_lookup(struct svc_export *); - static int check_export(const struct path *path, int *flags, unsigned char= *uuid) { struct inode *inode =3D d_inode(path->dentry); @@ -907,6 +1341,7 @@ static const struct cache_detail svc_export_cache_temp= late =3D { .name =3D "nfsd.export", .cache_put =3D svc_export_put, .cache_upcall =3D svc_export_upcall, + .cache_notify =3D svc_export_notify, .cache_request =3D svc_export_request, .cache_parse =3D svc_export_parse, .cache_show =3D svc_export_show, diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c index 81c943345d13db849483bf0d6773458115ff0134..fb401d7302afb9e41cb074581f7= b94e8ece6cf0c 100644 --- a/fs/nfsd/netlink.c +++ b/fs/nfsd/netlink.c @@ -12,11 +12,41 @@ #include =20 /* Common nested types */ +const struct nla_policy nfsd_auth_flavor_nl_policy[NFSD_A_AUTH_FLAVOR_FLAG= S + 1] =3D { + [NFSD_A_AUTH_FLAVOR_PSEUDOFLAVOR] =3D { .type =3D NLA_U32, }, + [NFSD_A_AUTH_FLAVOR_FLAGS] =3D NLA_POLICY_MASK(NLA_U32, 0x3ffff), +}; + +const struct nla_policy nfsd_fslocation_nl_policy[NFSD_A_FSLOCATION_PATH += 1] =3D { + [NFSD_A_FSLOCATION_HOST] =3D { .type =3D NLA_NUL_STRING, }, + [NFSD_A_FSLOCATION_PATH] =3D { .type =3D NLA_NUL_STRING, }, +}; + +const struct nla_policy nfsd_fslocations_nl_policy[NFSD_A_FSLOCATIONS_LOCA= TION + 1] =3D { + [NFSD_A_FSLOCATIONS_LOCATION] =3D NLA_POLICY_NESTED(nfsd_fslocation_nl_po= licy), +}; + const struct nla_policy nfsd_sock_nl_policy[NFSD_A_SOCK_TRANSPORT_NAME + 1= ] =3D { [NFSD_A_SOCK_ADDR] =3D { .type =3D NLA_BINARY, }, [NFSD_A_SOCK_TRANSPORT_NAME] =3D { .type =3D NLA_NUL_STRING, }, }; =20 +const struct nla_policy nfsd_svc_export_nl_policy[NFSD_A_SVC_EXPORT_FSID += 1] =3D { + [NFSD_A_SVC_EXPORT_SEQNO] =3D { .type =3D NLA_U64, }, + [NFSD_A_SVC_EXPORT_CLIENT] =3D { .type =3D NLA_NUL_STRING, }, + [NFSD_A_SVC_EXPORT_PATH] =3D { .type =3D NLA_NUL_STRING, }, + [NFSD_A_SVC_EXPORT_NEGATIVE] =3D { .type =3D NLA_FLAG, }, + [NFSD_A_SVC_EXPORT_EXPIRY] =3D { .type =3D NLA_U64, }, + [NFSD_A_SVC_EXPORT_ANON_UID] =3D { .type =3D NLA_U32, }, + [NFSD_A_SVC_EXPORT_ANON_GID] =3D { .type =3D NLA_U32, }, + [NFSD_A_SVC_EXPORT_FSLOCATIONS] =3D NLA_POLICY_NESTED(nfsd_fslocations_nl= _policy), + [NFSD_A_SVC_EXPORT_UUID] =3D { .type =3D NLA_BINARY, }, + [NFSD_A_SVC_EXPORT_SECINFO] =3D NLA_POLICY_NESTED(nfsd_auth_flavor_nl_pol= icy), + [NFSD_A_SVC_EXPORT_XPRTSEC] =3D NLA_POLICY_MASK(NLA_U32, 0x7), + [NFSD_A_SVC_EXPORT_FLAGS] =3D NLA_POLICY_MASK(NLA_U32, 0x3ffff), + [NFSD_A_SVC_EXPORT_FSID] =3D { .type =3D NLA_S32, }, +}; + const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED + 1]= =3D { [NFSD_A_VERSION_MAJOR] =3D { .type =3D NLA_U32, }, [NFSD_A_VERSION_MINOR] =3D { .type =3D NLA_U32, }, @@ -48,6 +78,16 @@ static const struct nla_policy nfsd_pool_mode_set_nl_pol= icy[NFSD_A_POOL_MODE_MOD [NFSD_A_POOL_MODE_MODE] =3D { .type =3D NLA_NUL_STRING, }, }; =20 +/* NFSD_CMD_SVC_EXPORT_GET_REQS - dump */ +static const struct nla_policy nfsd_svc_export_get_reqs_nl_policy[NFSD_A_S= VC_EXPORT_REQS_REQUESTS + 1] =3D { + [NFSD_A_SVC_EXPORT_REQS_REQUESTS] =3D NLA_POLICY_NESTED(nfsd_svc_export_n= l_policy), +}; + +/* NFSD_CMD_SVC_EXPORT_SET_REQS - do */ +static const struct nla_policy nfsd_svc_export_set_reqs_nl_policy[NFSD_A_S= VC_EXPORT_REQS_REQUESTS + 1] =3D { + [NFSD_A_SVC_EXPORT_REQS_REQUESTS] =3D NLA_POLICY_NESTED(nfsd_svc_export_n= l_policy), +}; + /* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] =3D { { @@ -103,6 +143,25 @@ static const struct genl_split_ops nfsd_nl_ops[] =3D { .doit =3D nfsd_nl_pool_mode_get_doit, .flags =3D GENL_CMD_CAP_DO, }, + { + .cmd =3D NFSD_CMD_SVC_EXPORT_GET_REQS, + .dumpit =3D nfsd_nl_svc_export_get_reqs_dumpit, + .policy =3D nfsd_svc_export_get_reqs_nl_policy, + .maxattr =3D NFSD_A_SVC_EXPORT_REQS_REQUESTS, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + }, + { + .cmd =3D NFSD_CMD_SVC_EXPORT_SET_REQS, + .doit =3D nfsd_nl_svc_export_set_reqs_doit, + .policy =3D nfsd_svc_export_set_reqs_nl_policy, + .maxattr =3D NFSD_A_SVC_EXPORT_REQS_REQUESTS, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, +}; + +static const struct genl_multicast_group nfsd_nl_mcgrps[] =3D { + [NFSD_NLGRP_NONE] =3D { "none", }, + [NFSD_NLGRP_EXPORTD] =3D { "exportd", }, }; =20 struct genl_family nfsd_nl_family __ro_after_init =3D { @@ -113,4 +172,6 @@ struct genl_family nfsd_nl_family __ro_after_init =3D { .module =3D THIS_MODULE, .split_ops =3D nfsd_nl_ops, .n_split_ops =3D ARRAY_SIZE(nfsd_nl_ops), + .mcgrps =3D nfsd_nl_mcgrps, + .n_mcgrps =3D ARRAY_SIZE(nfsd_nl_mcgrps), }; diff --git a/fs/nfsd/netlink.h b/fs/nfsd/netlink.h index 478117ff6b8c0d6e83d6ece09a938935e031c62b..d6ed8d9b0bb149faa4d6493ba94= 972addf9c26ed 100644 --- a/fs/nfsd/netlink.h +++ b/fs/nfsd/netlink.h @@ -13,7 +13,11 @@ #include =20 /* Common nested types */ +extern const struct nla_policy nfsd_auth_flavor_nl_policy[NFSD_A_AUTH_FLAV= OR_FLAGS + 1]; +extern const struct nla_policy nfsd_fslocation_nl_policy[NFSD_A_FSLOCATION= _PATH + 1]; +extern const struct nla_policy nfsd_fslocations_nl_policy[NFSD_A_FSLOCATIO= NS_LOCATION + 1]; extern const struct nla_policy nfsd_sock_nl_policy[NFSD_A_SOCK_TRANSPORT_N= AME + 1]; +extern const struct nla_policy nfsd_svc_export_nl_policy[NFSD_A_SVC_EXPORT= _FSID + 1]; extern const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABL= ED + 1]; =20 int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb, @@ -26,6 +30,15 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, struc= t genl_info *info); int nfsd_nl_listener_get_doit(struct sk_buff *skb, struct genl_info *info); int nfsd_nl_pool_mode_set_doit(struct sk_buff *skb, struct genl_info *info= ); int nfsd_nl_pool_mode_get_doit(struct sk_buff *skb, struct genl_info *info= ); +int nfsd_nl_svc_export_get_reqs_dumpit(struct sk_buff *skb, + struct netlink_callback *cb); +int nfsd_nl_svc_export_set_reqs_doit(struct sk_buff *skb, + struct genl_info *info); + +enum { + NFSD_NLGRP_NONE, + NFSD_NLGRP_EXPORTD, +}; =20 extern struct genl_family nfsd_nl_family; =20 diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index dc294c4f8c58a6692b9dfbeb98fedbd649ae1b95..0f236046adfd239d0f88f4ed82a= 14e1a41cb6abe 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2215,6 +2215,34 @@ int nfsd_nl_pool_mode_get_doit(struct sk_buff *skb, = struct genl_info *info) return err; } =20 +int nfsd_cache_notify(struct cache_detail *cd, struct cache_head *h, u32 c= ache_type) +{ + struct genlmsghdr *hdr; + struct sk_buff *msg; + + if (!genl_has_listeners(&nfsd_nl_family, cd->net, NFSD_NLGRP_EXPORTD)) + return -ENOLINK; + + msg =3D genlmsg_new(nla_total_size(sizeof(u32)), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + hdr =3D genlmsg_put(msg, 0, 0, &nfsd_nl_family, 0, NFSD_CMD_CACHE_NOTIFY); + if (!hdr) { + nlmsg_free(msg); + return -ENOMEM; + } + + if (nla_put_u32(msg, NFSD_A_CACHE_NOTIFY_CACHE_TYPE, cache_type)) { + nlmsg_free(msg); + return -ENOMEM; + } + + genlmsg_end(msg, hdr); + return genlmsg_multicast_netns(&nfsd_nl_family, cd->net, msg, 0, + NFSD_NLGRP_EXPORTD, GFP_KERNEL); +} + /** * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace * @net: a freshly-created network namespace diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 260bf8badb032de18f973556fa5deabe7e67870d..709da3c7a5fa7cdb4f5e91b488b= 02295c5f54392 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -108,7 +108,7 @@ struct dentry *nfsd_client_mkdir(struct nfsd_net *nn, const struct tree_descr *, struct dentry **fdentries); void nfsd_client_rmdir(struct dentry *dentry); - +int nfsd_cache_notify(struct cache_detail *cd, struct cache_head *h, u32 c= ache_type); =20 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) #ifdef CONFIG_NFSD_V2_ACL diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_ne= tlink.h index 97c7447f4d14df97c1cba8cdf1f24fba0a7918b3..eae426e9c8e737a95181e7d7b09= 04b86fc35cff6 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -10,6 +10,52 @@ #define NFSD_FAMILY_NAME "nfsd" #define NFSD_FAMILY_VERSION 1 =20 +enum nfsd_cache_type { + NFSD_CACHE_TYPE_SVC_EXPORT =3D 1, +}; + +/* + * These flags are ordered to match the NFSEXP_* flags in + * include/linux/nfsd/export.h + */ +enum nfsd_export_flags { + NFSD_EXPORT_FLAGS_READONLY =3D 1, + NFSD_EXPORT_FLAGS_INSECURE_PORT =3D 2, + NFSD_EXPORT_FLAGS_ROOTSQUASH =3D 4, + NFSD_EXPORT_FLAGS_ALLSQUASH =3D 8, + NFSD_EXPORT_FLAGS_ASYNC =3D 16, + NFSD_EXPORT_FLAGS_GATHERED_WRITES =3D 32, + NFSD_EXPORT_FLAGS_NOREADDIRPLUS =3D 64, + NFSD_EXPORT_FLAGS_SECURITY_LABEL =3D 128, + NFSD_EXPORT_FLAGS_SIGN_FH =3D 256, + NFSD_EXPORT_FLAGS_NOHIDE =3D 512, + NFSD_EXPORT_FLAGS_NOSUBTREECHECK =3D 1024, + NFSD_EXPORT_FLAGS_NOAUTHNLM =3D 2048, + NFSD_EXPORT_FLAGS_MSNFS =3D 4096, + NFSD_EXPORT_FLAGS_FSID =3D 8192, + NFSD_EXPORT_FLAGS_CROSSMOUNT =3D 16384, + NFSD_EXPORT_FLAGS_NOACL =3D 32768, + NFSD_EXPORT_FLAGS_V4ROOT =3D 65536, + NFSD_EXPORT_FLAGS_PNFS =3D 131072, +}; + +/* + * These flags are ordered to match the NFSEXP_XPRTSEC_* flags in + * include/linux/nfsd/export.h + */ +enum nfsd_xprtsec_mode { + NFSD_XPRTSEC_MODE_NONE =3D 1, + NFSD_XPRTSEC_MODE_TLS =3D 2, + NFSD_XPRTSEC_MODE_MTLS =3D 4, +}; + +enum { + NFSD_A_CACHE_NOTIFY_CACHE_TYPE =3D 1, + + __NFSD_A_CACHE_NOTIFY_MAX, + NFSD_A_CACHE_NOTIFY_MAX =3D (__NFSD_A_CACHE_NOTIFY_MAX - 1) +}; + enum { NFSD_A_RPC_STATUS_XID =3D 1, NFSD_A_RPC_STATUS_FLAGS, @@ -81,6 +127,64 @@ enum { NFSD_A_POOL_MODE_MAX =3D (__NFSD_A_POOL_MODE_MAX - 1) }; =20 +enum { + NFSD_A_FSLOCATION_HOST =3D 1, + NFSD_A_FSLOCATION_PATH, + + __NFSD_A_FSLOCATION_MAX, + NFSD_A_FSLOCATION_MAX =3D (__NFSD_A_FSLOCATION_MAX - 1) +}; + +enum { + NFSD_A_FSLOCATIONS_LOCATION =3D 1, + + __NFSD_A_FSLOCATIONS_MAX, + NFSD_A_FSLOCATIONS_MAX =3D (__NFSD_A_FSLOCATIONS_MAX - 1) +}; + +enum { + NFSD_A_AUTH_FLAVOR_PSEUDOFLAVOR =3D 1, + NFSD_A_AUTH_FLAVOR_FLAGS, + + __NFSD_A_AUTH_FLAVOR_MAX, + NFSD_A_AUTH_FLAVOR_MAX =3D (__NFSD_A_AUTH_FLAVOR_MAX - 1) +}; + +enum { + NFSD_A_SVC_EXPORT_REQ_SEQNO =3D 1, + NFSD_A_SVC_EXPORT_REQ_CLIENT, + NFSD_A_SVC_EXPORT_REQ_PATH, + + __NFSD_A_SVC_EXPORT_REQ_MAX, + NFSD_A_SVC_EXPORT_REQ_MAX =3D (__NFSD_A_SVC_EXPORT_REQ_MAX - 1) +}; + +enum { + NFSD_A_SVC_EXPORT_SEQNO =3D 1, + NFSD_A_SVC_EXPORT_CLIENT, + NFSD_A_SVC_EXPORT_PATH, + NFSD_A_SVC_EXPORT_NEGATIVE, + NFSD_A_SVC_EXPORT_EXPIRY, + NFSD_A_SVC_EXPORT_ANON_UID, + NFSD_A_SVC_EXPORT_ANON_GID, + NFSD_A_SVC_EXPORT_FSLOCATIONS, + NFSD_A_SVC_EXPORT_UUID, + NFSD_A_SVC_EXPORT_SECINFO, + NFSD_A_SVC_EXPORT_XPRTSEC, + NFSD_A_SVC_EXPORT_FLAGS, + NFSD_A_SVC_EXPORT_FSID, + + __NFSD_A_SVC_EXPORT_MAX, + NFSD_A_SVC_EXPORT_MAX =3D (__NFSD_A_SVC_EXPORT_MAX - 1) +}; + +enum { + NFSD_A_SVC_EXPORT_REQS_REQUESTS =3D 1, + + __NFSD_A_SVC_EXPORT_REQS_MAX, + NFSD_A_SVC_EXPORT_REQS_MAX =3D (__NFSD_A_SVC_EXPORT_REQS_MAX - 1) +}; + enum { NFSD_CMD_RPC_STATUS_GET =3D 1, NFSD_CMD_THREADS_SET, @@ -91,9 +195,15 @@ enum { NFSD_CMD_LISTENER_GET, NFSD_CMD_POOL_MODE_SET, NFSD_CMD_POOL_MODE_GET, + NFSD_CMD_CACHE_NOTIFY, + NFSD_CMD_SVC_EXPORT_GET_REQS, + NFSD_CMD_SVC_EXPORT_SET_REQS, =20 __NFSD_CMD_MAX, NFSD_CMD_MAX =3D (__NFSD_CMD_MAX - 1) }; =20 +#define NFSD_MCGRP_NONE "none" +#define NFSD_MCGRP_EXPORTD "exportd" + #endif /* _UAPI_LINUX_NFSD_NETLINK_H */ diff --git a/net/sunrpc/netlink.c b/net/sunrpc/netlink.c index 41843f007c37a3ccb6480d11ec31de201c5aa5e7..3ac6b0cac5fece964f6e6591f90= d074f40e96af1 100644 --- a/net/sunrpc/netlink.c +++ b/net/sunrpc/netlink.c @@ -6,7 +6,6 @@ =20 #include #include -#include =20 #include "netlink.h" =20 @@ -22,6 +21,14 @@ const struct nla_policy sunrpc_ip_map_nl_policy[SUNRPC_A= _IP_MAP_EXPIRY + 1] =3D { [SUNRPC_A_IP_MAP_EXPIRY] =3D { .type =3D NLA_U64, }, }; =20 +const struct nla_policy sunrpc_unix_gid_nl_policy[SUNRPC_A_UNIX_GID_EXPIRY= + 1] =3D { + [SUNRPC_A_UNIX_GID_SEQNO] =3D { .type =3D NLA_U64, }, + [SUNRPC_A_UNIX_GID_UID] =3D { .type =3D NLA_U32, }, + [SUNRPC_A_UNIX_GID_GIDS] =3D { .type =3D NLA_U32, }, + [SUNRPC_A_UNIX_GID_NEGATIVE] =3D { .type =3D NLA_FLAG, }, + [SUNRPC_A_UNIX_GID_EXPIRY] =3D { .type =3D NLA_U64, }, +}; + /* SUNRPC_CMD_IP_MAP_GET_REQS - dump */ static const struct nla_policy sunrpc_ip_map_get_reqs_nl_policy[SUNRPC_A_I= P_MAP_REQS_REQUESTS + 1] =3D { [SUNRPC_A_IP_MAP_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_ip_map_nl_po= licy), @@ -32,14 +39,6 @@ static const struct nla_policy sunrpc_ip_map_set_reqs_nl= _policy[SUNRPC_A_IP_MAP_ [SUNRPC_A_IP_MAP_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_ip_map_nl_po= licy), }; =20 -const struct nla_policy sunrpc_unix_gid_nl_policy[SUNRPC_A_UNIX_GID_EXPIRY= + 1] =3D { - [SUNRPC_A_UNIX_GID_SEQNO] =3D { .type =3D NLA_U64, }, - [SUNRPC_A_UNIX_GID_UID] =3D { .type =3D NLA_U32, }, - [SUNRPC_A_UNIX_GID_GIDS] =3D { .type =3D NLA_U32, }, - [SUNRPC_A_UNIX_GID_NEGATIVE] =3D { .type =3D NLA_FLAG, }, - [SUNRPC_A_UNIX_GID_EXPIRY] =3D { .type =3D NLA_U64, }, -}; - /* SUNRPC_CMD_UNIX_GID_GET_REQS - dump */ static const struct nla_policy sunrpc_unix_gid_get_reqs_nl_policy[SUNRPC_A= _UNIX_GID_REQS_REQUESTS + 1] =3D { [SUNRPC_A_UNIX_GID_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_unix_gid_n= l_policy), diff --git a/net/sunrpc/netlink.h b/net/sunrpc/netlink.h index 16b87519a4096a72798e686dc20d2702ef329e52..2aec57d27a586e4c6b2fc65c7b4= 505b0996d9577 100644 --- a/net/sunrpc/netlink.h +++ b/net/sunrpc/netlink.h @@ -18,8 +18,7 @@ extern const struct nla_policy sunrpc_unix_gid_nl_policy[= SUNRPC_A_UNIX_GID_EXPIR =20 int sunrpc_nl_ip_map_get_reqs_dumpit(struct sk_buff *skb, struct netlink_callback *cb); -int sunrpc_nl_ip_map_set_reqs_doit(struct sk_buff *skb, - struct genl_info *info); +int sunrpc_nl_ip_map_set_reqs_doit(struct sk_buff *skb, struct genl_info *= info); int sunrpc_nl_unix_gid_get_reqs_dumpit(struct sk_buff *skb, struct netlink_callback *cb); int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *skb, --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 5889A3FA5E2; Wed, 25 Mar 2026 14:41:10 +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=1774449670; cv=none; b=mXfupiUidGUBXWxl8TOkcpo0aI8q5CmxIemHypcuj6m/+wCZCToAaukJ3fP/IPVt7U+QTMDIUxDUHjJ44zBTARne8hAs11bvMjk0XZybbLpFv0bwg+Sj09MOuBiU2gZ5jieaToW3zMYiUy/pCc8C/HHQucUKqKthAgkZE/SY4Sw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449670; c=relaxed/simple; bh=a93t/sVtm9B/uugWNXM7m8wlzfW14hQRfjR7xraeum4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SS4v2af3l5qdDSqANFfiBJPAHPUCBx5eYl1GL9eXSL5Lm87RcJx+dp3PEz15WhkfMbq3h95M0hpiK8TPDetdH1HlH56tUL+KyP4ZikRnArD9SW8mhg1kz/FaxGEc9zGfc5yyPI2/5AgX35P+2S/vkz9WRlTYElq8m3knYEkXArw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dfYh0gHQ; 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="dfYh0gHQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 54B76C19423; Wed, 25 Mar 2026 14:41:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449669; bh=a93t/sVtm9B/uugWNXM7m8wlzfW14hQRfjR7xraeum4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dfYh0gHQ5ySUMZSAyEnU3XRjrcoB2vkB3bVkwUjGNx+KZPDIBJTPUdHkJtgxsRk+6 URNGNTWgIHQyfprpOQD9hn7s5om+rN44qFyWaTrJaMoy1lZo4sOT3bixwxWRypQbVk gmV5C6g2PUOn8Gk0gGsDkvUmj1+vSs2JinnJ6JRS37wMUO/p0iSjOPTOeZ6QATb9h3 KgWLxV2vKgk2GR1iBt8yu4pzokUdl8t2Yu+fSREJXFbKaJIzrwNhtpxPyUgOUdjgB7 qI0nd2teWphlCbGjllIHthJD1VWePocguvED8cHP8xW7d0nPU95RPFYk6HzAPALtbE QbpUQOAmskUfQ== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:32 -0400 Subject: [PATCH v2 11/13] nfsd: add netlink upcall for the nfsd.fh cache Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-11-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=15170; i=jlayton@kernel.org; h=from:subject:message-id; bh=a93t/sVtm9B/uugWNXM7m8wlzfW14hQRfjR7xraeum4=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/Pvn5knBKL3TYylOJ2sRTKmHkF5FM1+6s2YQ l0P2jB778GJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz7wAKCRAADmhBGVaC FSrED/9oYb1iqdPNkM5oWNawopN/Exu9mJWaqty87uGa2DKNe+wvCzJJiT1EnNm2rc4kCBxrofL 7D/muvBexRJshtms163zWN0KFeW/eZcUcHY7qvTDwDBMuu8J7KgSnMgnD9MpluNsB+43m3w4MS2 HPgxUkwYKhWuya2sd0OaiSrxwyt5lr48fNUr8p9jfIhhKrNQliJwKh1BY98YkYtjMLSyt7daE0r lKkyQ28CPsQ3Vu/RuhDrhmJVW9RY4CH5N+LXNafCgdHg+03yvn8Ha3yI59YlwChV0JZoXYLea4o 49MGINWMLUmLr3udYl+TOJqox03jf7zN0Zr9p8XQSwMdYBNp0VDvnORahlMtT/uGyyeLEki2cK3 5avybqNBCHbrUEjiqrhKMnGmSekfkei24pCY/g7AilTH6v3huYPqwtuiUemwdQ6S6Bhnb07/iF7 SS7nHRJltBnrKdwPYEkH0K1mJzm6Efb3bM+lZ2xZjiD4TY93/DAt8vo7NEr7wiH23bynHz7gsX7 Rz/dVFWLXen2sgeDRL8XUS/e32Xi2TTcklBWUSyJ/q1fTAsE6sb6HUWZYbnba0OHJI7ZgWR65YT 1fi9LiAgLVUH5NQBL3zVDLXw9gvBFmBFDV3VbYzy7F5sTkgY8NO8QxA9IdNbsWAPAfigyRyCryQ 7aiYKGNcG3qqpPA== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add netlink-based cache upcall support for the expkey (nfsd.fh) cache, following the same pattern as the existing svc_export netlink support. Add expkey to the cache-type enum, a new expkey attribute-set with client, fsidtype, fsid, negative, expiry, and path fields, and the expkey-get-reqs / expkey-set-reqs operations to the nfsd YAML spec and generated headers. Implement nfsd_nl_expkey_get_reqs_dumpit() which snapshots pending expkey cache requests and sends each entry's seqno, client name, fsidtype, and fsid over netlink. Implement nfsd_nl_expkey_set_reqs_doit() which parses expkey cache responses from userspace (client, fsidtype, fsid, expiry, and path or negative flag) and updates the cache via svc_expkey_lookup() / svc_expkey_update(). Wire up the expkey_notify() callback in svc_expkey_cache_template so cache misses trigger NFSD_CMD_CACHE_NOTIFY multicast events with NFSD_CACHE_TYPE_EXPKEY. Signed-off-by: Jeff Layton --- Documentation/netlink/specs/nfsd.yaml | 52 ++++++- fs/nfsd/export.c | 266 ++++++++++++++++++++++++++++++= ++++ fs/nfsd/netlink.c | 34 +++++ fs/nfsd/netlink.h | 4 + include/uapi/linux/nfsd_netlink.h | 23 +++ 5 files changed, 378 insertions(+), 1 deletion(-) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index 709751502f8b56bd4b68462fa15337df5e3e035e..ae9563ca58ee0bf7373fd96d7d2= 253df411316fd 100644 --- a/Documentation/netlink/specs/nfsd.yaml +++ b/Documentation/netlink/specs/nfsd.yaml @@ -10,7 +10,7 @@ definitions: - type: flags name: cache-type - entries: [svc_export] + entries: [svc_export, expkey] - type: flags name: export-flags @@ -273,6 +273,38 @@ attribute-sets: type: nest nested-attributes: svc-export multi-attr: true + - + name: expkey + attributes: + - + name: seqno + type: u64 + - + name: client + type: string + - + name: fsidtype + type: u8 + - + name: fsid + type: binary + - + name: negative + type: flag + - + name: expiry + type: u64 + - + name: path + type: string + - + name: expkey-reqs + attributes: + - + name: requests + type: nest + nested-attributes: expkey + multi-attr: true =20 operations: list: @@ -400,6 +432,24 @@ operations: request: attributes: - requests + - + name: expkey-get-reqs + doc: Dump all pending expkey requests + attribute-set: expkey-reqs + flags: [admin-perm] + dump: + request: + attributes: + - requests + - + name: expkey-set-reqs + doc: Respond to one or more expkey requests + attribute-set: expkey-reqs + flags: [admin-perm] + do: + request: + attributes: + - requests =20 mcast-groups: list: diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index cfe542fd7b22e27a7971a1f792061767068ac439..07d40e786aa77488b27fa0e4708= 2ae5000f6f286 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -266,12 +266,18 @@ static void expkey_flush(void) mutex_unlock(&nfsd_mutex); } =20 +static int expkey_notify(struct cache_detail *cd, struct cache_head *h) +{ + return nfsd_cache_notify(cd, h, NFSD_CACHE_TYPE_EXPKEY); +} + static const struct cache_detail svc_expkey_cache_template =3D { .owner =3D THIS_MODULE, .hash_size =3D EXPKEY_HASHMAX, .name =3D "nfsd.fh", .cache_put =3D expkey_put, .cache_upcall =3D expkey_upcall, + .cache_notify =3D expkey_notify, .cache_request =3D expkey_request, .cache_parse =3D expkey_parse, .cache_show =3D expkey_show, @@ -322,6 +328,266 @@ svc_expkey_update(struct cache_detail *cd, struct svc= _expkey *new, return NULL; } =20 +/** + * nfsd_nl_expkey_get_reqs_dumpit - dump pending expkey requests + * @skb: reply buffer + * @cb: netlink metadata and command arguments + * + * Walk the expkey cache's pending request list and create a netlink + * message with a nested entry for each cache_request, containing the + * seqno, client string, fsidtype and fsid. + * + * Uses cb->args[0] as a seqno cursor for dump continuation across + * multiple netlink messages. + * + * Returns the size of the reply or a negative errno. + */ +int nfsd_nl_expkey_get_reqs_dumpit(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct nfsd_net *nn; + struct cache_detail *cd; + struct cache_head **items; + u64 *seqnos; + int cnt, i, emitted; + void *hdr; + int ret; + + nn =3D net_generic(sock_net(skb->sk), nfsd_net_id); + + mutex_lock(&nfsd_mutex); + + cd =3D nn->svc_expkey_cache; + if (!cd) { + ret =3D -ENODEV; + goto out_unlock; + } + + cnt =3D sunrpc_cache_requests_count(cd); + if (!cnt) { + ret =3D 0; + goto out_unlock; + } + + items =3D kcalloc(cnt, sizeof(*items), GFP_KERNEL); + seqnos =3D kcalloc(cnt, sizeof(*seqnos), GFP_KERNEL); + if (!items || !seqnos) { + ret =3D -ENOMEM; + goto out_alloc; + } + + cnt =3D sunrpc_cache_requests_snapshot(cd, items, seqnos, cnt, + cb->args[0]); + if (!cnt) { + ret =3D 0; + goto out_alloc; + } + + hdr =3D genlmsg_put(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, &nfsd_nl_family, + NLM_F_MULTI, NFSD_CMD_EXPKEY_GET_REQS); + if (!hdr) { + ret =3D -ENOBUFS; + goto out_put; + } + + emitted =3D 0; + for (i =3D 0; i < cnt; i++) { + struct svc_expkey *ek; + struct nlattr *nest; + + ek =3D container_of(items[i], struct svc_expkey, h); + + nest =3D nla_nest_start(skb, NFSD_A_EXPKEY_REQS_REQUESTS); + if (!nest) + break; + + if (nla_put_u64_64bit(skb, NFSD_A_EXPKEY_SEQNO, + seqnos[i], 0) || + nla_put_string(skb, NFSD_A_EXPKEY_CLIENT, + ek->ek_client->name) || + nla_put_u8(skb, NFSD_A_EXPKEY_FSIDTYPE, + ek->ek_fsidtype) || + nla_put(skb, NFSD_A_EXPKEY_FSID, + key_len(ek->ek_fsidtype), ek->ek_fsid)) { + nla_nest_cancel(skb, nest); + break; + } + + nla_nest_end(skb, nest); + cb->args[0] =3D seqnos[i]; + emitted++; + } + + if (!emitted) { + genlmsg_cancel(skb, hdr); + ret =3D -EMSGSIZE; + goto out_put; + } + + genlmsg_end(skb, hdr); + ret =3D skb->len; +out_put: + for (i =3D 0; i < cnt; i++) + cache_put(items[i], cd); +out_alloc: + kfree(seqnos); + kfree(items); +out_unlock: + mutex_unlock(&nfsd_mutex); + return ret; +} + +/** + * nfsd_nl_parse_one_expkey - parse one expkey entry from netlink + * @cd: cache_detail for the expkey cache + * @attr: nested attribute containing expkey fields + * + * Parses one expkey entry from a netlink message and updates the + * cache. Mirrors the logic in expkey_parse(). + * + * Returns 0 on success or a negative errno. + */ +static int nfsd_nl_parse_one_expkey(struct cache_detail *cd, + struct nlattr *attr) +{ + struct nlattr *tb[NFSD_A_EXPKEY_PATH + 1]; + struct auth_domain *dom =3D NULL; + struct svc_expkey key; + struct svc_expkey *ek =3D NULL; + struct timespec64 boot; + int err; + u8 fsidtype; + int fsid_len; + + err =3D nla_parse_nested(tb, NFSD_A_EXPKEY_PATH, attr, + nfsd_expkey_nl_policy, NULL); + if (err) + return err; + + /* client (required) */ + if (!tb[NFSD_A_EXPKEY_CLIENT]) + return -EINVAL; + + dom =3D auth_domain_find(nla_data(tb[NFSD_A_EXPKEY_CLIENT])); + if (!dom) + return -ENOENT; + + /* fsidtype (required) */ + if (!tb[NFSD_A_EXPKEY_FSIDTYPE]) { + err =3D -EINVAL; + goto out_dom; + } + fsidtype =3D nla_get_u8(tb[NFSD_A_EXPKEY_FSIDTYPE]); + if (key_len(fsidtype) =3D=3D 0) { + err =3D -EINVAL; + goto out_dom; + } + + /* fsid (required) */ + if (!tb[NFSD_A_EXPKEY_FSID]) { + err =3D -EINVAL; + goto out_dom; + } + fsid_len =3D nla_len(tb[NFSD_A_EXPKEY_FSID]); + if (fsid_len !=3D key_len(fsidtype)) { + err =3D -EINVAL; + goto out_dom; + } + + /* expiry (required, wallclock seconds) */ + if (!tb[NFSD_A_EXPKEY_EXPIRY]) { + err =3D -EINVAL; + goto out_dom; + } + + key.h.flags =3D 0; + getboottime64(&boot); + key.h.expiry_time =3D nla_get_u64(tb[NFSD_A_EXPKEY_EXPIRY]) - + boot.tv_sec; + key.ek_client =3D dom; + key.ek_fsidtype =3D fsidtype; + memcpy(key.ek_fsid, nla_data(tb[NFSD_A_EXPKEY_FSID]), fsid_len); + + ek =3D svc_expkey_lookup(cd, &key); + if (!ek) { + err =3D -ENOMEM; + goto out_dom; + } + + if (tb[NFSD_A_EXPKEY_NEGATIVE]) { + set_bit(CACHE_NEGATIVE, &key.h.flags); + ek =3D svc_expkey_update(cd, &key, ek); + if (ek) + trace_nfsd_expkey_update(ek, NULL); + else + err =3D -ENOMEM; + } else if (tb[NFSD_A_EXPKEY_PATH]) { + err =3D kern_path(nla_data(tb[NFSD_A_EXPKEY_PATH]), 0, + &key.ek_path); + if (err) + goto out_ek; + ek =3D svc_expkey_update(cd, &key, ek); + if (ek) + trace_nfsd_expkey_update(ek, + nla_data(tb[NFSD_A_EXPKEY_PATH])); + else + err =3D -ENOMEM; + path_put(&key.ek_path); + } else { + err =3D -EINVAL; + goto out_ek; + } + + cache_flush(); + +out_ek: + if (ek) + cache_put(&ek->h, cd); +out_dom: + auth_domain_put(dom); + return err; +} + +/** + * nfsd_nl_expkey_set_reqs_doit - respond to expkey requests + * @skb: reply buffer + * @info: netlink metadata and command arguments + * + * Parse one or more expkey cache responses from userspace and + * update the expkey cache accordingly. + * + * Returns 0 on success or a negative errno. + */ +int nfsd_nl_expkey_set_reqs_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct nfsd_net *nn; + struct cache_detail *cd; + const struct nlattr *attr; + int rem, ret =3D 0; + + nn =3D net_generic(genl_info_net(info), nfsd_net_id); + + mutex_lock(&nfsd_mutex); + + cd =3D nn->svc_expkey_cache; + if (!cd) { + ret =3D -ENODEV; + goto out_unlock; + } + + nlmsg_for_each_attr_type(attr, NFSD_A_EXPKEY_REQS_REQUESTS, + info->nlhdr, GENL_HDRLEN, rem) { + ret =3D nfsd_nl_parse_one_expkey(cd, (struct nlattr *)attr); + if (ret) + break; + } + +out_unlock: + mutex_unlock(&nfsd_mutex); + return ret; +} =20 #define EXPORT_HASHBITS 8 #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c index fb401d7302afb9e41cb074581f7b94e8ece6cf0c..394230e250a5b07fa0bb6a5b76f= 7282758e94565 100644 --- a/fs/nfsd/netlink.c +++ b/fs/nfsd/netlink.c @@ -17,6 +17,16 @@ const struct nla_policy nfsd_auth_flavor_nl_policy[NFSD_= A_AUTH_FLAVOR_FLAGS + 1] [NFSD_A_AUTH_FLAVOR_FLAGS] =3D NLA_POLICY_MASK(NLA_U32, 0x3ffff), }; =20 +const struct nla_policy nfsd_expkey_nl_policy[NFSD_A_EXPKEY_PATH + 1] =3D { + [NFSD_A_EXPKEY_SEQNO] =3D { .type =3D NLA_U64, }, + [NFSD_A_EXPKEY_CLIENT] =3D { .type =3D NLA_NUL_STRING, }, + [NFSD_A_EXPKEY_FSIDTYPE] =3D { .type =3D NLA_U8, }, + [NFSD_A_EXPKEY_FSID] =3D { .type =3D NLA_BINARY, }, + [NFSD_A_EXPKEY_NEGATIVE] =3D { .type =3D NLA_FLAG, }, + [NFSD_A_EXPKEY_EXPIRY] =3D { .type =3D NLA_U64, }, + [NFSD_A_EXPKEY_PATH] =3D { .type =3D NLA_NUL_STRING, }, +}; + const struct nla_policy nfsd_fslocation_nl_policy[NFSD_A_FSLOCATION_PATH += 1] =3D { [NFSD_A_FSLOCATION_HOST] =3D { .type =3D NLA_NUL_STRING, }, [NFSD_A_FSLOCATION_PATH] =3D { .type =3D NLA_NUL_STRING, }, @@ -88,6 +98,16 @@ static const struct nla_policy nfsd_svc_export_set_reqs_= nl_policy[NFSD_A_SVC_EXP [NFSD_A_SVC_EXPORT_REQS_REQUESTS] =3D NLA_POLICY_NESTED(nfsd_svc_export_n= l_policy), }; =20 +/* NFSD_CMD_EXPKEY_GET_REQS - dump */ +static const struct nla_policy nfsd_expkey_get_reqs_nl_policy[NFSD_A_EXPKE= Y_REQS_REQUESTS + 1] =3D { + [NFSD_A_EXPKEY_REQS_REQUESTS] =3D NLA_POLICY_NESTED(nfsd_expkey_nl_policy= ), +}; + +/* NFSD_CMD_EXPKEY_SET_REQS - do */ +static const struct nla_policy nfsd_expkey_set_reqs_nl_policy[NFSD_A_EXPKE= Y_REQS_REQUESTS + 1] =3D { + [NFSD_A_EXPKEY_REQS_REQUESTS] =3D NLA_POLICY_NESTED(nfsd_expkey_nl_policy= ), +}; + /* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] =3D { { @@ -157,6 +177,20 @@ static const struct genl_split_ops nfsd_nl_ops[] =3D { .maxattr =3D NFSD_A_SVC_EXPORT_REQS_REQUESTS, .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, + { + .cmd =3D NFSD_CMD_EXPKEY_GET_REQS, + .dumpit =3D nfsd_nl_expkey_get_reqs_dumpit, + .policy =3D nfsd_expkey_get_reqs_nl_policy, + .maxattr =3D NFSD_A_EXPKEY_REQS_REQUESTS, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + }, + { + .cmd =3D NFSD_CMD_EXPKEY_SET_REQS, + .doit =3D nfsd_nl_expkey_set_reqs_doit, + .policy =3D nfsd_expkey_set_reqs_nl_policy, + .maxattr =3D NFSD_A_EXPKEY_REQS_REQUESTS, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, }; =20 static const struct genl_multicast_group nfsd_nl_mcgrps[] =3D { diff --git a/fs/nfsd/netlink.h b/fs/nfsd/netlink.h index d6ed8d9b0bb149faa4d6493ba94972addf9c26ed..f5b3387772850692b220bbbf8a6= 6bc416b67801e 100644 --- a/fs/nfsd/netlink.h +++ b/fs/nfsd/netlink.h @@ -14,6 +14,7 @@ =20 /* Common nested types */ extern const struct nla_policy nfsd_auth_flavor_nl_policy[NFSD_A_AUTH_FLAV= OR_FLAGS + 1]; +extern const struct nla_policy nfsd_expkey_nl_policy[NFSD_A_EXPKEY_PATH + = 1]; extern const struct nla_policy nfsd_fslocation_nl_policy[NFSD_A_FSLOCATION= _PATH + 1]; extern const struct nla_policy nfsd_fslocations_nl_policy[NFSD_A_FSLOCATIO= NS_LOCATION + 1]; extern const struct nla_policy nfsd_sock_nl_policy[NFSD_A_SOCK_TRANSPORT_N= AME + 1]; @@ -34,6 +35,9 @@ int nfsd_nl_svc_export_get_reqs_dumpit(struct sk_buff *sk= b, struct netlink_callback *cb); int nfsd_nl_svc_export_set_reqs_doit(struct sk_buff *skb, struct genl_info *info); +int nfsd_nl_expkey_get_reqs_dumpit(struct sk_buff *skb, + struct netlink_callback *cb); +int nfsd_nl_expkey_set_reqs_doit(struct sk_buff *skb, struct genl_info *in= fo); =20 enum { NFSD_NLGRP_NONE, diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_ne= tlink.h index eae426e9c8e737a95181e7d7b0904b86fc35cff6..2cbd2a36f00ca38e313e95a4ccf= aa46a5c1c0df3 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -12,6 +12,7 @@ =20 enum nfsd_cache_type { NFSD_CACHE_TYPE_SVC_EXPORT =3D 1, + NFSD_CACHE_TYPE_EXPKEY =3D 2, }; =20 /* @@ -185,6 +186,26 @@ enum { NFSD_A_SVC_EXPORT_REQS_MAX =3D (__NFSD_A_SVC_EXPORT_REQS_MAX - 1) }; =20 +enum { + NFSD_A_EXPKEY_SEQNO =3D 1, + NFSD_A_EXPKEY_CLIENT, + NFSD_A_EXPKEY_FSIDTYPE, + NFSD_A_EXPKEY_FSID, + NFSD_A_EXPKEY_NEGATIVE, + NFSD_A_EXPKEY_EXPIRY, + NFSD_A_EXPKEY_PATH, + + __NFSD_A_EXPKEY_MAX, + NFSD_A_EXPKEY_MAX =3D (__NFSD_A_EXPKEY_MAX - 1) +}; + +enum { + NFSD_A_EXPKEY_REQS_REQUESTS =3D 1, + + __NFSD_A_EXPKEY_REQS_MAX, + NFSD_A_EXPKEY_REQS_MAX =3D (__NFSD_A_EXPKEY_REQS_MAX - 1) +}; + enum { NFSD_CMD_RPC_STATUS_GET =3D 1, NFSD_CMD_THREADS_SET, @@ -198,6 +219,8 @@ enum { NFSD_CMD_CACHE_NOTIFY, NFSD_CMD_SVC_EXPORT_GET_REQS, NFSD_CMD_SVC_EXPORT_SET_REQS, + NFSD_CMD_EXPKEY_GET_REQS, + NFSD_CMD_EXPKEY_SET_REQS, =20 __NFSD_CMD_MAX, NFSD_CMD_MAX =3D (__NFSD_CMD_MAX - 1) --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 C3F873FADF6; Wed, 25 Mar 2026 14:41: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=1774449671; cv=none; b=ZlDTpobPDRCCEdyi18OXq/vWBuRYxYuPAoZfiDQ842eqH/zylZArmCaNJ9Zw+DsyyAipNyiU5XL8rkRtp907bHDbP7/cpfjgM4o25Zwn6A0PesNBOpn4qTy1vFv5/J36bFRDmyFfLx+l/2QxNnTDMCuipWei7Td81YlU68Mp4uE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449671; c=relaxed/simple; bh=l00TRpXd2f1+4p+T4txcGsDt1BUsxxeKdZQhqcki53c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=W5iFXLPn+IPvjONjrsirXdMugK+9ihrKIdLaeUi21M59EpiJl5B5sE/oPqhYZwrKka0SJPPB98yeGJVYtZvcdLUMmKqKou/q+at+X48MKjWg7AtUx64kksya6kyogtuvegLS9Za8cyC/2yZZjFu4Pg+P9ZuNoauZTKmy1/b2+8A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ie1dmXq/; 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="Ie1dmXq/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1B06BC116C6; Wed, 25 Mar 2026 14:41:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449671; bh=l00TRpXd2f1+4p+T4txcGsDt1BUsxxeKdZQhqcki53c=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Ie1dmXq/eZQx/++jlkYRtT61jxPjtVAjaPie2LL2jDQC6VxaTz7AYD65e49as6RWu QG32QHSc5B7lKL/GWUG0umuaHiPgDZYi3UR8hIbHwb5N1zCq/N44VhKZ7znt3/uUu9 UA4UKfabG4rDp5WaNqohbguJBIA0lF/hHt6TUL1b3ZDROibxp8rD949ZkP7RUuHGm9 7+V+P+DvJsdtWXSamkPzd6EkTdamP2gPSOtcMR7YX+rvMrKyk0QLvNM3CUtExzzIiH Jo4up4NmZ8PIgkRiDs20lzKZ07MVjwaQS2RxgqXud1KYORO7W/7jo4GFyamJT1ZgVj FZWP/8oCW2w1Q== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:33 -0400 Subject: [PATCH v2 12/13] sunrpc: add SUNRPC_CMD_CACHE_FLUSH netlink command Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-12-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5832; i=jlayton@kernel.org; h=from:subject:message-id; bh=l00TRpXd2f1+4p+T4txcGsDt1BUsxxeKdZQhqcki53c=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpw/PwMgdB2OXJ8EfCAX4LMzVfUfVHcb59+ZG0I sXQgo/5ZTOJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCacPz8AAKCRAADmhBGVaC Fa5jD/kBwTT/CYyMO241SqrAcM1fDYerhfKh6BzpixfKT+Jhj3YAAf1n+XD3bHmIJ3B1WzAHvr7 l57ewXYb9IGXpVWcXkPYzC0W+uOAxDG0fohzhJk9lrW3tHFFCXN4xbXBfMvQLPT0kr1vieJ87Ah BMI8GWSj4/D34lkND12IiNEjPHPYg2W7CEg88NuuXC/pwEwde4cSbFdeKulKB4Mrebi55S1Hmxr UwguV4r+LBTwWhxK1sMDjP0MqmC6ZhCTJKXV+Dbkw6OBPFj8Ujc3gbjuZJHhCc21tmpiLTvp1pt mgXhfoeR7WrhT2KSkzkUMbmApi3w/D+yVGd9GI+B29JrmlrSEmkGts2gAAI8duoAxHTxYyKPaWg dt446F/TwhrkTsJdZ75JSXZweMUmmiHlnUB3dsd3wzeaGW9fPhGcAbiFwhI2Gd5L3AkUeOn8kJX ASyeh85cT5p/bjNCyprZjqdpVD7wdnaqSzY11kml6LDzAKHDkrWDqbYZ17ewqkyHUJDDlv0QPaP 95oq1NXlsx6vNGTffM9FHFs8jgUQvFpPhy6rPuUIuWqn/+SAwH8vyBDW6BQ1LW8nfKauyHgndRP oLt3XtKZy6AnEjISTq4XL27tkfCY7Nmx8H+iHfFif0OAwujPpRRSIaYA0FBViJ5uWCuworgqFWC bRdrP6FqYu86LFQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add a new SUNRPC_CMD_CACHE_FLUSH generic netlink command that allows userspace to flush the sunrpc auth caches (ip_map and unix_gid) without writing to /proc/net/rpc/*/flush. An optional SUNRPC_A_CACHE_FLUSH_MASK u32 attribute selects which caches to flush (bit 1 =3D ip_map, bit 2 =3D unix_gid). If the attribute is omitted, all sunrpc caches are flushed. This is used by exportfs to replace its /proc-based cache_flush() with a netlink equivalent, with /proc fallback for older kernels. Signed-off-by: Jeff Layton --- Documentation/netlink/specs/sunrpc_cache.yaml | 17 ++++++++++++++ include/uapi/linux/sunrpc_netlink.h | 8 +++++++ net/sunrpc/netlink.c | 12 ++++++++++ net/sunrpc/netlink.h | 1 + net/sunrpc/svcauth_unix.c | 32 +++++++++++++++++++++++= ++++ 5 files changed, 70 insertions(+) diff --git a/Documentation/netlink/specs/sunrpc_cache.yaml b/Documentation/= netlink/specs/sunrpc_cache.yaml index ed0ddb61ebcf22b6ad889b0760f8a6f470295dbd..55dabc914dbc8693e10a8765a65= 4b11021b32872 100644 --- a/Documentation/netlink/specs/sunrpc_cache.yaml +++ b/Documentation/netlink/specs/sunrpc_cache.yaml @@ -76,6 +76,14 @@ attribute-sets: type: nest nested-attributes: unix-gid multi-attr: true + - + name: cache-flush + attributes: + - + name: mask + type: u32 + enum: cache-type + enum-as-flags: true =20 operations: list: @@ -123,6 +131,15 @@ operations: request: attributes: - requests + - + name: cache-flush + doc: Flush sunrpc caches (ip_map and/or unix_gid) + attribute-set: cache-flush + flags: [admin-perm] + do: + request: + attributes: + - mask =20 mcast-groups: list: diff --git a/include/uapi/linux/sunrpc_netlink.h b/include/uapi/linux/sunrp= c_netlink.h index d71c623e92aba4566e3114cc23d0aa553cbdb885..34677f0ec2f958961f1f460c1dc= 81c8377cc5157 100644 --- a/include/uapi/linux/sunrpc_netlink.h +++ b/include/uapi/linux/sunrpc_netlink.h @@ -59,12 +59,20 @@ enum { SUNRPC_A_UNIX_GID_REQS_MAX =3D (__SUNRPC_A_UNIX_GID_REQS_MAX - 1) }; =20 +enum { + SUNRPC_A_CACHE_FLUSH_MASK =3D 1, + + __SUNRPC_A_CACHE_FLUSH_MAX, + SUNRPC_A_CACHE_FLUSH_MAX =3D (__SUNRPC_A_CACHE_FLUSH_MAX - 1) +}; + enum { SUNRPC_CMD_CACHE_NOTIFY =3D 1, SUNRPC_CMD_IP_MAP_GET_REQS, SUNRPC_CMD_IP_MAP_SET_REQS, SUNRPC_CMD_UNIX_GID_GET_REQS, SUNRPC_CMD_UNIX_GID_SET_REQS, + SUNRPC_CMD_CACHE_FLUSH, =20 __SUNRPC_CMD_MAX, SUNRPC_CMD_MAX =3D (__SUNRPC_CMD_MAX - 1) diff --git a/net/sunrpc/netlink.c b/net/sunrpc/netlink.c index 3ac6b0cac5fece964f6e6591f90d074f40e96af1..5ccf0967809c4d3cbc58fde5dd2= 0279e1ec29301 100644 --- a/net/sunrpc/netlink.c +++ b/net/sunrpc/netlink.c @@ -49,6 +49,11 @@ static const struct nla_policy sunrpc_unix_gid_set_reqs_= nl_policy[SUNRPC_A_UNIX_ [SUNRPC_A_UNIX_GID_REQS_REQUESTS] =3D NLA_POLICY_NESTED(sunrpc_unix_gid_n= l_policy), }; =20 +/* SUNRPC_CMD_CACHE_FLUSH - do */ +static const struct nla_policy sunrpc_cache_flush_nl_policy[SUNRPC_A_CACHE= _FLUSH_MASK + 1] =3D { + [SUNRPC_A_CACHE_FLUSH_MASK] =3D NLA_POLICY_MASK(NLA_U32, 0x3), +}; + /* Ops table for sunrpc */ static const struct genl_split_ops sunrpc_nl_ops[] =3D { { @@ -79,6 +84,13 @@ static const struct genl_split_ops sunrpc_nl_ops[] =3D { .maxattr =3D SUNRPC_A_UNIX_GID_REQS_REQUESTS, .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, + { + .cmd =3D SUNRPC_CMD_CACHE_FLUSH, + .doit =3D sunrpc_nl_cache_flush_doit, + .policy =3D sunrpc_cache_flush_nl_policy, + .maxattr =3D SUNRPC_A_CACHE_FLUSH_MASK, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, }; =20 static const struct genl_multicast_group sunrpc_nl_mcgrps[] =3D { diff --git a/net/sunrpc/netlink.h b/net/sunrpc/netlink.h index 2aec57d27a586e4c6b2fc65c7b4505b0996d9577..2c1012303d48bcbaad01192eca1= c306790a4522b 100644 --- a/net/sunrpc/netlink.h +++ b/net/sunrpc/netlink.h @@ -23,6 +23,7 @@ int sunrpc_nl_unix_gid_get_reqs_dumpit(struct sk_buff *sk= b, struct netlink_callback *cb); int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *skb, struct genl_info *info); +int sunrpc_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info= ); =20 enum { SUNRPC_NLGRP_NONE, diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 7703523d424617a6033fa7ab48e25728b4c14abb..64a2658faddbe6c217f548c565a= 3a434b5573a76 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -818,6 +818,38 @@ int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *s= kb, return ret; } =20 +/** + * sunrpc_nl_cache_flush_doit - flush sunrpc caches via netlink + * @skb: reply buffer + * @info: netlink metadata and command arguments + * + * Flush the ip_map and/or unix_gid caches. If SUNRPC_A_CACHE_FLUSH_MASK + * is provided, only flush the caches indicated by the bitmask (bit 1 =3D + * ip_map, bit 2 =3D unix_gid). If omitted, flush both. + * + * Return 0 on success or a negative errno. + */ +int sunrpc_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct sunrpc_net *sn; + u32 mask =3D ~0U; + + sn =3D net_generic(genl_info_net(info), sunrpc_net_id); + + if (info->attrs[SUNRPC_A_CACHE_FLUSH_MASK]) + mask =3D nla_get_u32(info->attrs[SUNRPC_A_CACHE_FLUSH_MASK]); + + if ((mask & SUNRPC_CACHE_TYPE_IP_MAP) && + sn->ip_map_cache) + cache_purge(sn->ip_map_cache); + + if ((mask & SUNRPC_CACHE_TYPE_UNIX_GID) && + sn->unix_gid_cache) + cache_purge(sn->unix_gid_cache); + + return 0; +} + static const struct cache_detail unix_gid_cache_template =3D { .owner =3D THIS_MODULE, .hash_size =3D GID_HASHMAX, --=20 2.53.0 From nobody Fri Apr 3 01:22:51 2026 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 D34623FB06A; Wed, 25 Mar 2026 14:41: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=1774449673; cv=none; b=V3FFbaPHDtq0ThJpwpaxumOd7TQVL/3R6Ix9yHiBpVrbUgocDN5gfR18P/3uKx09VS3maI2y1Ar+1f9TNG7MTX4yzdKgPc6qzkBrC9CYbbBt6+6MbUT20PD+HXnB2Wawc5zIGDWp1imK1YOhx4ajAmNJSsC7URlfKTAmvNQY/mE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774449673; c=relaxed/simple; bh=OaapqYw0nA2b3DJ3MpNZ3zm04w2f/GRhSYPxrDWpxf8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hjiWIwMv3CerIOKNDr4yTtIiXIa8tIsNi/6QgeFSmE4ClzWr4C4aE5XABr5E4WxdtgpjrAOX5NutDX7fu/WBwfwBCQTAXH586YSMNm1/EiJwHLzy/5dKxcOYL9wTbh+16HFgIv8ICotHKCAFy4P4IqB8WuO5W4nHOts+QQzjqOI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Vj0s+rtP; 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="Vj0s+rtP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D49B1C19423; Wed, 25 Mar 2026 14:41:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774449673; bh=OaapqYw0nA2b3DJ3MpNZ3zm04w2f/GRhSYPxrDWpxf8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Vj0s+rtPMV3vL8agHdWqjJLBuWc8HA/ixWUg4Ckvo7S2PZaLOdXBJRu7SFVPHq+l8 m7GDVllzFc8YHKkbY/KrjWNqehuRZuuVHB8FHmxcbKk/+hnfQISR2qwdSELQJGty/R Yx3QQ4/fvIZJXsaSJ3t2MJVf3v0JUaymMkbHg5CiCWzP3oENzyOSVheTMDMNwCEh/H 9ZqMU/1qvtAb60jXOGDS4n6qgtk9DTVXIo7Gh9c1mMQe1yUlDmfozPpkNaenCakbfF u82BkQdaIfrXSSFarvG8SO+FsadL3smAP0Vqv3NODb4L2klDcvOIJCCBrXStFGk4ua wmUQBbWwjYCLA== From: Jeff Layton Date: Wed, 25 Mar 2026 10:40:34 -0400 Subject: [PATCH v2 13/13] nfsd: add NFSD_CMD_CACHE_FLUSH netlink command Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260325-exportd-netlink-v2-13-067df016ea95@kernel.org> References: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> In-Reply-To: <20260325-exportd-netlink-v2-0-067df016ea95@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6012; i=jlayton@kernel.org; h=from:subject:message-id; bh=OaapqYw0nA2b3DJ3MpNZ3zm04w2f/GRhSYPxrDWpxf8=; b=kA0DAAoBAA5oQRlWghUByyZiAGnD8/DIvRbJMYoZ/hpZsqo8Y1cjvBiRLTw9qyngVhQNnittm YkCMwQAAQoAHRYhBEvA17JEcbKhhOr10wAOaEEZVoIVBQJpw/PwAAoJEAAOaEEZVoIVXsYP/RCj 5CkN71iWkmiV+VctbDimWOoMzhDl7CEefP9SHxcNTnjK0Kzfu+tkiqWfrPlfNcXPZC31FPRd//+ K/ct4Lgnrc4WTVIrm0MX9RjZdmi3CzdXU59n4DMt5RXvd4K875ORWgiQdlV3RJvwxxY50IVQvfB AFfl1VYFyi5sKlmZkA2q3qGKhIKlj2EBKoll4LbvZV0voCK3BN3LdTCr1zONY/MT6TgqMGOx/lu 0fk8NgaPKJQ5EIdBX9xDIxSiNR4bEzG6N3Hd1tpZvxWC6sOrakeNtZIpOPbsoim7uXpf24mEMbD 0Nmx4uUjaVs+SFf3KBmRpsTI0lVfs82kbrZm3XqIQqYumrslEahMQzHYq1lF9K91iEOfV8iIp4Y Qk/wz6Z6DtbiQo+UaCZYSwVpYb2d++uoQP3AmI3rkSQxBsQdcucr8O4JRzYXkbz++1LzOcpbMxj ESZUIx32KdgT+cvYylLewIjIf2bcrvl9vksh9RO64Qg7j4FFUHOOqDQyNVqSot69luZDleBn6FO 0+PFkIvWJdc5Ny9OYmf1KtNdwMJ9g/WsC3gMZXcTaScDAqPY1Qvcd03SNC2Fj16o1sxpgbmDm00 VtJP2sEUTfm2SivZH+MGZFXKlCMmTEaxZTbEvhpSOfd1kISRQ9MUpDa5Ey4l11iRpAq7QKobpA5 pvhu2 X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add a new NFSD_CMD_CACHE_FLUSH generic netlink command that allows userspace to flush the nfsd export caches (svc_export and expkey) without writing to /proc/net/rpc/*/flush. An optional NFSD_A_CACHE_FLUSH_MASK u32 attribute selects which caches to flush (bit 1 =3D svc_export, bit 2 =3D expkey). If the attribute is omitted, all nfsd caches are flushed. This is used by exportfs to replace its /proc-based cache_flush() with a netlink equivalent, with /proc fallback for older kernels. Signed-off-by: Jeff Layton --- Documentation/netlink/specs/nfsd.yaml | 17 +++++++++++++++++ fs/nfsd/netlink.c | 12 ++++++++++++ fs/nfsd/netlink.h | 1 + fs/nfsd/nfsctl.c | 36 +++++++++++++++++++++++++++++++= ++++ include/uapi/linux/nfsd_netlink.h | 8 ++++++++ 5 files changed, 74 insertions(+) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index ae9563ca58ee0bf7373fd96d7d2253df411316fd..f8ca70178c67d0e4bd074b86d19= dcd1514f127ff 100644 --- a/Documentation/netlink/specs/nfsd.yaml +++ b/Documentation/netlink/specs/nfsd.yaml @@ -305,6 +305,14 @@ attribute-sets: type: nest nested-attributes: expkey multi-attr: true + - + name: cache-flush + attributes: + - + name: mask + type: u32 + enum: cache-type + enum-as-flags: true =20 operations: list: @@ -450,6 +458,15 @@ operations: request: attributes: - requests + - + name: cache-flush + doc: Flush nfsd caches (svc_export and/or expkey) + attribute-set: cache-flush + flags: [admin-perm] + do: + request: + attributes: + - mask =20 mcast-groups: list: diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c index 394230e250a5b07fa0bb6a5b76f7282758e94565..30c4f8be3df98d8ae98ecddbfac= 488b5f997ab2f 100644 --- a/fs/nfsd/netlink.c +++ b/fs/nfsd/netlink.c @@ -108,6 +108,11 @@ static const struct nla_policy nfsd_expkey_set_reqs_nl= _policy[NFSD_A_EXPKEY_REQS [NFSD_A_EXPKEY_REQS_REQUESTS] =3D NLA_POLICY_NESTED(nfsd_expkey_nl_policy= ), }; =20 +/* NFSD_CMD_CACHE_FLUSH - do */ +static const struct nla_policy nfsd_cache_flush_nl_policy[NFSD_A_CACHE_FLU= SH_MASK + 1] =3D { + [NFSD_A_CACHE_FLUSH_MASK] =3D NLA_POLICY_MASK(NLA_U32, 0x3), +}; + /* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] =3D { { @@ -191,6 +196,13 @@ static const struct genl_split_ops nfsd_nl_ops[] =3D { .maxattr =3D NFSD_A_EXPKEY_REQS_REQUESTS, .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, + { + .cmd =3D NFSD_CMD_CACHE_FLUSH, + .doit =3D nfsd_nl_cache_flush_doit, + .policy =3D nfsd_cache_flush_nl_policy, + .maxattr =3D NFSD_A_CACHE_FLUSH_MASK, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, }; =20 static const struct genl_multicast_group nfsd_nl_mcgrps[] =3D { diff --git a/fs/nfsd/netlink.h b/fs/nfsd/netlink.h index f5b3387772850692b220bbbf8a66bc416b67801e..cc89732ed71bd77c1eee011dd07= f130c6909462b 100644 --- a/fs/nfsd/netlink.h +++ b/fs/nfsd/netlink.h @@ -38,6 +38,7 @@ int nfsd_nl_svc_export_set_reqs_doit(struct sk_buff *skb, int nfsd_nl_expkey_get_reqs_dumpit(struct sk_buff *skb, struct netlink_callback *cb); int nfsd_nl_expkey_set_reqs_doit(struct sk_buff *skb, struct genl_info *in= fo); +int nfsd_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info); =20 enum { NFSD_NLGRP_NONE, diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 0f236046adfd239d0f88f4ed82a14e1a41cb6abe..3241bcfc2c6ff0b3273a8164218= 0d17cf6c5b4a3 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -10,6 +10,7 @@ #include #include =20 +#include #include #include #include @@ -2215,6 +2216,41 @@ int nfsd_nl_pool_mode_get_doit(struct sk_buff *skb, = struct genl_info *info) return err; } =20 +/** + * nfsd_nl_cache_flush_doit - flush nfsd caches via netlink + * @skb: reply buffer + * @info: netlink metadata and command arguments + * + * Flush the svc_export and/or expkey caches. If NFSD_A_CACHE_FLUSH_MASK + * is provided, only flush the caches indicated by the bitmask (bit 0 =3D + * svc_export, bit 1 =3D expkey). If omitted, flush both. + * + * Return 0 on success or a negative errno. + */ +int nfsd_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct net *net =3D genl_info_net(info); + struct nfsd_net *nn =3D net_generic(net, nfsd_net_id); + u32 mask =3D ~0U; + + if (info->attrs[NFSD_A_CACHE_FLUSH_MASK]) + mask =3D nla_get_u32(info->attrs[NFSD_A_CACHE_FLUSH_MASK]); + + mutex_lock(&nfsd_mutex); + + if ((mask & NFSD_CACHE_TYPE_SVC_EXPORT) && + nn->svc_export_cache) + cache_purge(nn->svc_export_cache); + + if ((mask & NFSD_CACHE_TYPE_EXPKEY) && + nn->svc_expkey_cache) + cache_purge(nn->svc_expkey_cache); + + mutex_unlock(&nfsd_mutex); + + return 0; +} + int nfsd_cache_notify(struct cache_detail *cd, struct cache_head *h, u32 c= ache_type) { struct genlmsghdr *hdr; diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_ne= tlink.h index 2cbd2a36f00ca38e313e95a4ccfaa46a5c1c0df3..2d708d24cbd23770f800fa7e52b= 351886aec785c 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -206,6 +206,13 @@ enum { NFSD_A_EXPKEY_REQS_MAX =3D (__NFSD_A_EXPKEY_REQS_MAX - 1) }; =20 +enum { + NFSD_A_CACHE_FLUSH_MASK =3D 1, + + __NFSD_A_CACHE_FLUSH_MAX, + NFSD_A_CACHE_FLUSH_MAX =3D (__NFSD_A_CACHE_FLUSH_MAX - 1) +}; + enum { NFSD_CMD_RPC_STATUS_GET =3D 1, NFSD_CMD_THREADS_SET, @@ -221,6 +228,7 @@ enum { NFSD_CMD_SVC_EXPORT_SET_REQS, NFSD_CMD_EXPKEY_GET_REQS, NFSD_CMD_EXPKEY_SET_REQS, + NFSD_CMD_CACHE_FLUSH, =20 __NFSD_CMD_MAX, NFSD_CMD_MAX =3D (__NFSD_CMD_MAX - 1) --=20 2.53.0