Received: by 2002:a89:413:0:b0:1fd:dba5:e537 with SMTP id m19csp561976lqs; Thu, 13 Jun 2024 20:44:54 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUSKZ4/lR+i9vqiXYY746CNWu7o93Xlygqs2JnrsZAL6RyEoJIC74btF0xdSAlBwQn3BaZVpR9x0CUlEdnrd9SiLEmzsg/+5mfXpFqAgw== X-Google-Smtp-Source: AGHT+IE5CXN6V18huXUo11mC9PcL8Gi4f+I7U9seMo/4EFvaNGaV7pvQTBPxvB4s9h/Yc8KbGuP4 X-Received: by 2002:a0c:ea8f:0:b0:6b2:a333:2abd with SMTP id 6a1803df08f44-6b2afcd41e9mr17242676d6.33.1718336694457; Thu, 13 Jun 2024 20:44:54 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1718336694; cv=pass; d=google.com; s=arc-20160816; b=0UY9ZAuMR5mudL3OH9uQnyrUtEtZdB8y075WFsAUHG5iKzOYoFfamrhTVIhPYPHvk4 gx+A5ce7WCbsmjchZUizhCTcUOifJT77L44diMSgWTqSm3Z95GEWrhPzTHHCTUZ9jH2P lvUm6jnqKQ0EfE4uoZcNPudoIlRmLWDqx7KuN7KPAUNAyeTX8MTbJLBSIlvv0Gx6OCFw VYigv9GNiPIynWC4PcWXnyFFA3RZLOkYuDZP9nWX3KyMcN50CGSTNZinf1vzRJ67bd/D HqoN5zQUppaq/gG0ZZOODblTVPDYj+uFd3u5qlPTJQdT++viIYexPgJEsfN74jb1fWma 72nw== 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=2xedlmfZaKQu2cVUVU24KkVg3S0Z34L5Lk45liX88E8=; fh=+HdF1SWcNPggmowVZtzfZ2+SYSXLLgvZBECjaw6UQek=; b=LeAY0+diOLGQxDgkE9ZWkaJNaVQuVQ7wQ04I84lMGdnyLnSS+5KnvKnw4R09yjdN42 MdCewKL4EExq8k0LNgdcvbWIfFn3M0uU9l7FkzE/o/lRe0TUAx/4uiaMNrpzddlmE2ZR TwwR++eRBDHxtfJt+TfM9i4I0/lax5vAHLYviZld/usbfzhsTsYu61OqicyOqVh5TxWT svEB/gQn+gSyjSSxjw/AXwUfK8d4ejAH/JcwhfE3PY/6vlD/TXegNX4U2o+uFEko+zGD gG5+9LCvSz/iAVzp/gi2xzAjVT0AvQnMc7yeuy5y3RrH35QdAgcuC3/9mPPcfwACW6nv MsZg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=WE4s2aVc; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-nfs+bounces-3811-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-nfs+bounces-3811-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id 6a1803df08f44-6b2a5a151besi29641626d6.74.2024.06.13.20.44.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Jun 2024 20:44:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs+bounces-3811-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=WE4s2aVc; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-nfs+bounces-3811-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-nfs+bounces-3811-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 ny.mirrors.kernel.org (Postfix) with ESMTPS id 10C911C21540 for ; Fri, 14 Jun 2024 03:44:54 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 30B4B146D43; Fri, 14 Jun 2024 03:44:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WE4s2aVc" 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 0CC39146D40 for ; Fri, 14 Jun 2024 03:44:43 +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=1718336683; cv=none; b=KLHMrTtjqxhQIPL1U/mVofG5bqa7TxQg1PAIiy2qZd1yCz7fhQLWiR7Ej4xPWKCvEo13G8u981ERgChZ+KoTwVfRSNf6CNMFG6GOb+ERnPGZC1q1U+ETLTxVEZGkwyo46EkfjVm4xLI0wi97BGQQLyBTlk7+GWmVDoSMhRUINGk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718336683; c=relaxed/simple; bh=09lWm/AKX2LDeCYV9fqxg3IzOsPq+5UtqFtqeVCjbuY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ob5Tif/qGrKRVEhVCaIzONIMIqo4jjOVo6CMLI5CFPIAbKukcogaSB4vE8OebsJ0aR1OmNik7F1ofqR2Bwa2GpfFUABshHmskkLtosuJosXa5RzEAZq2JUt0+w085duHFye7mLKqX0Fee3NN5Zw1Pn3ZsfofjSTv6mfkgxTf3oM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WE4s2aVc; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id A4FB6C3277B; Fri, 14 Jun 2024 03:44:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1718336682; bh=09lWm/AKX2LDeCYV9fqxg3IzOsPq+5UtqFtqeVCjbuY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WE4s2aVci5zzR4ModKphhai9goWLZDjZti8n0A12axU9jwId2AC+1q+N2QkgbHmgv vb/IiOruGoKHkF62nRLrNiOZ5eZiOnYFVA0WfDtyynHJ52NSUqVAhWahCGGcAmkKeB 9EgBFMO0uDmtWImBK38UVGSU4wYU/5XjBovamHF8YVIIfUmhaP2GWiI1VFhfR2GRJt P7UqArusW5v0fTfzYsH/yAP/a8RqDN1cJ7hdBF/WVqxZqA1ZDHo2gvqdT2+72pkPKG 7K1KfsJwMXwrW7EyfX+LC8v3+1iZT9u7XykRd5Ot5mQ3DXpwF0GQR9+qLuPtyYdEiB gTlrVzJdJcYXA== From: Mike Snitzer To: linux-nfs@vger.kernel.org Cc: Jeff Layton , Chuck Lever , Trond Myklebust , NeilBrown , snitzer@hammerspace.com Subject: [PATCH v3 11/18] nfsd: implement v3 and v4 server support for NFS_LOCALIO_PROGRAM Date: Thu, 13 Jun 2024 23:44:19 -0400 Message-ID: <20240614034426.31043-12-snitzer@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240614034426.31043-1-snitzer@kernel.org> References: <20240614034426.31043-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 6e2918e76f49..bb84e165dbe1 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 @@ -241,3 +244,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 7383dc10611c..0f2f257be94f 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 IS_ENABLED(CONFIG_NFSD_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_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 IS_ENABLED(CONFIG_NFSD_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_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 IS_ENABLED(CONFIG_NFSD_LOCALIO) + .pg_next = &nfsd_localio_program, +#endif /* CONFIG_NFSD_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 IS_ENABLED(CONFIG_NFSD_LOCALIO) + .pg_next = &nfsd_localio_program, +#endif /* CONFIG_NFSD_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 IS_ENABLED(CONFIG_NFSD_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_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