From nobody Tue Apr 7 02:54:32 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 A332939F183; Mon, 16 Mar 2026 15:15:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674112; cv=none; b=fOd73TVCHYSiwrKsrUVRhHfYnxAyWSt8bHj4guQ58/Ixan2hCX6WRNRy7p/ll5kBGHQXalt7PldTncCuLe2toqa0mkbYblQrA5hnDfeBrJxUMCs2kMkfAjP1+wnS58+ERxIHmErb+MlW08pg45jq/COxRSjMdKCBuKLKl60zKgc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674112; c=relaxed/simple; bh=N3IH110vSVveR9UotqARZCtiLBniRTymPztXiHOEEzM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rlyxOdCitzQ3dR1rGAU9xTRDeyFa+QEuQe18fmk+8XYAoXePYNjXr6NxZPtIhCqVXiHdI4guKmmvEopXsrstKANEAdhsKjLO2Hou4EfjMVNi5JncUVf5mkr3ia+6SZPwgw+D71G1Ta1tpG44C6nw0Ia83dTq932x/z4/koVP5Q4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EdfpoFsK; 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="EdfpoFsK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A3EEEC2BC87; Mon, 16 Mar 2026 15:15:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674112; bh=N3IH110vSVveR9UotqARZCtiLBniRTymPztXiHOEEzM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EdfpoFsKjvD0gAz8U869cdsqNUh8O1Lod+4QqT0CaRbZEIa8B7NFAE37gL8NpNQxx ros2MstF/Dkk2oHmEGcHiyxJaCQEf3bUnUv9Npx0ooMFGjg76rl3kL9m/O1fc78ThM fG0EzE5h1G0Q6ppK6JSgUanrw3JJqDhC6rdCKF/v2y4pkB/eDQqtlmpa0xUQvOdX7D 9KtVB///Pik+xBArd+ahBUwQ1UOPQevQk/cOX6ei16+CKIf/4e9w267Ckg7axEHT85 qfXDRKt9DaOW/+rEPYwxX8jLKjPerIoZTBquujYXm5BptSPbL7pW7r+vQgLyF7+h3n lEgVbGxAwDQrw== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:35 -0400 Subject: [PATCH 01/14] 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: <20260316-exportd-netlink-v1-1-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@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/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB56LRrKbhNqVJ8OdfCCgaPqj9zW4G5AQfRxv Fq3ZAvMuGOJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgeegAKCRAADmhBGVaC FcZhD/sFkyyYU55oTQhvjzlnwWt7soz+d5CmTIzVOyBv0Oy1k+cluI3R78oC9Wv9TVSmHOhqjaA dmElHoXkY1t/WmGGeom+TMdURoIe4icj7xQ5cklbvv9+UVm4hkRrIFx++HNQEpjaMuCcqpEtQew BoEN99pd21qe5Dni3+xmEK4e1eW2UoKtUsb4X/JkOlgBwIP/V4o18MnLp7HW8aMXT1FM1cgf2eN OqEsRGhQhJnBHSc7uiDsKMGv/QVWEjBCUd4kdZGh19xZ4gXj6M6er2sDNkR3PHjQD/VgoY61/+a vQi+R9SmJmsuESlZegrmeRi30yKNfbg0GEWPqX0QbGMYEep3WN6Vh6emIvMhkbIlt7cKAMOsY/N jqWlpUR/bFMnOzhMSLrFl7C91p3MtyKvQsaaGAFLX41BGSpkLl5YdjGY/lBn+bLYvBnT0oYZQ98 0jaFrGi/EDLrbGLYAwEjCPUL0QYYPub1Y9oSK0sMPlu8Ab+1wljFoJ6PbPcjJ0S9B55/NRPhLDv KM01PcWlNd6OF5yLqRfEUMMlDcr5+NW3yP6XGMEP8ahi9RZDoukjbo42U0IZ1fBkXMSZNreB8LA IzzekpAjyanu7kwOQHpC+EX3+EcqbcKlWtOgx+AHX95RYfaY/+lwYt2iFXVawng+5ZdOlAFcZPe UH28BDJesoGO91g== 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 Tue Apr 7 02:54:32 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 C96513A0B24; Mon, 16 Mar 2026 15:15: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=1773674113; cv=none; b=hilkBpyeFXH67/PVI+dGqAlElKGyWzetGPBpcuWvB1JFDvh08IsC9abti600kBcX44ill1fOqHJW8traeTtpURu4/XFujB753OZCk54upabRlY6V9/q8y5HyIBWSOuvx9GU2UlZSrdMNlFyel6wXp4nco92cbUpNwwei8SZ974I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674113; c=relaxed/simple; bh=NoO6ZhN61vrVI769RdauWaqike+0l8sHT/NIJRC45ZA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rB1XigGO4fcVt8+T6WNh/U4gSHV6ejQ09AMfc+xzrmh9qyZyzSf6dzaDln4ceP3sqzuUr0nmLMpMO2B2dtvmp/fktt4gelHLsfU5rL0Az+yUtLYrg5SI4OXU5MY9GRc43NpGZin31iLSl733Avz5L/E96GM8vAj7Ywh/XjacZTk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OVkc5eZX; 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="OVkc5eZX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BEDEDC2BCB0; Mon, 16 Mar 2026 15:15:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674113; bh=NoO6ZhN61vrVI769RdauWaqike+0l8sHT/NIJRC45ZA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=OVkc5eZX8Qpw2W8bs8l9ZOXp82/VUvLYB8GBJ28yWYePR/sgllaVNw3MsEa3fLlNn PJ3Ro9AcGumMDRMPRqaE/dBleHXDJ2jmTPDrJeNRF7Nxf/KzgUlBN92GI5g/Wp78lm IHqbue+HhjYX1h7fOLVlxqzlyU610GLzKESJzgYS8UGccJcAqmwhaDiKaTQVRXckqj OHpGKw9SKAGNaEAx8XZQBd1vloCqFMBNf+ZvooL6ZI84nz092D99DKwMpEDuAC5OHp tkSVVyCkhkV6a5uumNQS9Kuccghe2MfRZTWKmCE4YFxJGgYXXu1zGWPKAdO8cJ6TkM 10d/mRtBoLW/g== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:36 -0400 Subject: [PATCH 02/14] 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: <20260316-exportd-netlink-v1-2-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@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=NoO6ZhN61vrVI769RdauWaqike+0l8sHT/NIJRC45ZA=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB57/hehqqrJdLZN83YthvxBCLSUSigaK6OhG 1L3rg0Wq5KJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgeewAKCRAADmhBGVaC FXE8EACuwMF15qrjMbRPZZj/vqbISL7xnS47Ki+j0EHBEPDkBjJIz4CB+6BkvBiZXy5w2/ov+7g LhvpXkz22Wrd/5bi7vH0ep2HHOn74h73l+tzyhKyEK8BO4s+dPTS1dplbQKRnN3y364Rr6WR4q7 Yknz6nhTfziTaKsGXtziRF5VduDPnP21cFk24dx2gOjHLj+lAvVY0zQPCVQ34Ov4tuf2FwTT0C9 CD8vJ5c+FxLnb40yh87VTZYkDULngBewpIaWI6McTgEKDJW2bwdpA9gLjnDeIbl9bEzjs70nwH1 JF9+NFCiB7BBtp9baD7xAvd9RsiutVQYGMvdWaQjDDUm4JvtBrvLQgojLbuIpbfxQc7udyTBOrF Dcor4tkuJ6FeWlLrMV3Wm+qnpnrheJmz5pDUTcH0GBh54IWd8axjRYgf9PVtVDJNNWSeL3ByO++ xcnMZwFLu0NhQ+Ioiw5pr/MDJmNZ7BBWbmbPm4W8MC0MTvEmiWN4X9RKHzxIgXPc720hS1ystqh Q3ZPXit5LEu7PswJHhWKP4nbrmoXDVvaHD5RfLeC6oDMRC5iiEjKyqD2PzLdZzj/2orqTe/NtGJ jsnkXxg/LM1bRExn0B9iO6K3cx+71TzSO3AGVZHoB9Yxo3W4V5w1fdcae19+S6k9VaV6GqEk/Cm fnoRab9qJmhjUVA== 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 d5941cc24303d1a80a974a4625a0b91d36da5d3f..5553a1182c9b8d0d9c8b2be9e9b= 1bed5bfa58057 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1247,13 +1247,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) @@ -1263,7 +1263,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 Tue Apr 7 02:54:32 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 278D53A0E80; Mon, 16 Mar 2026 15:15:14 +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=1773674115; cv=none; b=HO2yGOeXobmDtkR13OMflMRik4efngPKt45cDVw8vS7C7uNVj6jxr/jcam0CfgFjLkD50P+9lm0pMR/+Gm7DLo5nPlSQEa5xIKlxoG837WXf1s+adSRcR9cwYkUDGkWFSSoNG/UldabrnDou3Byigfle/jW9Gz3MJvPY3JHDgy0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674115; c=relaxed/simple; bh=zt2/sd0q9/IbNJ/McsmnmQOqytwxOWzYyjmVxUWCOTg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uRUgYGLYA72JNquBwb48p+M/65/LsKMq6D5lo8hW59FlbLTyyvImbNXnmv0Sqf0qSAaZK0bfBq7vGwCMYKFFYxEeCCuBsbXxZz5ImnUcbN+jj8yBCHwAbxi/So5vuF/YO16jBgnfJnH48RVzTqa5SanpQHXJCu5ysY+y3O3R1uI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nJ7rGU+k; 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="nJ7rGU+k" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DB467C19425; Mon, 16 Mar 2026 15:15:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674114; bh=zt2/sd0q9/IbNJ/McsmnmQOqytwxOWzYyjmVxUWCOTg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=nJ7rGU+k4LrBVsBrLjfECqHKESvwMyMiJZjUO9HseahPvgZl/hIttvEM8lON1scen sJhdqGEfDmxuHykKILXNL+sIEmq0NoT6Ij4VFgBvxEgfsxnWJTiB2wctMA5rbDX7+1 enbtvNG+Gv/itTSbv1VTJ+LzOn5sgFdqnUEPxAUi7tVYqKt/hk4Pqi3cPVZcm19DRK Y1BXgQft9koTk0HsRJDf2QgOCA6ECA8MhgpOZ0Wx9SqHpCMln1sJYfJlZhOARq28Hj NsACova4XxTolgODbbSq+9ET4LYBZuy4lunzTMCoLyg0tos7yjXgLzfUJDfuGKC0TW 5tyJUwtqAh52w== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:37 -0400 Subject: [PATCH 03/14] 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: <20260316-exportd-netlink-v1-3-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@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=zt2/sd0q9/IbNJ/McsmnmQOqytwxOWzYyjmVxUWCOTg=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB57+kbFQkQ3C7Pi5mFFn7vMhq/xLT9dvlGI5 US3sYPhiquJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgeewAKCRAADmhBGVaC FR+uD/0YoV/R4gu4rAAbNl0GXIyuLqG9S0eQUFI8AfwixNN2Cf540AEQVcMFYR+RSWFdcEgmlUq 6HQqoszrCLlwjmL0wTXznEs7SmqoI33kiWORWM5X23cRkK6rkMI4JOeXrrUhofInjsJTZKkelau BtIm7RAcmkiU0BpH56t3CnofwW6XbdCq18lz6dUIvfI2lBRjrre0CjNZfzOL3s3LCWkrf3hg5mT JOarikZi6014KxEjfur/96pOeRGYQR3WoAYRTkiNc6NeZER0XuWwtcqcyrsBI0nvzzuIkIGrSvq g79+yne2f6DGhJiFdzf6YHyn0tkWw1TVaXFz9DRoV1DT9wyZnWloaKgJdTxVY2swe1wZWDzmrj1 7BZ791OZJrlcJKcJf7VLI6J2j1CevplcUYtYsz/QAQivymYZK5MN8xazGk/3bB3Ze4BQsjEojyU BRwDpSRwSNTHyC5j5TKtLcu1Cwelq49I+IfIypyVkCLQeQzst2sOF7kfnaej5pHw2yOrhhoBa+L d//KsBwCb0OYxWJgfpF5eLoPwZSXX0PIqWwccZhvvSqr5vQ/ZnjKI0hNbxON4yD+MxfW2Kz3aPe M4Q0M3Nme9uyFGc/HfsFYh+a2PqF9/zCoaEYL90edICZvDkTQQqIeslbIRz7y5xwVBHDdOD4EPl i3FhxyN8hBBkPSw== 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 5553a1182c9b8d0d9c8b2be9e9b1bed5bfa58057..5e36f6404400aea5700d0893c00= b6d69c1ec128e 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1255,8 +1255,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); @@ -1265,7 +1265,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 Tue Apr 7 02:54:32 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 2969939FCAF; Mon, 16 Mar 2026 15:15:15 +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=1773674116; cv=none; b=BI9eE3hd/u0i3gI8PfIgVI4JLXrRA54POiAGHs4V5ocONWudgCINvWT70Y4fNtATsSRVt8hYtraPXFHhOy/OlJmY3sOeclXd39pvjdmSoq/EMkLp1rTzsw6gu07HNK2pT2p2HU5kzFGtbq7jETfqQXhWMUXpDiZS2qR/tniigVU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674116; c=relaxed/simple; bh=oeDUirb5QsxFfctXdbfNXappHx0QW4l5k81kduxUPCs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Jm15vxAn4FXL5jb946AOE/MwupQnvufZ1Q/EioAyKFjfz0qvgefOYwcw23+/+akh2lp79Ug0w/T61l0sjp8biVUBjmqaANOWL2Rbn5Wxe0not1kWBSBjhZzs1/U0terklWegB0qnqgXp4wLY1HFm5n1IN/zVOlFeSXPsOGjKD3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qJf7bwd1; 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="qJf7bwd1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 019A3C19421; Mon, 16 Mar 2026 15:15:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674115; bh=oeDUirb5QsxFfctXdbfNXappHx0QW4l5k81kduxUPCs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qJf7bwd1PNWYwmZGHDZ1nfwiLqpl/+ycN5OTtgMBpbFZD3lkrlUx/ynayAAp2mUj7 3iDcpd0aDbxdX5DQRXVxuGvdSGHuZBvJ5OzVFkywqofS0Lyd6AWdSw/f+7P1BTnAjm ydLlKZN+NdX0HXi9PO+GSDsN2eYfKlX9ZEpwq6dnY9B2xrOVT5JCYE7sKin6EwIhCB UDPBr34/eOzWyeUODAf9F/3x79O0cBPxv4KSZCLLaRLqWC/GkOIR1JsdBowhSN4LkV gV6Vz7vOV9ilpKIAxOgMjLdBNDSZomtofDz+i/4WQxkzA6VJMd5tzMY0GUJ73O3J8u kKUc2uqi2e3Qg== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:38 -0400 Subject: [PATCH 04/14] 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: <20260316-exportd-netlink-v1-4-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1048; i=jlayton@kernel.org; h=from:subject:message-id; bh=oeDUirb5QsxFfctXdbfNXappHx0QW4l5k81kduxUPCs=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB57jy0B1ah7altKkzsgZGIf3x7vny8fUR4VU FP2MbzwMV2JAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgeewAKCRAADmhBGVaC FY+QD/0TeMGlfxugPjljX9MmLFU2/iHKs5qzhPxWHVikdSmhT8Gma7zheHBqV9RNh20b780FdYI 0qgpO2Q96Sms0NCvZ0ErTcT3+F3oQ3Ln9H1PXmcE3oXba1HfMiTZHSKDNmFEYLT+36LmFvdtwEX PYlv5238avPrae/ZiAGDMgC0LQaNRnDQb0SQXqNeDcMvFQjG1ZTNN6NQXVwUWONJHguEb4yPD2H 28tvfOMXVl1Sk2w4M0ePlvZnedOk7XX4L0i/Ie5b7Ni6C2+WzjGVsJPwlhIUviAb6Cv+0R8btea LUP+xB05fumUrptMkRaxE8MU0n3bIfntTwQrZ+1HON+lRg76vyqkq9/enEzn5seDuA5KfILljiC WZ7f9aqke6GgOpy21B8kzhGcJX5EJzE+BBw4XmnSNdFJiTiXq+j8g2FZ5dCYQUpgUJaa3Od1FfC oL4qsxWfQbK4sddp1C1zLWvs/gg5mChV2c6LvYAkZZ8ZFykW8dt9dNNsnXPgwxDbLkcgrBK2ZlA DeaN2MOROd/gRwd1SB0Q/6PqAuwCHhYyTdOek+dke1ZNBtRQ1qeZD+2zbg1g/UD2MExsdSXVldR jdU9bkWNAiHs+Ns+dBPA+N42C/6ZYrSvEnn4APVwXp4iCQF6Dn+TsdvZWYdbk9oKE9uG94c8Ukw uc5yKcsZ1ERQtsQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 ...since it will also handle netlink upcalls. Signed-off-by: Jeff Layton --- net/sunrpc/cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 5e36f6404400aea5700d0893c00b6d69c1ec128e..7081b6e0e9090d2ba7da68c1f36= b4c170fb228cb 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1206,7 +1206,7 @@ static bool cache_listeners_exist(struct cache_detail= *detail) * * 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; @@ -1251,7 +1251,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 Tue Apr 7 02:54:32 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 225A73A1A3F; Mon, 16 Mar 2026 15:15:17 +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=1773674117; cv=none; b=RBj1I9Oyf2kWcir2cJM2stP49U1uJMmSxz7ZiGTnAOK5lamuSTjn0Bxm6sdyBr7xqN45XoAkjUzXLgia6kkjLR9s7FwgDz4/zGdGwePExj3dp5iyalw4El9YcL/Boup5WVNgy4Pu6KL6tJ6ka3CzWZeYXzGDPMUuk1TtEi8t5Zc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674117; c=relaxed/simple; bh=GBY2gRkFAZM9XwvOjqnzxklHseW2P36+SjSSJPoy2cw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jSJ8TjBMLnXPghgwlkbed9bkpXiVgAVlEpcrX0aj3FEJ4BADkBiv4E3FqoqxNU9/7mKj9Zdhe5/SaAyaQnvuXCHhWUSTgoqeKt/lCc9hg4LK2GLZ1XblAGPzaKFhTaiyxIIQ2aeBuya/Vbh0V9ibsoukvVgOfOqrK5ayrcmCcMY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cB5kROMl; 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="cB5kROMl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1EF00C2BCB2; Mon, 16 Mar 2026 15:15:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674117; bh=GBY2gRkFAZM9XwvOjqnzxklHseW2P36+SjSSJPoy2cw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cB5kROMlU7UOftvc/9KDCVdXnwdRebVy/I0JEc+ZyQbRcktrQ+F9r5Aj9hYx7P6RR 6CUppoQANwe46j6a6jp9YG5WosIG4UyKpmMMPJy/wpVIf5kfnFRSmvkGgpmL39CTLK JXsDBW0Ck7OX1cRp0cy/UvwgRrjvCwJjKr5EWUc1IgNoTRTPwB2D3VqbSZi1HMVYzD 2MINfsvCImj8xwlHV/VdJ1Z5OSBlRPM0OJgrOWT36x45sNGPFtZFlBM8065XwqQU+o v1KIssukD0giIcurn8MEAzVbLOHrmECsNEUJJZlXO70kyJfhLgmH3V/POTD6waeMnr tuJH1vylv1yxQ== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:39 -0400 Subject: [PATCH 05/14] 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: <20260316-exportd-netlink-v1-5-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1715; i=jlayton@kernel.org; h=from:subject:message-id; bh=GBY2gRkFAZM9XwvOjqnzxklHseW2P36+SjSSJPoy2cw=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB574PtozW+tMf3NB2jAg9fVS9f2DLJNG0P6c 006MGdR0EGJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgeewAKCRAADmhBGVaC FZdlEACFwAc86uZLqNE8pJA6RscNRlFFg++4gjJLNLyvq+cwKsKCusXsRYD5VCXA0F+iTUItHNk QeHl4TN2xTjM7dBFAtdXqUyozlQ2zenw9RQsmkTGhLj+8fTfH/Vbgqx34M+KLRzUQKstnvQXpHt DEAizU8PqjYsSPO+wAorfkx7I4LEINyQuC4bY5IU9XJq65zBz+Q6bKZJedkCLDO6vnWwpkIsB4P s+9zVQ/dgFQcCBx139ZVgyYOeS+3V9sObZdKADsPk96a+QJuo0jiO/Hy8dJLAL6hSDI43HZK76C ZtHBAW8mMIdUpHbs1PrN6yNq7O7zI9vJjZ4m2Eddq7eMch5O3wU1tFk0MzvaC9DwR33zrzVNGjT Ib+BIrBDRabxG9KaLrE91UNzBKbNOyjnZuw+UMW1GhaQr3KTtmHc6+uuaS4r3mHYE9yYqg3zQZM U605kWhsnNsoE5VwnGPT/lRedizolpaaZ5c9sS8JAbrdr5ZrVCWVO4s87TYdVW5fOom5rRc3Yjn GSxoepO0fdK3+YpZonDKqLRgdpbTcFXlx5c7M/Nbj48sRv4Ul8A+yO/olceb4aQwSgHogX4mK+i rjFUjaADON+0VJXNDR2fuTW/RMIKLC7lxCXGRTNXVmcGz+3xCm3Ut1e84IR3d22qfFWzyXojhaN 7wa4C0ng4Dps/iQ== 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 | 3 +++ 2 files changed, 6 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 7081b6e0e9090d2ba7da68c1f36b4c170fb228cb..819f12add8f26562fdc6aaa200f= 55dec0180bfbc 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -33,6 +33,7 @@ #include #include #include +#include #include =20 #include "netns.h" @@ -1239,6 +1240,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 (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 Tue Apr 7 02:54:32 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 7B11A3A1CFE; Mon, 16 Mar 2026 15:15:18 +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=1773674118; cv=none; b=C3RB5H39wRscUQ/Rz4zW/nyfchfyCzLxfALRB8T9PAEihjrMkjmOH8IqAL2dgW14jDkUQSmiD0n6K0KptV7jZEyP/94GBncbR9TWbthxZz/QMxS50sH98MC22ilWMOFCsRPdM/9pVhLPAjUjNoYeeAUosS7whkKclSXcVXw4aLQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674118; c=relaxed/simple; bh=X0uUzaqlrvWI3pq3RSR2Kt1DBj/aWQDwAozoQb51la8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TGBjS3Wh+lapxU2pfqsOKQ8vYTvYYY8JtT/xPQS1dXk/T9cZA0aoJqfde259OE+05QleTffjS1nSiiC42weepQ7E/7ClegqbuB6OXI7mNVqnPbuEbVmQSmEjicxr4PDnSBZZgEUkRD1hmmlqMI3FaOUpQJ/AQcdAO1pFr9cns0Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=K5Gxm2XC; 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="K5Gxm2XC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 393E3C19425; Mon, 16 Mar 2026 15:15:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674118; bh=X0uUzaqlrvWI3pq3RSR2Kt1DBj/aWQDwAozoQb51la8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=K5Gxm2XCC+frGkQreeJNP0RDEHgVY/TP2V7A7FTYrdOWk6NARJ8UITQD2y5WgIBcH PqeQSvGE2tZM0IepjyW7DKH+jAubfPD2GTM+ppaO2PKIFOv4uzOQGannvp2LCKQkvQ /Em4rcBL1Y3zRF8jCPSkzYzJj1J+rPjeUiHVj/c1POtVf/Ut9fI92uBgUqWcYJ0xvy DYwOOmTgyEeRDVrjmCqX9JRyKDGAm0TWs679DCUsEdezr3eAgEyXY9Cxpa+EFoeBi3 +MRZbXupSee6KWuL2QE8hc+JbAVeIap4LsPT/slHPlsSSHJGZxL72asUwB/o8/Eipa pF0N3uRl8cZLA== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:40 -0400 Subject: [PATCH 06/14] 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: <20260316-exportd-netlink-v1-6-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3688; i=jlayton@kernel.org; h=from:subject:message-id; bh=X0uUzaqlrvWI3pq3RSR2Kt1DBj/aWQDwAozoQb51la8=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB58Z1BDol0s8jn1EM0GW5gC1McET0++OR+vQ jqRLgGizWWJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefAAKCRAADmhBGVaC FRiSD/9+ivJxJwlW+Nh54iimrPD+ZoYpdccLcPCs5eUi9HnCzaaAiqi62DNeqbaFR3lxB3/9ZUg 5fQH0dtB36nS/wFnYYdK7PLAfgEVRFKhOG+Rc2oasThDeiP53iMlE9WYtPqIpVmHbaYwVOC/wjn QPlKb5lM40gHKAaM4XrVXYD8mZ+VOubofqBmppf7oTez2pEmIq38jPVhqgr9CjwL50oSPPcEGAh bnk4RKGvCy32xsJM8GDmvC5+j0tgFYE4L3BM4Ui43W4kgA+2z80jBe9g3cJlTUbKtaaom7WcoSc S4MSwQMIPNdN6GDFZIqNVQ2D9Cf+fqClDERUF1GuRtmgnR5VUcQZXLOHQLlWd2RsPd0jhWwD+Xc OG4PAWm3GME5y5waXFR4MubY19fkkDWJrqzQqZcGQwJrIHRXMaUpvm7DsjwtsV17rCs0/WktdbE 6DZnY7gDnopWSP7pPz2qpWzrPmbkAjnxc1rXTa30SSrn287H23AoZ7+fz3IG+XzU91DsgLdpBBD r29TsJlstZNIjL1ly0HsWmzrd7g9My0vhETDXI8gVB9+vYU4sPApVTbtczxuXGtEXme7Uyjxib6 zNRUyI2lNarvWosL/fzeYDdzyoEqsicrShS8ROi/yye8c3UIVRvtYvrgWFm4fyAr8zuuCvXa5hA u9lqC2d7cHfA4ew== 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 | 5 ++++ net/sunrpc/cache.c | 57 ++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 62 insertions(+) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index c358151c23950ab48e83991c6138bb7d0e049ace..343f0fb675d761e019989e47e03= 645484e0aa30f 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -251,6 +251,11 @@ 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); + /* 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 819f12add8f26562fdc6aaa200f55dec0180bfbc..2a78560edee5ca07be0fce90f87= ce43a19df245f 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1906,3 +1906,60 @@ 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 + * + * 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) +{ + 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; + 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 Tue Apr 7 02:54:32 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 676B63A0B3E; Mon, 16 Mar 2026 15:15:19 +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=1773674119; cv=none; b=NSYKFpH+Pa7pBCm/qk+YXZBt0VHwfGQoLLwDXqZ3F+Pf0ws1FLImJYWCJ3t4C0inyjgKpGoY1T/FT284QyyYc3ooEpmGoL+lztr0MZajULOtF4LTyUgkjxr3aJ85xrsUayCf3Wh/f4gJlfggSC18Pq6wkC5i+F5ZrNHJ18V4zNs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674119; c=relaxed/simple; bh=NMqyCBf4sgp+Ub5LuggG1DdHfY4oQfmiKnZO0y5QASs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Bcgt/HTZKdmHBgKhw3WDrHlGJfi6otHnio3Wii6YKTlNCk6X92jV4zk5v24G2H4JYaVvL/Cg5rd6RzvSNYcXsUmIS0+GRet8ATHT3A8vw6KQkodPThi1tLWtmgw2BDmGy6vpKXeHCKKTO1mW7WzVGJqNAz57DX70wIxlKK9RRbA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qrvIsVv8; 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="qrvIsVv8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 53521C2BC87; Mon, 16 Mar 2026 15:15:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674119; bh=NMqyCBf4sgp+Ub5LuggG1DdHfY4oQfmiKnZO0y5QASs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qrvIsVv8/S1QGAeTi5kqSJvTAtsQbS9DlA7jtSXWtBCJ4gSBprYxRGPhth2/vkYeZ U2RSMqHPOmmCqe5+NIyUj4FbcO3D96pJwX+nsJd5nZ40KCXDQzlH5qW/ZLjxnmLtlZ lzgg/e1s7LTu5z59CNE7BEKdfnKVl9GwB+O3lw7D4bnpP//N672aOlKo23OcQ2F6nO PeQyoP0D5LOJf0DRCBs/i9qKRUyPpytgjtZY5fgq2ce3EOsWejINDnfzftuZwJdAxL JQdln2JASyq4tRIvDRaTj76Df5kb4ACGNZXIuadoyxFCz4jzzd4i8tRG+Jxk9mOc+H JYFSU7xjzE5bg== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:41 -0400 Subject: [PATCH 07/14] 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: <20260316-exportd-netlink-v1-7-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=8890; i=jlayton@kernel.org; h=from:subject:message-id; bh=NMqyCBf4sgp+Ub5LuggG1DdHfY4oQfmiKnZO0y5QASs=; b=owEBbAKT/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB58bNaMr7/hf+dYu7EFzEiX/9urCCqM9YdgQ //FPhsom8uJAjIEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefAAKCRAADmhBGVaC FUsSD/YwFKR95zxttQckmbrCzzVDnws/iWcyLyOP65nIyUDWzyi+HV0EJ7iMen35RvNjNeMGhdr WLEvH9hR4ePvNpBp/Z82FtrCjBDnI1f82Pn0xwAJZfHP+45mbhEYKcuDUbTtm/NFL44xdiHa5wx 412CZKa7bIADNp7Nc5mVh6NNKXCZ6cbNpK3fpQqU1lU/polulwYCPs9u9luw+ctxgMQRU2y6TMZ iIsBOj/AyG90tA+H46gS4gLnSk0jhF9U8ZWl6B4HuH7xBKPEewj7wGgEcszsEZ9pT/4dq09VPII aZ0Jr1Ak13/RvCPPTrRESZ7sOMh4JzpC3/ZA1OXXFc/c3O8QneLFpMfd8mQeh0PeQWyVxwjc2Z5 JQS5VVs1xG/eB/L4vsU3G5/ZWAjAhE7Rn18RzEKklcb7nH1/CbJWfLv0Oyv+WdlQhw4PhiGHjuI EAvVirMD1j262EZc8qYN8sZtS60itAPfGcip+Wh/ZVZr57wIfB62qQr2Mern3qbReSHUt+oh/hL 6S2/PXvnwu/TJOOYxQhMxPhf9U1RcUpnQfJ40mv+2lJ/j1UyAbKSZsOwDRxBRlvs3NxQI03eYgM 5zhiWcthGGYWgX5fVOgIukzhpfFydfvZlnWmIJ2SCQnsVMmtsv/W9L20bLZYdkTc7lshNVQH+Nr 2CSrY5X9m9lW1 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() which mirrors the nfsd_cache_notify() pattern: check for listeners on the exportd multicast group, build and send SUNRPC_CMD_CACHE_NOTIFY 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 ++++++++++++++++ fs/nfsd/netlink.c | 2 +- include/uapi/linux/sunrpc_netlink.h | 35 ++++++++++++++ net/sunrpc/Makefile | 2 +- net/sunrpc/netlink.c | 66 +++++++++++++++++++++++= ++++ net/sunrpc/netlink.h | 25 ++++++++++ net/sunrpc/sunrpc_syms.c | 10 ++++ 7 files changed, 178 insertions(+), 2 deletions(-) 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/fs/nfsd/netlink.c b/fs/nfsd/netlink.c index 4e08c1a6b3943cda5b44c2b64bcf3a00173a08db..81c943345d13db849483bf0d677= 3458115ff0134 100644 --- a/fs/nfsd/netlink.c +++ b/fs/nfsd/netlink.c @@ -59,7 +59,7 @@ static const struct genl_split_ops nfsd_nl_ops[] =3D { .cmd =3D NFSD_CMD_THREADS_SET, .doit =3D nfsd_nl_threads_set_doit, .policy =3D nfsd_threads_set_nl_policy, - .maxattr =3D NFSD_A_SERVER_MAX, + .maxattr =3D NFSD_A_SERVER_FH_KEY, .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { 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/netlink.c b/net/sunrpc/netlink.c new file mode 100644 index 0000000000000000000000000000000000000000..e59ee82dfab358fc367045d9f04= c394000c812ec --- /dev/null +++ b/net/sunrpc/netlink.c @@ -0,0 +1,66 @@ +// 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), +}; + +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(GENLMSG_DEFAULT_SIZE, 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.h b/net/sunrpc/netlink.h new file mode 100644 index 0000000000000000000000000000000000000000..efb05f87b89513fe738964a1b27= 637a09f9b88a9 --- /dev/null +++ b/net/sunrpc/netlink.h @@ -0,0 +1,25 @@ +/* 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; + +int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h, + u32 cache_type); + +#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 Tue Apr 7 02:54:32 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 AAC243A2565; Mon, 16 Mar 2026 15:15:20 +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=1773674120; cv=none; b=RHy7bgld0Ex1og0nz6bvS+yu736SDg+1+IKZgtDQOkYzF1GRww3g64Fz4+kIJycXUqcE2I5MpN3mGoSUjvW+PE+286fErRG9He3KLZkiRxCXYZ2hm89ozyO0Qc3LOd2cZz8MN9s9qUA0Z/MPfIf5pCSaLgtVm2TxSlikqn1SCfg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674120; c=relaxed/simple; bh=bfUwiBYY9UpU/nzDprBrdX3J33AE5K3VXi/DpNoVG7k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PUozPZGL6dfRuNKnPDCwNRuwj9FBGL2+bHvI2vINop33jR3laXPFFNuA4XcSrZrzentJFcmvTzINb1UCDvMdht3CeQhn5KJCOY0Hv5cL7CFMRyMmDc1oNI2u8HIP1RXzMFaKSy7kZ/TLFgms9YUFS4PS0hWBb8enlspJ3fMhb90= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VZtPxxrr; 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="VZtPxxrr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6E117C19425; Mon, 16 Mar 2026 15:15:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674120; bh=bfUwiBYY9UpU/nzDprBrdX3J33AE5K3VXi/DpNoVG7k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=VZtPxxrr8XZxzPxNJgVNvzZ0skv8QOcLau4cZYC9IiI7I4PWGgk0IY0+Di39fRJih yERQyczV+t3tfPo7XbVC1lwAV5i3YWZtyowUZbsnvlxFvOhTQW3iA6O9YG20rrshGG xixeHBOaa6rME3RqN1QOCautqEtyb/AFow+70tW8vtyh/wxZGkGFzFp3wMTWl4Y0WQ +wnfHdkUJc1axUy8AyebKjA7QFnR7cXc1Ad3rQKCdp9Lrz4Nd461MJkn0hx6CSFTXL sboG6F241ajCzFOjLXFgzhnosme68mpv/U2D21JlsV4dCvfA4bgz7c5oAqxKdKnGo3 vK/F1gdmCOsRQ== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:42 -0400 Subject: [PATCH 08/14] 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: <20260316-exportd-netlink-v1-8-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=13419; i=jlayton@kernel.org; h=from:subject:message-id; bh=bfUwiBYY9UpU/nzDprBrdX3J33AE5K3VXi/DpNoVG7k=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB58kUzkLGlT4mSInXBanOVHb5qSOb2fABpSU Yu5NvPtBGaJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefAAKCRAADmhBGVaC Fcf5D/4ljm9SmMD66dkRpuAB3Ax9PDABRlNFym01tTNag7BaRoZmJVa0bUac32PCcn7Rs5zUDET gh65dZbYPnf1sveeoU/t3s7reAZj611pzhvC564qNCyzWPel+1Ab4NOD27RdcLdblr1IQKubbd0 8YDIrS3D8fW3D8MB6zoVgUPecnaFABElQOgVzFUu8uiLjwo9e9SUiBjAywFs8iw7zQGzSRkrGtQ POq0ZJ1E4CLBQtcWK6YEW7Rj2R9RGS6LKpw+ppOo9pJBZTieUvCU3kGsxbrSvDrWlSycTyYFVtQ XsW/LYY55MLVq2gx3VhuxI3WdNVJrPuMCTZxs7wbMyWCrqOZ88D+PmW1ou0kbwVz1YCb9Kz0vtZ VTwh5aRP03SS1ULCSpi4m8uw0nE+l7zofs8+2MPoiVsjzjd6wCDfLXzv90M1Y/Lgef29ZlxecaR gTwnN0gXgx6p9Dk+N+6c81+iVCQcPc4w3CxXZeAZ9ibL0SSVe+XFplMZatFZvHzohzuL6p7hWS4 r0FFTLe6Q+Z3b6zxr1xEwZfVH0Xwj5YkDknqKTkRqrfZz/ZgjJ6ojFSW18ReTJ+/gTttpdD1xQj kmhR3s8Bf4IQGyMMTU8wiLAqDhjSvKgCYIESqRdZ9wgskCmqXBV4WZo3bnz8HGEzcvWJmJinCDd gV76j41WzG0JAKw== 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 | 241 ++++++++++++++++++++++= ++++ 5 files changed, 351 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 e59ee82dfab358fc367045d9f04c394000c812ec..baeaf28fda02f120c2cd4778fcb= 444850ae8868a 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 efb05f87b89513fe738964a1b27637a09f9b88a9..6849faec517ea33ddc5cafab827= 381984e0dc602 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..e4b196742877bd3abf199f2bf81= 5b90615a2be04 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,250 @@ 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. + * + * 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; + 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; + + /* Second call means we've already dumped everything */ + if (cb->args[0]) + return 0; + + 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); + + 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; + } + + 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) { + ret =3D -ENOBUFS; + goto out_cancel; + } + + 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); + ret =3D -ENOBUFS; + goto out_cancel; + } + + nla_nest_end(skb, nest); + } + + genlmsg_end(skb, hdr); + cb->args[0] =3D 1; + ret =3D skb->len; + goto out_put; + +out_cancel: + genlmsg_cancel(skb, hdr); +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 Tue Apr 7 02:54:32 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 81CC63A0E9A; Mon, 16 Mar 2026 15:15:21 +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=1773674121; cv=none; b=WB6fuogM+oOC+SKhGUMWsDKZ9WxxsvRsv/HZkrpbrUxf8KEyn9AHvPaiglGYTjjyVyzv8tTuL7cKOnDmXR4HjmtVTYgMgWnO0WoYrarcbkheYtA7huWnSHAmVHWoeM02HLc9U7ACcNHxbpATKfurOlHVXXTsE4b/cfr3y0VeWCE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674121; c=relaxed/simple; bh=a29/VGykAzsIQd0t1Dj10js2ROjrRaqXqw3BjsUSNvU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ncP155LnYcCUw3HuNuuDaS5v0qtO++pRPq0ZM1pGDuDZ320y88touXKsUxdijoKDAnozF6PXJJ2ufvPs6nO9AfDt47c98bO8ghxVtDb5a3UMVuGGati9e19G3eMHGKG6GDuwf1HlF5LjA13MfhnlwNVp2zC6A+SGLldGkC5lCLY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Nbhp5fS9; 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="Nbhp5fS9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 88DFBC2BC9E; Mon, 16 Mar 2026 15:15:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674121; bh=a29/VGykAzsIQd0t1Dj10js2ROjrRaqXqw3BjsUSNvU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Nbhp5fS9MJnAglNNMPQt12IR8wAf/hADfWqb8oStqPJqEhojB9BLIr4xkfm7TtsyN JnRme6x739UWfg4wT9Ix1c9yJ1u0HBbUUzl2BQSHLoaUMpr4nQTxGpYeNFdNMCMlay 8krRG6USh5JH74pUl1JOe+gaGYftygFtcN+4Q2cILY1yXDToS7uCjX/01mxDerrFso ONCF9N1clolosypXywas5Cx6nNLVNdSgcXWFa4loC7xZ/GEqtisRATPVe1XeUuemUQ Rs30AdDB8UVfuo4ff0INSn3Ad8u3rORyUFXw3HUy10hpvcuW8m3w53HsuI1i7EAFoN ZVAU8iaIZvpnA== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:43 -0400 Subject: [PATCH 09/14] 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: <20260316-exportd-netlink-v1-9-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=13078; i=jlayton@kernel.org; h=from:subject:message-id; bh=a29/VGykAzsIQd0t1Dj10js2ROjrRaqXqw3BjsUSNvU=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB58hyA+QVe1dKeQwicnEAgUgQ+jsRev2tZO8 zp6IUfVdVWJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefAAKCRAADmhBGVaC FSatEADJFJV5NMXJYHufkd3hlN9pnKvJnBEwT1rslbjQeLp0mNWs7JgO3OKeUadtj8gmH1efs+l Ftwt/iyXX8fkr35FXuCJ/x2pg1tBbZZgr+AHyrinxAU0uz/ALUVReALQQZ668ysHT66RiWZXmjN 6stRot8pvLVgrb4bIvo8QFsUP/5AxEDKJSG3CrqLHugndHB1GeYXG5kHIxP2kdoUYtZLjp/I3wD mQqO4pzRa1Ux774kTuzEfoKcH34ZydpaQeQOR0iuHLDWvLN8hTGlHnYo1Znrj0kAMP+hJQDhNPb 5CDL3mJHZpefErWDOtCY4lPo9UnM24cPUI9nBO5ERO8qSxc1yXAV+3TL4jgqiviYgZavGVBFaHm IEDMA9mOzKY8chXRzSonJCLByjHKnkTbhdezIcTtWv6kPrsSU0mUaPfC0wz74p0Jir8Cn/yJaE9 og1o48dxroZLAm6c8VRxh0Ne5wu2AecQMKP8byImr0GJxspTkNDgqMfQJsYtvYBSt2Wv02gJ0r3 PCuBIpJTH9ceSfb5e0VW/8Xg6tIw2nFBZu3Hp1EXtN1C2pVVXXjUaLJoZeblueHaRUSC+HM84H9 vKLPGAxe6pX1iEddAB+KMzuHpjU81ENkNiMpPAgYcf6RxZefSCF5PdPLIvjoWWPP7kSTy1CTlqH avyiDAD3aGMRhuA== 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 | 229 ++++++++++++++++++++++= ++++ 5 files changed, 331 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 baeaf28fda02f120c2cd4778fcb444850ae8868a..44a38aba820d9ad25bd50d0d8c7= a827dfe37c2bd 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 6849faec517ea33ddc5cafab827381984e0dc602..f01477c13f98f6708f3f24391cd= e164edb21a860 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 e4b196742877bd3abf199f2bf815b90615a2be04..b84511ff726c1836f777c802943= f6d8e112a0998 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -585,12 +585,241 @@ 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. + * + * 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; + 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; + + /* Second call means we've already dumped everything */ + if (cb->args[0]) + return 0; + + 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); + + 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; + } + + 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) { + ret =3D -ENOBUFS; + goto out_cancel; + } + + 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); + ret =3D -ENOBUFS; + goto out_cancel; + } + + nla_nest_end(skb, nest); + } + + genlmsg_end(skb, hdr); + cb->args[0] =3D 1; + ret =3D skb->len; + goto out_put; + +out_cancel: + genlmsg_cancel(skb, hdr); +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 Tue Apr 7 02:54:32 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 E26EA3A3E86; Mon, 16 Mar 2026 15:15:22 +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=1773674123; cv=none; b=h3MVe92QIDVzOMs2n9qaadD7T8xHGV89aewmB6iouxUw0ZLm2ad0cB5O/7IHChr6kkc+tw7rruZ5nqKrEZRu0BBuwQPgRiXVzanqxsctK2ggun2LbXSQieO5jzZSQTQ5P3R4JaLSwHhOcW5KQhMp2+TOblSQtXJw6qQM42bkjMc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674123; c=relaxed/simple; bh=/3CFP+ANQV2MMgTPxJuapu5JNhEBNvW8koV5ZXFWusU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rMQkFlt02AXOBcuwpPaK4jqSndCBuRmxkYwSurxP7d84lLgTFDgJSRYir/AUNmwUCzPPoS4dLQPC8ynhDk3vdnMAp2FEiJUXfiCGBhaZyPJ8F1i2j/u/j4c2hFKc30JlCYpnoEX+VRGnZ7Gjk9T76UXXEnuILBN2wQSAAlEDbWM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WJL5qiHH; 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="WJL5qiHH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A2A2AC19421; Mon, 16 Mar 2026 15:15:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674122; bh=/3CFP+ANQV2MMgTPxJuapu5JNhEBNvW8koV5ZXFWusU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=WJL5qiHHsctrAJG6yV76gE8Glu04SGTUgQkf846Yttpwwko32TyD+V0ZW3L08D1qY 6163DOuJLlRLDSEriwqQEGYGYxFtyhBWDsnjmQ7HObstLOyZNS6+OCaOd4+QQbDKJh fZRkLVqkY/1qOP45kVYniF6Xjrh//flU+nkFBgNIys9DzSBNF/EZdwMT4GSO6QBPj8 US7qCvpycA9qa6OcvQND6LFNVgcBSorv0KEaediQ05GNs5dkSFcQZKfs6en44n35Wd 7v69yRsJeHW/cuFqqW8BXrD4rEUMs2YcOV8ljv5EoPhGllxSn0x9jWH/KK0kOz6dcw 3aa+wawprLtdA== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:44 -0400 Subject: [PATCH 10/14] nfsd: add new netlink spec for svc_export 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: <20260316-exportd-netlink-v1-10-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=17436; i=jlayton@kernel.org; h=from:subject:message-id; bh=/3CFP+ANQV2MMgTPxJuapu5JNhEBNvW8koV5ZXFWusU=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB59eV9QJ2ZkKuXcDm7hVMneWUgj1azqGTDDl J/n2+id+t2JAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefQAKCRAADmhBGVaC FTpxD/0buJlqY7PjV/UQ88Pvagcw4Iy/bkbKI+4alYNJ3i81+m8LJ9+4KUT9JV+uPJyHwd876Vt y35bpvMQ+cF/B59U5vs0H5FKA8aSPvj7HGV/KRSEZGqn93/anxj3acHR/rxBcyWjNNzKwjVSkf1 9cbhkc7uAB/TPjB0Akt6q0pP9zel4eVcNi8safNLoRN3HRBAzIh62Pwn6y62J4CAceqpS4/blht SehtG1nV2CdTLKeBxYhXs8NY63sfd5hH4UqvBQPCYfhq4bGW+cS/9WG1aHNbYQO4Esz9++IjTtH XniVCMQRPMCGoqq4p7mbjZSFbr5Nc1aymD00FDmGPZEYfHTBGzhBCIeeFZIJYAfoMr/gdLgan3R wRVhZyD58/6UVcODovmoTmZg56tUY2KnTgOS4ayNnfPvfz3aZ1wpJe/pr1SO7acKkrZ0QVvjmk0 1K8pyl9/G21rh4SpuPHhWE9UFZ6am6/MFyXiYRdqj1rm8ZCfdaQC8No7TegMcD8GQIqWWG1bSxJ Cfg6vv1SDdX5rhChgSr7CTL+idZF5JUolIR3fXAUVBlAODCW8gckTeMheo2lHYPUe2PIGAmCE63 m8gMl5TGZZcK4GqmyScLgdQaLM22x9Fa90fnWA2XsRZQwUKH/m1p7E10z01WYwPEzjDhEhjHivh I8sR76/BlWTpfNw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 ...and generate the headers. Signed-off-by: Jeff Layton --- Documentation/netlink/specs/nfsd.yaml | 172 ++++++++++++++++++++++++++++++= ++++ fs/nfsd/netlink.c | 61 ++++++++++++ fs/nfsd/netlink.h | 13 +++ include/uapi/linux/nfsd_netlink.h | 102 ++++++++++++++++++++ net/sunrpc/netlink.c | 49 ++-------- net/sunrpc/netlink.h | 6 +- 6 files changed, 357 insertions(+), 46 deletions(-) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index 8ab43c8253b2e83bcc178c3f4fe8c41c2997d153..08322bc3dee7458e6a202372dd3= 32067d03e1be6 100644 --- a/Documentation/netlink/specs/nfsd.yaml +++ b/Documentation/netlink/specs/nfsd.yaml @@ -6,7 +6,49 @@ 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 + 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 + entries: + - none + - tls + - mtls + attribute-sets: + - + name: cache-notify + attributes: + - + name: cache-type + type: u32 + enum: cache-type - name: rpc-status attributes: @@ -132,6 +174,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 +372,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/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/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_ne= tlink.h index 97c7447f4d14df97c1cba8cdf1f24fba0a7918b3..1ba1c2c167fd06cd0c845d947f5= a03702356d991 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -10,6 +10,44 @@ #define NFSD_FAMILY_NAME "nfsd" #define NFSD_FAMILY_VERSION 1 =20 +enum nfsd_cache_type { + NFSD_CACHE_TYPE_SVC_EXPORT =3D 1, +}; + +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, +}; + +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 +119,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 +187,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 44a38aba820d9ad25bd50d0d8c7a827dfe37c2bd..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), @@ -98,35 +97,3 @@ struct genl_family sunrpc_nl_family __ro_after_init =3D { .mcgrps =3D sunrpc_nl_mcgrps, .n_mcgrps =3D ARRAY_SIZE(sunrpc_nl_mcgrps), }; - -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(GENLMSG_DEFAULT_SIZE, 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.h b/net/sunrpc/netlink.h index f01477c13f98f6708f3f24391cde164edb21a860..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, @@ -32,7 +31,4 @@ enum { =20 extern struct genl_family sunrpc_nl_family; =20 -int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h, - u32 cache_type); - #endif /* _LINUX_SUNRPC_GEN_H */ --=20 2.53.0 From nobody Tue Apr 7 02:54:32 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 B73453A168C; Mon, 16 Mar 2026 15:15:23 +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=1773674123; cv=none; b=DseZKMRnfj5EHovSon2eeOkLnYsNlFEgKd5Hb/5ENQWymTUmJvys6NWrEjHlX5x4UivZQo9M1GlVnvjNOIZGa7rRbPDP57coh5LZbiORG9rd8jjfufXwfvtb1w70I4qyFMkI6L7leRxtol5m0IwJGqHo3aaifdn27vC3dkNPCCI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674123; c=relaxed/simple; bh=gAFoqWBNfhEgHq70T84C6SLnH52z9jYPIsTUasayNGY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IibyuJyRN0GQNry64HZbCMwuZQKIjFGbtqebIfjfN6Rpz31U5hZ3H8xqOEZ8GY5lFxE58m4j7Tck0eF2Xd35qvhDgFP1xnJaaoSBcDHaSljiVms9c8uWFLCcsCaD8gkIqoFRZhiUZVPeyTGBGkTYnLZz66c6kOtpZ1yEL3ZTldg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qez1pyuy; 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="qez1pyuy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BCD35C19425; Mon, 16 Mar 2026 15:15:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674123; bh=gAFoqWBNfhEgHq70T84C6SLnH52z9jYPIsTUasayNGY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qez1pyuyrL5kbGBGBchavzDEooXfwbtaImELLHvS69B/hNq11XlI6NHMI287lzygw ifOnLHRDQOzEQmfsciucEzk+2GY8NLy9iAbsbZmeCBZNiN+I3FrTCdM7yh9C+jyuie iKd4F83GjClf7Llhc1txRHTPCjjOLjoaNajkEJnfj8J4MEu5EJqPr06RpNaXGBebiq oZ+xfez+AuQS+qEWO9hvZPiMLPiCHsq/nn36ZbG6kTjDD0NDO87T6oz2eVVtHINe7f LrSaGpx8aW/WURypakNBLM662PDubDLpqi9kgH2Ivrf0MJKFVVaJh+lbpTmmZy1gAn sZrd4P2SwvX2Q== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:45 -0400 Subject: [PATCH 11/14] 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: <20260316-exportd-netlink-v1-11-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=15411; i=jlayton@kernel.org; h=from:subject:message-id; bh=gAFoqWBNfhEgHq70T84C6SLnH52z9jYPIsTUasayNGY=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB591LEvAezPcWErdjZ0f+jeo6QVwVBZ76pAK G5Dmd2ZE+yJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefQAKCRAADmhBGVaC FaAVD/0cDm8dMktsjojlLMcCsC0EL1hBoOazooBd3EZCr0CoZpmu8xp7voSGtNKzAGLYUa/fa/H 4TqlZ2IT6rGAUW8TxDBxsm90lC0PH+EDh63CFAMN1S8EJ1dnZ2drSrSOMWRtiLyuecBIkPcGv+N bDw6Ry5BceDj4KbBuBXeaFkWQPrHJV8zLy+OMHomoOubF6pxm8UnStH3NyKi4ohIZYNzHCcGCTk q9/RbVxLlm4vWzvi7GT8iNU26dok4KS9FWlF14Wgz9q7/fBpad+jc+BOTDIheeqjF5UilNCL5RZ QKir8StN0ioTtAbFMAIs7ecMLM5lvZ4pwQUGnLrCPZ/QPR66YHuyagVqqh+efqd/KD7IoapbHTj P1PssSTGPLLl/4DVak47e5/TyXaSb4D+8I1vlwsxh/F4h6AyKAVZXS8lDcpmk1+s8H3KJ3VrBny u+oje2A9pAxpwXsHLQ/V/WZ903MLXA19PX/QdV2WcmdJI8PBt/rCWyhq8//MDS3Pe78XFTN6++A JyqUeenrIa3ScbBsaXbiXpmiyHOW6b+e4SMEfNOeae8ZWNoz+Lql8srHARwNZ7SnzMZtEIzUOAm SZfFB3L66vBdvYusnPMQGMZYuMnz415PaX6ry+g0HUh3KE56sL+2CakY7F+tvq3ovVXb/8cMcuh MFf6zxgXvmzAaRw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add netlink-based cache upcall support for the svc_export (nfsd.export) cache. 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. Signed-off-by: Jeff Layton --- fs/nfsd/export.c | 440 +++++++++++++++++++++++++++++++++++++++++++++++++++= +++- fs/nfsd/nfsctl.c | 28 ++++ fs/nfsd/nfsd.h | 2 +- 3 files changed, 465 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index e83e88e69d90ab48c7aff58ac2b36cd1a6e1bb71..45a8e7b9866377131aac8639deb= dc4f877dc5788 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,443 @@ 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. + * + * 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; + 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; + } + + /* Second call means we've already dumped everything */ + if (cb->args[0]) { + ret =3D 0; + 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); + + 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; + } + + 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) { + ret =3D -ENOBUFS; + goto out_cancel; + } + + 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); + ret =3D -ENOBUFS; + goto out_cancel; + } + + nla_nest_end(skb, nest); + } + + genlmsg_end(skb, hdr); + cb->args[0] =3D 1; + ret =3D skb->len; + goto out_put; + +out_cancel: + genlmsg_cancel(skb, hdr); +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 +845,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 +1338,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/nfsctl.c b/fs/nfsd/nfsctl.c index dc294c4f8c58a6692b9dfbeb98fedbd649ae1b95..7edcbe4504a91966db4805a0993= 68edb92ca38ee 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(GENLMSG_DEFAULT_SIZE, 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 --=20 2.53.0 From nobody Tue Apr 7 02:54:32 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 D40A53A4F21; Mon, 16 Mar 2026 15:15:24 +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=1773674124; cv=none; b=dighFmC/XEha01Q7iYG2gxfjyefnNKoUPOXLU3713dspLhu7g4+H6xs8ZrKNJlkcGHEY3EBQHQ+nI2YbyudR7FGigrqSTi2KsEyPYnM6CCh5CLsS/eYGqzZ/vi6CUplghxQKbaD9c8UyZ5zQb426esGmTDwP5QAujrcOj1UkD6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674124; c=relaxed/simple; bh=M5sSlrxR4y1O2la/4E0fRjLF5UH9Ez1CUZv8gguKdTo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Ne7QQtSAljWeVvWZq6kjO/NkdkFxFghxPDTHtXhwU+eq+CDcExDCq6k2YGnEQAxlAXDM7tAfAvc1Yxn4+oguzbVPH3g8M4bOIoVLkdUhshIfg+bWFStqrCUMrIzCdl1okGkaYM39jKL3BTjF8PpqxNSjYy783iupTs6KfroJ/1k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ou7/s+mo; 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="ou7/s+mo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D8593C19425; Mon, 16 Mar 2026 15:15:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674124; bh=M5sSlrxR4y1O2la/4E0fRjLF5UH9Ez1CUZv8gguKdTo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ou7/s+mo0foqTfqDnYQZo23uVeFvUSB9TnSBCXQoZQOw+nIG1TEbNRkwQxC7FbGJZ QRv1DUPS5yYcVlSE3NxkBhO8qJ9HoV90N2OxzbyER8d/YInPBbStyb2C9yCSKYJx6k EeSy9Q7vKWtFYzH8bDEirLKJqCPcNPKLY2zn6Ao+yA3kDKZkBY+YAj3FDBuXPsBMln zZUQ6gdhA8eBMXiJVlwO0tX2Eq1Y62h/GXYAPUW5h50choCqwoa8WV+MvgYXit+VLH ekDD+TcynjsQAuIInlQSmVYypl61AxFkaN2OpXGmxG/XwWOBUyFcCw3S41sKMBRR5/ Dc5yIOh/qTvMQ== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:46 -0400 Subject: [PATCH 12/14] 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: <20260316-exportd-netlink-v1-12-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=15119; i=jlayton@kernel.org; h=from:subject:message-id; bh=M5sSlrxR4y1O2la/4E0fRjLF5UH9Ez1CUZv8gguKdTo=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB59eLBWkXfjsQZwwtN4tbGxmaxIdowh/1Hnb hiIZDIFKWOJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefQAKCRAADmhBGVaC FXKvEACSu6G3dRhL5sg82UwP9w/CW3/7dRpfzSVDiUlCIQ0fxnDK40tYm8MNqDb8W7h3ubSAGUf f3bv6Ng1T3cREKKK7obKxH0zAh4FYZkPesF+dDXde4iRfbOyNjH/f12eImpc2f1zJzYN1yY1Air k8AZd5Lw/d7ToXnXWSM4/QdQgvrgKnAFn4kG6SFDDtoC95NcPx54yDK9jPs71NQfEl83uqZmoLL 1ba2Lz96DDzE2rOljwFtTgmQvASaRj3CzKVQK6OK1H2b4c8Ft/VNfm+ZHyQsphqW6AvnB889mNb MXEHVmOya+j6s4ZZMubCx5X1bXxlrjbnpNl/jMgGGacqnAWmSAcUR59rzWK4x50B5bQyJ9DurJ6 gyw/h78fyXE3BbIK5/j09Ty4XzAHfuBmR/AGIZXqijLoOBL58TH/cTJ36SHHpT2+3Rsjo8tdQJ6 v2kSqeMpNbRVaflMmkOsNlZEGcGqskLAX2hzeRzvKDvTH3OdCJASNEcCqMOHqYkX+/wH5XXvdAF esvyUOzjnw1R6gZEWNVv84E/PNpC7rQTrudmXh4Nj08YGVU9JDON9ztLsFAWxTzzjJF6336hvmu ADr3nRIzM3El0Yo8B1uYPcO2SJn1+nX+6IwYsBwfJSQLAWhhLTZXA8diQIctSKdp25E6I6IE9Za t08+Bk9oI1vdWpg== 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 | 263 ++++++++++++++++++++++++++++++= ++++ fs/nfsd/netlink.c | 34 +++++ fs/nfsd/netlink.h | 4 + include/uapi/linux/nfsd_netlink.h | 23 +++ 5 files changed, 375 insertions(+), 1 deletion(-) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index 08322bc3dee7458e6a202372dd332067d03e1be6..65fd9caf6bf66abca9302ffa3b9= 47b589dbf0dd3 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 @@ -271,6 +271,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: @@ -398,6 +430,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 45a8e7b9866377131aac8639debdc4f877dc5788..33988de28e95d30948b2f7e4445= 3742c4cb62697 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,263 @@ 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. + * + * 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; + 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; + } + + /* Second call means we've already dumped everything */ + if (cb->args[0]) { + ret =3D 0; + 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); + + 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; + } + + 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) { + ret =3D -ENOBUFS; + goto out_cancel; + } + + 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); + ret =3D -ENOBUFS; + goto out_cancel; + } + + nla_nest_end(skb, nest); + } + + genlmsg_end(skb, hdr); + cb->args[0] =3D 1; + ret =3D skb->len; + goto out_put; + +out_cancel: + genlmsg_cancel(skb, hdr); +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 1ba1c2c167fd06cd0c845d947f5a03702356d991..e96cc1d23366bce13624084fd47= 6dda65aef140a 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 enum nfsd_export_flags { @@ -177,6 +178,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, @@ -190,6 +211,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 Tue Apr 7 02:54:32 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 F032B3A1A38; Mon, 16 Mar 2026 15:15:25 +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=1773674126; cv=none; b=LkZz2dQbzEq6kVYm2SE+mcwanKKA1SiG3rn4HITeNK6sdUuM5kFKL3F03114nzMf/mqyynZWCPPtA2zOd5Qfrz1yJIqYvxksMidIM4VDYn6cB2fqNdFHKzocfjkFzcfZ/RBKsHHC+pW7pVv8Gq4DW3/5jjTa25o2Rz0qvJg1gkM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674126; c=relaxed/simple; bh=OxGhnlUBkot6TJTrZW99YZR3StOdNEnOnPus13qKpRg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LkUpURwsyUdwx81Bw8vAfTfilzeYFHJEY2Pz3k4JtY8q/HOQYgJeLnurQLaZkTPqbU4QY39jxAiY8EgmhUcdrW6Pe1b402ILSmExaffcZ8O/DsJmTFbC3/n9cdh/65NLti1/kv4TuB2W0yzwp4D1ni86YGhyA+bKFvmvRQ/k87M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uTf43bMT; 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="uTf43bMT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 00FF2C19421; Mon, 16 Mar 2026 15:15:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674125; bh=OxGhnlUBkot6TJTrZW99YZR3StOdNEnOnPus13qKpRg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=uTf43bMTY3dJYk0g8NGCwAjeJMkfKut6qkkSMskTvcB6WVKI8vrn5ipF7qqXdogvW p/9G7dO/HSHCnNT83iYV4h2UXQFeXjdbLUhVOZokfCL3624wthD4WSfY6iPhHAyhWU 94yjAgRu8to9NjwL/HCnawyOpuriELnhvOgTclkHvIJRtWTNyZ+WADTFor8/F598Xm fRbraBn43V+EOocXDDfzHvfT6MFrdcAJf6HuIDkHAPjcs1ObZ0d0MYPh9wDZD88xsm 5QOiDz4/NPzurp+mTzLjhDtLwivOc0nIRiEmkqwKVuQfttpNttjcCotxck5ZHkv8e0 W40P7kaiZInng== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:47 -0400 Subject: [PATCH 13/14] 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: <20260316-exportd-netlink-v1-13-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7165; i=jlayton@kernel.org; h=from:subject:message-id; bh=OxGhnlUBkot6TJTrZW99YZR3StOdNEnOnPus13qKpRg=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB59bM5OmlDgR84KagSz9fcKGeW9LTz0TYLIo hzbmF5eAreJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefQAKCRAADmhBGVaC Ff2/EACXwWL2s4gVik8U086OlbvnKZKiOMMU5R7JYQOGwrvYP+Ex9LA8p/fcmdzKFGiQSUz0791 3vi0WcSmZ8dU8thU+vVDBq6cuLcIrOGD6jY2IV8R2KSsRkxFGCHsyqgPbuGT9RwW0g4attg3/rB zQgssBAHOezHF2+5THjFmysp+POGjEwhViwAW0adLs/Kaq9GfhZtaMn0hT1ixtSUitJbFDylWjX xoQSXLG324PXNmhu8pgj7a6nVZU/t4xXqexVzOVx7yPmkuUssphXDv38yp31l0+vFv6mShAwx1y 52cGFo37u2ibaEQk3oAEbOZXhuHiok1VwLVbL4ZGHQdRi8YYsuTvm7zuqh5hQyRnAjbSVguPyDr yLlKUh4X9XE8t7hjt5XtGjHKH6UBNaOCCeDDtTGTrQWpxKZrjeUYtrxMuolnUCPOfeXcE3eJ+yb SD5wFEgO9zPBxu0zJFAypGzajS5YAm5cQmbof8nNZWj2BxdYAUUOS+BYHRBvQOLFxUTpPOUP2R5 B6etZTbbDsDJdkXcjZ58XmE8djhrfiAyMN3NzQ2uFSJ4KUV3+MIa9F7HVPngsGk7L01QbRMKaAf kMd6Ed6L41/yni/bIsgwPWGa2XSzbNoPp3ILWA1D2lLoh2qwmQGuHyuJxS1QVY1cShzRD8JNIeb H7PQSUIk40IskTw== 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 | 45 +++++++++++++++++++++++= ++++ net/sunrpc/netlink.h | 4 +++ net/sunrpc/svcauth_unix.c | 32 +++++++++++++++++++ 5 files changed, 106 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..47491c2e63ebb8cacf4f8fe2fa9= 13e31541c77a5 100644 --- a/net/sunrpc/netlink.c +++ b/net/sunrpc/netlink.c @@ -6,6 +6,7 @@ =20 #include #include +#include =20 #include "netlink.h" =20 @@ -49,6 +50,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 +85,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 { @@ -97,3 +110,35 @@ struct genl_family sunrpc_nl_family __ro_after_init =3D= { .mcgrps =3D sunrpc_nl_mcgrps, .n_mcgrps =3D ARRAY_SIZE(sunrpc_nl_mcgrps), }; + +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(GENLMSG_DEFAULT_SIZE, 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.h b/net/sunrpc/netlink.h index 2aec57d27a586e4c6b2fc65c7b4505b0996d9577..7eec78cb32ff3c7ae9ed2b1b1c6= b75e2a403f68e 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, @@ -31,4 +32,7 @@ enum { =20 extern struct genl_family sunrpc_nl_family; =20 +int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h, + u32 cache_type); + #endif /* _LINUX_SUNRPC_GEN_H */ diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index b84511ff726c1836f777c802943f6d8e112a0998..dd90beebd74c1e243535d11e753= 668589ae1fe18 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -813,6 +813,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 Tue Apr 7 02:54:32 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 53E7C3A5E7F; Mon, 16 Mar 2026 15:15:27 +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=1773674127; cv=none; b=h5kmtRAf4jh1mydk67lT0CAkOTsRLXrDwyL2SZeYJWOzjTgegtcQCfghbifvd+bl1sz+p88GFnHTyZ+ATmKozqcn2OxPOooGSNpbfHVTwdwNhEXsSh+QbdSNKhbLoy2Ys1lRSrIu+J//2XMbxkd2ea3YdlGtlzlA60BTaMn0er8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773674127; c=relaxed/simple; bh=A9Rw84PlLvLsCjZyYBdQk3iW5PsqBOc6SO9yNWSLjU0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=izmmoHynxckt09Wqs+nC9Rd020h7Y/nNxbJJ5ouuoUBulrlg/7n89a1EwgYStltWj5mcMtyHm+jzNa5CEBmDMJwxQiz/DYs6A5gz8sVnadfdOjNnC4Xz/zWEhpTPzJ6JYsOpwJMSLTBP+mO6TYF2Y6GA5HKoIygmwi+EVf5top0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WE9xlX72; 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="WE9xlX72" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1C8F2C19421; Mon, 16 Mar 2026 15:15:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773674127; bh=A9Rw84PlLvLsCjZyYBdQk3iW5PsqBOc6SO9yNWSLjU0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=WE9xlX72XGTFNkZJpJ5UdbnjMQoldYjF0TjXc5V2P2UuJVeHCsBC8htrKvG8nK8th TkxmA3ymLj0zHNUa/JD0z/H9qNLekev9hr3uaDCKi+Cp9koVBgBIV96tCvo5vGx3Oy TPZE+TmW1cHDQDfEeRQxHeHtzlbTZ/UCUubR0VmqqB6CxWWJonPZKU0AgS2CAi/vIz vHg1guRZqt/K4w+GUQ2voft9syAQA6V54NewlO11rAwg7DqUMiRScy34TUhMNd525U hMzcRPq8id2AicjChAzhwdpPPxKtF+ph00TbKOFl5ReWjgne7wtzT1QAU2Pg+9cVZy +IyO7Fgt7TXxA== From: Jeff Layton Date: Mon, 16 Mar 2026 11:14:48 -0400 Subject: [PATCH 14/14] 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: <20260316-exportd-netlink-v1-14-6125dc62b955@kernel.org> References: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> In-Reply-To: <20260316-exportd-netlink-v1-0-6125dc62b955@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: Trond Myklebust , Anna Schumaker , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5945; i=jlayton@kernel.org; h=from:subject:message-id; bh=A9Rw84PlLvLsCjZyYBdQk3iW5PsqBOc6SO9yNWSLjU0=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpuB5+qaZJuw7HoA3SF+Kci3ALyrvcNxRbIoJvf UbqgIk2s6OJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCabgefgAKCRAADmhBGVaC FY73EACrZTUB90KsKnSQLxrjsifgYD4HZx+ue9Xwo/uLwLAqjU7s6Cw+Hs+Uej5pwaQgoYaoLhb IZSVjYaxJITDEEHe5hV7GEa+4axLE3iC4cxp3PNN3yLN6Bs02s7CqBbN0jIwv2QCIFD10Wi/hco /Snm0gcrSszfxTLw+MFvCLeZw/JDboup1UEf4IIPAL2/63ADEn7ZYE1+iInU+df4EUhjK0XtTGO N8KdYcSFSZE2Fnc0wb+ajHtEhjEqQ+VWbrdm/HjVaZ+voomhKgnK+ulV+gT2/XSH02mqv59gYy7 nfUnvIBaMNcPFyuppU8j6eLFAM8ILoQjXkdJePexjJrwV6gLmImfX8NNCUx0Ap3hIQKxob/py+o hsGhzwliAlcMWRq15J95kfvD6WCokKGCSBrYOyT1KG/CkpfnANYwxr3ueQB3JKlhus9kWnecF0u Z4Tik/paZA6k1egXnuhRiuk5JW7TNJvr8VK84FOtZrifXVC52p/xQPTn51NjIB0FLOWqFyeB+8I BLnrVi0/I9ks8mV9YghcjxGYSXl0aE5yjK6Qcw8cbtu+UbADpQ9hUV5SnECkYQ9dS5OUPH51TBX nYDbUWI/yxvyN6waWwHCQTZzE+hWoHBOu7DbnD0E7fxcP6Ual+6IIVMIDki8YK6QfU7SRqlKCdG l08xKXExS4ZMPdw== 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 | 32 ++++++++++++++++++++++++++++++++ include/uapi/linux/nfsd_netlink.h | 8 ++++++++ 5 files changed, 70 insertions(+) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index 65fd9caf6bf66abca9302ffa3b947b589dbf0dd3..09faeff3b7c20032cd61c992170= f1e81f922605e 100644 --- a/Documentation/netlink/specs/nfsd.yaml +++ b/Documentation/netlink/specs/nfsd.yaml @@ -303,6 +303,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: @@ -448,6 +456,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 7edcbe4504a91966db4805a099368edb92ca38ee..98eeb2be56ce4b826611ba37807= 4c522d761cb1e 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,37 @@ 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]); + + 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); + + 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 e96cc1d23366bce13624084fd476dda65aef140a..08b8a77179f88f596d482d7a2ec= 5c19ee98b2e77 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -198,6 +198,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, @@ -213,6 +220,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