Received: by 2002:ab2:6c55:0:b0:1fd:c486:4f03 with SMTP id v21csp181297lqp; Tue, 11 Jun 2024 20:08:20 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXT3N58vU7XERqFLho8uGi0oiWGKbJPzvRsd9g+2rI+vgay5ptUPTebvBQb3XgD6LsPB5+RDam4DTD3bbYKFemyktnyiFN9X8OIKrgZfg== X-Google-Smtp-Source: AGHT+IGwcxAPM7RUHco3ZHVmIKtppPx6OX8QOwmbJ56JuiGEuvE9jm4Wl1TLM7TN8tEVa7yvQZWD X-Received: by 2002:a9d:7f08:0:b0:6f9:b071:28e4 with SMTP id 46e09a7af769-6fa1c33d4d5mr687869a34.34.1718161700288; Tue, 11 Jun 2024 20:08:20 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1718161700; cv=pass; d=google.com; s=arc-20160816; b=f9MpIOctMwcFn1dGCESbYDbDbOrRrZQZ6rnZfrCUm0+IR8txEwH+BGeY6QnPGfRUVJ kUgU7siGeOkB5pDx4fB+pk8kjWHp+E4LhVoYNGav9tU605IY5QUQBSIoo9ZHvbcv6osp BFkUmVFFgPRNdCDNAGTF7tQbIP3rksINpTGVupikwhZpYO76xcZeH6j9b7p46Q3SmjdP f3S93dvWZE++z4nQ24GFiPYjc+ZKUVgH4DEoxFqK7+bdhhbqCPWDY6i1OYxU1ztHGX3s scQiFJjTqmDb/kiFlzHIe3iRlpfsOqR3Rncjl3gvGwCI/tG/OzSyTEa+PJKG8/fTlr3s B1/A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=au1AeAXMGewof3KKgKVTf40OgVN7AdI3/dd1uqP7sgw=; fh=+HdF1SWcNPggmowVZtzfZ2+SYSXLLgvZBECjaw6UQek=; b=wVhbIRL9chbQNtS3eIV/dH9nbJvSLwrqm1voHNH8GeqMb+0GodjtX6NsSz3cm0RuBP BkTXdUItTS/gFfZc9pQ33m8FoYAXKfqd14bWzUzfGK9ObB4KMoj9YRaAN/u/jnSecVRK Jt3NtTtmkbgsTduKDJuvCtF+r20o4atsUdZIDhPumgtvrL8+iauW6gCX9rM/7X90Z1M/ AqoPe90DgfJIjf1c2Wb4Cvr97XqTw3vlplFBQMvZGuJGx/Mzv10N9JSvMOBwnNcJU+sc pzuMF5YFmwE22S5iRxNeg60l6RNbInAAfy7r2qKG4xvFeaB3gR+N6MC5MDZbR/Dcgs0Y SVLg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="QE29d/xr"; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-nfs+bounces-3668-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-nfs+bounces-3668-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id 41be03b00d2f7-6ea6e277927si6015693a12.69.2024.06.11.20.08.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Jun 2024 20:08:20 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs+bounces-3668-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="QE29d/xr"; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-nfs+bounces-3668-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-nfs+bounces-3668-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id D76C2283123 for ; Wed, 12 Jun 2024 03:08:19 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 90EE7286A6; Wed, 12 Jun 2024 03:08:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QE29d/xr" X-Original-To: linux-nfs@vger.kernel.org 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 6C52428385 for ; Wed, 12 Jun 2024 03:08:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718161691; cv=none; b=CEoDpJebX5FMqUPKJ23BrHkv8khY6+VIfyqyRs3gJCz4zjyhdfRB0Q/cU/9eitibY/vm7uoQ4E26AAqnFTsFxrrNogzXKutZ44UWp3exlAIMROk+hjzrkp1D+h+J6YDKY4Cv+/yWeedl0qpOpp6eGXM0o95A9/bJX0JAgLusfoQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718161691; c=relaxed/simple; bh=DWzSXIeQu9Uc70wrWQRohNZIeHuCwZHn1bmENXNYxsw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FXBSlDt+ywvdbAT7zn/feHC8+co9ssQYJ431IcZTaleexxSvMP1PPGHTpjgS1/ET7tDKVQKfPwO8UwVCDqRK84vDvyMkltsajrGC9puTVcMvRxPrVVIh2Dw+EJ3E9xF5efCoPsJL4bZkLvR+mEn/GVObN5WMR/Irb3kmDS1J45o= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QE29d/xr; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1B66DC2BD10; Wed, 12 Jun 2024 03:08:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1718161691; bh=DWzSXIeQu9Uc70wrWQRohNZIeHuCwZHn1bmENXNYxsw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QE29d/xrTP4dsUII3d6w6+Z4JJuTzqz02pNZYqUtY2YOqDEMWbGYPf3ssFeALzxbR wAON7msJlFW+ysnUVAtSo+eCdjCSX/zZwDxkkcEpihAK1BNwY6oaAIiDq/hxMSQSlH R3GX/fcXDcYzfu86u02MmPFUZfDsCAeXdVzT0uU4Lhii1eKNufBSoi+9DSgiXwPe5+ UtL+jJWJTXmIAAMcc5XqGyXNCEGzz1V4ZRt9wRrgLsQWFZo+e5khUcqTeMak53JRiQ q/RSCV9c5OxGQfMYtjeXEusaMzVeh/6ccKjMQss78fUxjre15s4VXusuBCRFxSuVhu DfGfUmVjVEu0A== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Jeff Layton , Chuck Lever , Trond Myklebust , NeilBrown , snitzer@hammerspace.com Subject: [RFC PATCH v2 12/15] nfsd: implement v3 and v4 server support for NFS_LOCALIO_PROGRAM Date: Tue, 11 Jun 2024 23:07:49 -0400 Message-ID: <20240612030752.31754-13-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240612030752.31754-1-snitzer@kernel.org> References: <20240612030752.31754-1-snitzer@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit LOCALIOPROC_GETUUID encodes the server's uuid_t in terms of the fixed UUID_SIZE (16). The fixed size opaque encode and decode XDR methods are used instead of the less efficient variable sized methods. Signed-off-by: Mike Snitzer --- fs/nfsd/localio.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ fs/nfsd/nfsd.h | 11 ++++ fs/nfsd/nfssvc.c | 80 ++++++++++++++++++++++++- fs/nfsd/xdr.h | 6 ++ 4 files changed, 244 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c index 6a418aa5614f..e35480595ec9 100644 --- a/fs/nfsd/localio.c +++ b/fs/nfsd/localio.c @@ -17,6 +17,9 @@ #include "vfs.h" #include "netns.h" #include "filecache.h" +#include "cache.h" +#include "xdr3.h" +#include "xdr4.h" #define NFSDDBG_FACILITY NFSDDBG_FH @@ -182,3 +185,148 @@ EXPORT_SYMBOL_GPL(nfsd_open_local_fh); /* Compile time type checking, not used by anything */ static nfs_to_nfsd_open_t __maybe_unused nfsd_open_local_fh_typecheck = nfsd_open_local_fh; + +/* + * GETUUID XDR encode functions + */ + +static __be32 nfsd_proc_null(struct svc_rqst *rqstp) +{ + return rpc_success; +} + +static __be32 nfsd_proc_getuuid(struct svc_rqst *rqstp) +{ + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + struct nfsd_getuuidres *resp = rqstp->rq_resp; + + uuid_copy(&resp->uuid, &nn->nfsd_uuid.uuid); + resp->status = nfs_ok; + + return rpc_success; +} + +#define NFS_getuuid_sz XDR_QUADLEN(UUID_SIZE) + +static inline void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len) +{ + WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0); +} + +static void encode_uuid(struct xdr_stream *xdr, uuid_t *src_uuid) +{ + u8 uuid[UUID_SIZE]; + + export_uuid(uuid, src_uuid); + encode_opaque_fixed(xdr, uuid, UUID_SIZE); + dprintk("%s: uuid=%pU\n", __func__, uuid); +} + +#if defined(CONFIG_NFSD_V3_LOCALIO) +static bool nfs3svc_encode_getuuidres(struct svc_rqst *rqstp, + struct xdr_stream *xdr) +{ + struct nfsd_getuuidres *resp = rqstp->rq_resp; + + if (!svcxdr_encode_nfsstat3(xdr, resp->status)) + return false; + if (resp->status == nfs_ok) + encode_uuid(xdr, &resp->uuid); + + return true; +} + +#define ST 1 /* status */ +#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) + +static const struct svc_procedure nfsd_localio_procedures3[2] = { + [LOCALIOPROC_NULL] = { + .pc_func = nfsd_proc_null, + .pc_decode = nfssvc_decode_voidarg, + .pc_encode = nfssvc_encode_voidres, + .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_ressize = sizeof(struct nfsd_voidres), + .pc_cachetype = RC_NOCACHE, + .pc_xdrressize = 1, + .pc_name = "NULL", + }, + [LOCALIOPROC_GETUUID] = { + .pc_func = nfsd_proc_getuuid, + .pc_decode = nfssvc_decode_voidarg, + .pc_encode = nfs3svc_encode_getuuidres, + .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_ressize = sizeof(struct nfsd_getuuidres), + .pc_cachetype = RC_NOCACHE, + .pc_xdrressize = 1+NFS_getuuid_sz, + .pc_name = "GETUUID", + }, +}; + +static DEFINE_PER_CPU_ALIGNED(unsigned long, + nfsd_localio_count3[ARRAY_SIZE(nfsd_localio_procedures3)]); +const struct svc_version nfsd_localio_version3 = { + .vs_vers = 3, + .vs_nproc = 2, + .vs_proc = nfsd_localio_procedures3, + .vs_dispatch = nfsd_dispatch, + .vs_count = nfsd_localio_count3, + .vs_xdrsize = NFS3_SVC_XDRSIZE, +}; +#endif /* CONFIG_NFSD_V3_LOCALIO */ + +#if defined(CONFIG_NFSD_V4_LOCALIO) +static bool nfs4svc_encode_getuuidres(struct svc_rqst *rqstp, + struct xdr_stream *xdr) +{ + struct nfsd_getuuidres *resp = rqstp->rq_resp; + __be32 *p; + + p = xdr_reserve_space(xdr, 8); + if (!p) + return 0; + *p++ = cpu_to_be32(LOCALIOPROC_GETUUID); + *p++ = resp->status; + + if (resp->status == nfs_ok) + encode_uuid(xdr, &resp->uuid); + + return 1; +} + +static const struct svc_procedure nfsd_localio_procedures4[2] = { + [LOCALIOPROC_NULL] = { + .pc_func = nfsd_proc_null, + .pc_decode = nfssvc_decode_voidarg, + .pc_encode = nfssvc_encode_voidres, + .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_ressize = sizeof(struct nfsd_voidres), + .pc_cachetype = RC_NOCACHE, + .pc_xdrressize = 1, + .pc_name = "NULL", + }, + [LOCALIOPROC_GETUUID] = { + .pc_func = nfsd_proc_getuuid, + .pc_decode = nfssvc_decode_voidarg, + .pc_encode = nfs4svc_encode_getuuidres, + .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_ressize = sizeof(struct nfsd_getuuidres), + .pc_cachetype = RC_NOCACHE, + .pc_xdrressize = 2+NFS_getuuid_sz, + .pc_name = "GETUUID", + }, +}; + +static DEFINE_PER_CPU_ALIGNED(unsigned long, + nfsd_localio_count4[ARRAY_SIZE(nfsd_localio_procedures4)]); +const struct svc_version nfsd_localio_version4 = { + .vs_vers = 4, + .vs_nproc = 2, + .vs_proc = nfsd_localio_procedures4, + .vs_dispatch = nfsd_dispatch, + .vs_count = nfsd_localio_count4, + .vs_xdrsize = NFS4_SVC_XDRSIZE, + .vs_rpcb_optnl = true, + .vs_need_cong_ctrl = true, + +}; +#endif /* CONFIG_NFSD_V4_LOCALIO */ diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 8f4f239d9f8a..dd225330837f 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -142,6 +142,17 @@ extern const struct svc_version nfsd_acl_version3; #endif #endif +#if defined(CONFIG_NFSD_V3_LOCALIO) +extern const struct svc_version nfsd_localio_version3; +#else +#define nfsd_localio_version3 NULL +#endif +#if defined(CONFIG_NFSD_V4_LOCALIO) +extern const struct svc_version nfsd_localio_version4; +#else +#define nfsd_localio_version4 NULL +#endif + struct nfsd_net; enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index e67eb34a836b..22fb16258d44 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -38,6 +38,16 @@ atomic_t nfsd_th_cnt = ATOMIC_INIT(0); extern struct svc_program nfsd_program; static int nfsd(void *vrqstp); +#if defined(CONFIG_NFSD_V3_LOCALIO) || defined(CONFIG_NFSD_V4_LOCALIO) +static int nfsd_localio_rpcbind_set(struct net *, + const struct svc_program *, + u32, int, + unsigned short, + unsigned short); +static __be32 nfsd_localio_init_request(struct svc_rqst *, + const struct svc_program *, + struct svc_process_info *); +#endif /* CONFIG_NFSD_V3_LOCALIO || CONFIG_NFSD_V4_LOCALIO */ #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) static int nfsd_acl_rpcbind_set(struct net *, const struct svc_program *, @@ -81,6 +91,31 @@ DEFINE_SPINLOCK(nfsd_drc_lock); unsigned long nfsd_drc_max_mem; unsigned long nfsd_drc_mem_used; +#if defined(CONFIG_NFSD_V3_LOCALIO) || defined(CONFIG_NFSD_V4_LOCALIO) +static const struct svc_version *nfsd_localio_version[] = { +#if defined(CONFIG_NFSD_V3_LOCALIO) + [3] = &nfsd_localio_version3, +#endif +#if defined(CONFIG_NFSD_V4_LOCALIO) + [4] = &nfsd_localio_version4, +#endif +}; + +#define NFSD_LOCALIO_MINVERS 3 +#define NFSD_LOCALIO_NRVERS ARRAY_SIZE(nfsd_localio_version) + +static struct svc_program nfsd_localio_program = { + .pg_prog = NFS_LOCALIO_PROGRAM, + .pg_nvers = NFSD_LOCALIO_NRVERS, + .pg_vers = nfsd_localio_version, + .pg_name = "nfslocalio", + .pg_class = "nfsd", + .pg_authenticate = &svc_set_client, + .pg_init_request = nfsd_localio_init_request, + .pg_rpcbind_set = nfsd_localio_rpcbind_set, +}; +#endif /* CONFIG_NFSD_V3_LOCALIO || CONFIG_NFSD_V4_LOCALIO */ + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) static const struct svc_version *nfsd_acl_version[] = { # if defined(CONFIG_NFSD_V2_ACL) @@ -95,6 +130,9 @@ static const struct svc_version *nfsd_acl_version[] = { #define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version) static struct svc_program nfsd_acl_program = { +#if defined(CONFIG_NFSD_V3_LOCALIO) || defined(CONFIG_NFSD_V4_LOCALIO) + .pg_next = &nfsd_localio_program, +#endif /* CONFIG_NFSD_V3_LOCALIO || CONFIG_NFSD_V4_LOCALIO */ .pg_prog = NFS_ACL_PROGRAM, .pg_nvers = NFSD_ACL_NRVERS, .pg_vers = nfsd_acl_version, @@ -123,6 +161,10 @@ static const struct svc_version *nfsd_version[] = { struct svc_program nfsd_program = { #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) .pg_next = &nfsd_acl_program, +#else +#if defined(CONFIG_NFSD_V3_LOCALIO) || defined(CONFIG_NFSD_V4_LOCALIO) + .pg_next = &nfsd_localio_program, +#endif /* CONFIG_NFSD_V3_LOCALIO || CONFIG_NFSD_V4_LOCALIO */ #endif .pg_prog = NFS_PROGRAM, /* program number */ .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ @@ -817,6 +859,42 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scop return error; } +#if defined(CONFIG_NFSD_V3_LOCALIO) || defined(CONFIG_NFSD_V4_LOCALIO) +static bool +nfsd_support_localio_version(int vers) +{ + if (vers >= NFSD_LOCALIO_MINVERS && vers < NFSD_LOCALIO_NRVERS) + return nfsd_localio_version[vers] != NULL; + return false; +} + +static int +nfsd_localio_rpcbind_set(struct net *net, const struct svc_program *progp, + u32 version, int family, unsigned short proto, + unsigned short port) +{ + if (!nfsd_support_localio_version(version) || + !nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST)) + return 0; + return svc_generic_rpcbind_set(net, progp, version, family, + proto, port); +} + +static __be32 +nfsd_localio_init_request(struct svc_rqst *rqstp, + const struct svc_program *progp, + struct svc_process_info *ret) +{ + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + + if (likely(nfsd_support_localio_version(rqstp->rq_vers) && + nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST))) + return svc_generic_init_request(rqstp, progp, ret); + + return rpc_prog_unavail; +} +#endif /* CONFIG_NFSD_V3_LOCALIO || CONFIG_NFSD_V4_LOCALIO */ + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) static bool nfsd_support_acl_version(int vers) @@ -959,7 +1037,7 @@ nfsd(void *vrqstp) } /** - * nfsd_dispatch - Process an NFS or NFSACL Request + * nfsd_dispatch - Process an NFS or NFSACL or NFSLOCALIO Request * @rqstp: incoming request * * This RPC dispatcher integrates the NFS server's duplicate reply cache. diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h index 852f71580bd0..5714469af597 100644 --- a/fs/nfsd/xdr.h +++ b/fs/nfsd/xdr.h @@ -5,6 +5,7 @@ #define LINUX_NFSD_H #include +#include #include "nfsd.h" #include "nfsfh.h" @@ -123,6 +124,11 @@ struct nfsd_statfsres { struct kstatfs stats; }; +struct nfsd_getuuidres { + __be32 status; + uuid_t uuid; +}; + /* * Storage requirements for XDR arguments and results. */ -- 2.44.0