Received: by 2002:a05:6a10:6744:0:0:0:0 with SMTP id w4csp1402266pxu; Fri, 16 Oct 2020 11:01:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxdIFRD94u41JHfQI8bIIa/zwKtYy8C8VeZstMwlydcx8Bq/t3FRKLtjJ9HHF6C5UEJD6Xz X-Received: by 2002:a17:906:3397:: with SMTP id v23mr4946308eja.212.1602871286610; Fri, 16 Oct 2020 11:01:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602871286; cv=none; d=google.com; s=arc-20160816; b=i++ej6hcJSHY2BwEf3m2Fc3K2xFNpciISsqp4wodTv0lIKytsL8K8nyWwyrBd+Z7FA ihNt5X02a9dRURj64Ntqk+kmH8e8MzK6yHjV/u/8wn0HQ/iWR6MS/I8C671TS19/YOQb LXgsJOExibEb+6Lw3jTxHOWtiyhq6S6WnnwDRL/G2ncX4KFzNHN3eT4qkaQRe1ZFs2gi H2AHc2w4daR1lWzY8IvOKxMXdguv+oo2KxZZOjRu7FvjIKwgMAlJSwgmNAHixb3a66Tu Tk56cbwwC7s0ZLSWpnBRIRb2XavVWnyYtKcR+B+QFqoUAvEve4dZhmWEf/uTYlvQCuFa 4OGw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature:dkim-filter; bh=I9qpbpvmP5M1PsjExDiTQ6DTZMim0zsuYuKgazVNpSs=; b=xtwM9TP4H8aXWKzh5b7rB17FPPGnPhPX9qEmPS/hogiyMnHS2KHul8XykQf/IXPTIP 3SVyDQqgYqHUtP5vf1qutyrp/rONXVnCE7amXiIrVhdgYfuMIT6EhLL4UuS9JdVafjaS qwQwyAFa02cJyxJ010JFmAjhpTlnxyzTcB6HIYnPAwmM7gTXUIkxDBvZF2TIT6c9hjRh Z79Uaa3RbXBpgBQ8HXWk1FB/FMqP0SmrGarLMUUqLZ1VcYu83RDeoxDMMj53DS6QjIKT gbkcqtK3YbpTs/cI11B8tIkxf090myGIEe3BGKYD78ojiBZER1G0WLdjRYjqkBNIoQCp RIGg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@fieldses.org header.s=default header.b=gFfpAtpR; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id n17si2086817eje.315.2020.10.16.11.00.50; Fri, 16 Oct 2020 11:01:26 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@fieldses.org header.s=default header.b=gFfpAtpR; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387509AbgJPR7i (ORCPT + 99 others); Fri, 16 Oct 2020 13:59:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733113AbgJPR7i (ORCPT ); Fri, 16 Oct 2020 13:59:38 -0400 Received: from fieldses.org (fieldses.org [IPv6:2600:3c00:e000:2f7::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0964DC061755 for ; Fri, 16 Oct 2020 10:59:38 -0700 (PDT) Received: by fieldses.org (Postfix, from userid 2815) id 8007C36E1; Fri, 16 Oct 2020 13:59:36 -0400 (EDT) DKIM-Filter: OpenDKIM Filter v2.11.0 fieldses.org 8007C36E1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fieldses.org; s=default; t=1602871176; bh=I9qpbpvmP5M1PsjExDiTQ6DTZMim0zsuYuKgazVNpSs=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=gFfpAtpRwiyFBdkDwyGmcQ3ZkQO3S7Fn6doHJxnahoHELstxla4UGbgKh3bdt06LF xUPvyFao2L/GMojtx/0i7/klanV5axShm67tJL4z5f3Q2AZsE2cNIDFlozqcmRgU4M 1bKx40Io+Qi7OQn7QrXnda5SBsb+Ce0M4eCuyruc= Date: Fri, 16 Oct 2020 13:59:36 -0400 From: "J. Bruce Fields" To: Dai Ngo Cc: linux-nfs@vger.kernel.org Subject: Re: [PATCH v3 1/1] NFSv4.2: Fix NFS4ERR_STALE error when doing inter server copy Message-ID: <20201016175936.GA7332@fieldses.org> References: <20201009062819.92173-2-dai.ngo@oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20201009062819.92173-2-dai.ngo@oracle.com> User-Agent: Mutt/1.5.21 (2010-09-15) Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org On Fri, Oct 09, 2020 at 02:28:19AM -0400, Dai Ngo wrote: > NFS_FS=y as dependency of CONFIG_NFSD_V4_2_INTER_SSC still have > build errors and some configs with NFSD=m to get NFS4ERR_STALE > error when doing inter server copy. > > Added ops table in nfs_common for knfsd to access NFS client modules. This looks like a good start, but I think it could be a lot simpler: > > Fixes: 3ac3711adb88 ("NFSD: Fix NFS server build errors") > Signed-off-by: Dai Ngo > --- > changes from v2: fix 0-day build issues. > --- > fs/nfs/nfs4file.c | 40 +++++++++++-- > fs/nfs/nfs4super.c | 6 ++ > fs/nfs/super.c | 20 +++++++ > fs/nfs_common/Makefile | 1 + > fs/nfs_common/nfs_ssc.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ > fs/nfsd/Kconfig | 2 +- > fs/nfsd/nfs4proc.c | 3 +- > include/linux/nfs_ssc.h | 77 +++++++++++++++++++++++++ > 8 files changed, 289 insertions(+), 8 deletions(-) > create mode 100644 fs/nfs_common/nfs_ssc.c > create mode 100644 include/linux/nfs_ssc.h > > diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c > index fdfc77486ace..7d242fcb134a 100644 > --- a/fs/nfs/nfs4file.c > +++ b/fs/nfs/nfs4file.c > @@ -9,6 +9,7 @@ > #include > #include > #include > +#include > #include "delegation.h" > #include "internal.h" > #include "iostat.h" > @@ -314,9 +315,8 @@ static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off, > static int read_name_gen = 1; > #define SSC_READ_NAME_BODY "ssc_read_%d" > > -struct file * > -nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh, > - nfs4_stateid *stateid) > +static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt, > + struct nfs_fh *src_fh, nfs4_stateid *stateid) > { > struct nfs_fattr fattr; > struct file *filep, *res; > @@ -398,14 +398,42 @@ struct file * > fput(filep); > goto out_free_name; > } > -EXPORT_SYMBOL_GPL(nfs42_ssc_open); > -void nfs42_ssc_close(struct file *filep) > + > +static void __nfs42_ssc_close(struct file *filep) > { > struct nfs_open_context *ctx = nfs_file_open_context(filep); > > ctx->state->flags = 0; > } > -EXPORT_SYMBOL_GPL(nfs42_ssc_close); > + > +static const struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_tbl = { > + .sco_owner = THIS_MODULE, > + .sco_open = __nfs42_ssc_open, > + .sco_close = __nfs42_ssc_close, > +}; > + > +/** > + * nfs42_ssc_register_ops - Wrapper to register NFS_V4 ops in nfs_common > + * > + * Return values: > + * On success, returns 0 > + * %-EINVAL if validation check fails > + */ > +int nfs42_ssc_register_ops(void) > +{ > + return nfs42_ssc_register(&nfs4_ssc_clnt_ops_tbl); > +} > + > +/** > + * nfs42_ssc_unregister_ops - wrapper to un-register NFS_V4 ops in nfs_common > + * > + * Return values: > + * None. > + */ > +void nfs42_ssc_unregister_ops(void) > +{ > + nfs42_ssc_unregister(&nfs4_ssc_clnt_ops_tbl); > +} > #endif /* CONFIG_NFS_V4_2 */ > > const struct file_operations nfs4_file_operations = { > diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c > index 0c1ab846b83d..ed0c1f9fc890 100644 > --- a/fs/nfs/nfs4super.c > +++ b/fs/nfs/nfs4super.c > @@ -7,6 +7,7 @@ > #include > #include > #include > +#include > #include "delegation.h" > #include "internal.h" > #include "nfs4_fs.h" > @@ -273,6 +274,10 @@ static int __init init_nfs_v4(void) > err = nfs4_xattr_cache_init(); > if (err) > goto out2; > + > + err = nfs42_ssc_register_ops(); > + if (err) > + goto out2; > #endif > > err = nfs4_register_sysctl(); > @@ -297,6 +302,7 @@ static void __exit exit_nfs_v4(void) > unregister_nfs_version(&nfs_v4); > #ifdef CONFIG_NFS_V4_2 > nfs4_xattr_cache_exit(); > + nfs42_ssc_unregister_ops(); > #endif > nfs4_unregister_sysctl(); > nfs_idmap_quit(); > diff --git a/fs/nfs/super.c b/fs/nfs/super.c > index 7a70287f21a2..65636fef6a00 100644 > --- a/fs/nfs/super.c > +++ b/fs/nfs/super.c > @@ -57,6 +57,7 @@ > #include > > #include > +#include > > #include "nfs4_fs.h" > #include "callback.h" > @@ -85,6 +86,11 @@ > }; > EXPORT_SYMBOL_GPL(nfs_sops); > > +static const struct nfs_ssc_client_ops nfs_ssc_clnt_ops_tbl = { > + .sco_owner = THIS_MODULE, > + .sco_sb_deactive = nfs_sb_deactive, > +}; > + > #if IS_ENABLED(CONFIG_NFS_V4) > static int __init register_nfs4_fs(void) > { > @@ -106,6 +112,16 @@ static void unregister_nfs4_fs(void) > } > #endif > > +static int nfs_ssc_register_ops(void) > +{ > + return nfs_ssc_register(&nfs_ssc_clnt_ops_tbl); > +} > + > +static void nfs_ssc_unregister_ops(void) > +{ > + nfs_ssc_unregister(&nfs_ssc_clnt_ops_tbl); > +} > + > static struct shrinker acl_shrinker = { > .count_objects = nfs_access_cache_count, > .scan_objects = nfs_access_cache_scan, > @@ -133,6 +149,9 @@ int __init register_nfs_fs(void) > ret = register_shrinker(&acl_shrinker); > if (ret < 0) > goto error_3; > + ret = nfs_ssc_register_ops(); > + if (ret < 0) > + goto error_3; > return 0; > error_3: > nfs_unregister_sysctl(); > @@ -152,6 +171,7 @@ void __exit unregister_nfs_fs(void) > unregister_shrinker(&acl_shrinker); > nfs_unregister_sysctl(); > unregister_nfs4_fs(); > + nfs_ssc_unregister_ops(); > unregister_filesystem(&nfs_fs_type); > } > > diff --git a/fs/nfs_common/Makefile b/fs/nfs_common/Makefile > index 4bebe834c009..fa82f5aaa6d9 100644 > --- a/fs/nfs_common/Makefile > +++ b/fs/nfs_common/Makefile > @@ -7,3 +7,4 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o > nfs_acl-objs := nfsacl.o > > obj-$(CONFIG_GRACE_PERIOD) += grace.o > +obj-$(CONFIG_GRACE_PERIOD) += nfs_ssc.o > diff --git a/fs/nfs_common/nfs_ssc.c b/fs/nfs_common/nfs_ssc.c > new file mode 100644 > index 000000000000..6d99a6d2d6b9 > --- /dev/null > +++ b/fs/nfs_common/nfs_ssc.c > @@ -0,0 +1,148 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * fs/nfs_common/nfs_ssc_comm.c > + * > + * Helper for knfsd's SSC to access ops in NFS client modules > + * > + * Author: Dai Ngo > + * > + * Copyright (c) 2020, Oracle and/or its affiliates. > + */ > + > +#include > +#include > +#include > +#include "../nfs/nfs4_fs.h" > + > +MODULE_LICENSE("GPL"); > + > +/* > + * NFS_FS > + */ > +static void nfs_sb_deactive_def(struct super_block *sb); > + > +static struct nfs_ssc_client_ops nfs_ssc_clnt_ops_def = { > + .sco_owner = THIS_MODULE, > + .sco_sb_deactive = nfs_sb_deactive_def, > +}; > + > +/* > + * NFS_V4 > + */ > +static struct file *nfs42_ssc_open_def(struct vfsmount *ss_mnt, > + struct nfs_fh *src_fh, nfs4_stateid *stateid); > +static void nfs42_ssc_close_def(struct file *filep); > + > +static struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_def = { > + .sco_owner = THIS_MODULE, > + .sco_open = nfs42_ssc_open_def, > + .sco_close = nfs42_ssc_close_def, > +}; > + > + > +struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl = { > + .ssc_nfs4_ops = &nfs4_ssc_clnt_ops_def, > + .ssc_nfs_ops = &nfs_ssc_clnt_ops_def > +}; > +EXPORT_SYMBOL_GPL(nfs_ssc_client_tbl); > + > + > +static struct file *nfs42_ssc_open_def(struct vfsmount *ss_mnt, > + struct nfs_fh *src_fh, nfs4_stateid *stateid) > +{ > + return ERR_PTR(-EIO); > +} > + > +static void nfs42_ssc_close_def(struct file *filep) > +{ > +} I don't think we need any of these "_def" ops. We just shouldn't be calling any of these ops in the case the operations aren't loaded. > + > +#ifdef CONFIG_NFS_V4_2 > +/** > + * nfs42_ssc_register - install the NFS_V4 client ops in the nfs_ssc_client_tbl > + * @ops: NFS_V4 ops to be installed > + * > + * Return values: > + * On success, return 0 > + * %-EINVAL if validation check fails > + */ > +int nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops) > +{ > + if (ops == NULL || ops->sco_open == NULL || ops->sco_close == NULL) > + return -EINVAL; This function only has one caller, and we know it won't do these things. It's not worth the check and the error handling in the caller for something so unlikely. > + nfs_ssc_client_tbl.ssc_nfs4_ops = ops; > + return 0; > +} > +EXPORT_SYMBOL_GPL(nfs42_ssc_register); > + > +/** > + * nfs42_ssc_unregister - uninstall the NFS_V4 client ops from > + * the nfs_ssc_client_tbl > + * @ops: ops to be uninstalled > + * > + * Return values: > + * None > + */ > +void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops) > +{ > + if (nfs_ssc_client_tbl.ssc_nfs4_ops != ops) > + return; > + > + nfs_ssc_client_tbl.ssc_nfs4_ops = &nfs4_ssc_clnt_ops_def; > +} > +EXPORT_SYMBOL_GPL(nfs42_ssc_unregister); > +#endif /* CONFIG_NFS_V4_2 */ > + > +/* > + * NFS_FS > + */ > +static void nfs_sb_deactive_def(struct super_block *sb) > +{ > +} > + > +#ifdef CONFIG_NFS_V4_2 > +/** > + * nfs_ssc_register - install the NFS_FS client ops in the nfs_ssc_client_tbl > + * @ops: NFS_FS ops to be installed > + * > + * Return values: > + * On success, return 0 > + * %-EINVAL if validation check fails > + */ > +int nfs_ssc_register(const struct nfs_ssc_client_ops *ops) > +{ > + if (ops == NULL || ops->sco_sb_deactive == NULL) > + return -EINVAL; Ditto, let's drop these checks. > + nfs_ssc_client_tbl.ssc_nfs_ops = ops; > + return 0; > +} > +EXPORT_SYMBOL_GPL(nfs_ssc_register); > + > +/** > + * nfs_ssc_unregister - uninstall the NFS_FS client ops from > + * the nfs_ssc_client_tbl > + * @ops: ops to be uninstalled > + * > + * Return values: > + * None > + */ > +void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops) > +{ > + if (nfs_ssc_client_tbl.ssc_nfs_ops != ops) > + return; > + nfs_ssc_client_tbl.ssc_nfs_ops = &nfs_ssc_clnt_ops_def; > +} > +EXPORT_SYMBOL_GPL(nfs_ssc_unregister); > + > +#else > +int nfs_ssc_register(const struct nfs_ssc_client_ops *ops) > +{ > + return 0; > +} > +EXPORT_SYMBOL_GPL(nfs_ssc_register); > + > +void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops) > +{ > +} > +EXPORT_SYMBOL_GPL(nfs_ssc_unregister); > +#endif /* CONFIG_NFS_V4_2 */ > diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig > index 99d2cae91bd6..f368f3215f88 100644 > --- a/fs/nfsd/Kconfig > +++ b/fs/nfsd/Kconfig > @@ -136,7 +136,7 @@ config NFSD_FLEXFILELAYOUT > > config NFSD_V4_2_INTER_SSC > bool "NFSv4.2 inter server to server COPY" > - depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2 && NFS_FS=y > + depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2 > help > This option enables support for NFSv4.2 inter server to > server copy where the destination server calls the NFSv4.2 > diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c > index eaf50eafa935..84e10aef1417 100644 > --- a/fs/nfsd/nfs4proc.c > +++ b/fs/nfsd/nfs4proc.c > @@ -38,6 +38,7 @@ > #include > #include > #include > +#include > > #include "idmap.h" > #include "cache.h" > @@ -1247,7 +1248,7 @@ extern struct file *nfs42_ssc_open(struct vfsmount *ss_mnt, > static void > nfsd4_interssc_disconnect(struct vfsmount *ss_mnt) > { > - nfs_sb_deactive(ss_mnt->mnt_sb); > + nfs_do_sb_deactive(ss_mnt->mnt_sb); > mntput(ss_mnt); > } > > diff --git a/include/linux/nfs_ssc.h b/include/linux/nfs_ssc.h > new file mode 100644 > index 000000000000..45a763bd6b0b > --- /dev/null > +++ b/include/linux/nfs_ssc.h > @@ -0,0 +1,77 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * include/linux/nfs_ssc.h > + * > + * Author: Dai Ngo > + * > + * Copyright (c) 2020, Oracle and/or its affiliates. > + */ > + > +#include > + > +extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl; > + > +/* > + * NFS_V4 > + */ > +struct nfs4_ssc_client_ops { > + struct module *sco_owner; > + struct file *(*sco_open)(struct vfsmount *ss_mnt, > + struct nfs_fh *src_fh, nfs4_stateid *stateid); > + void (*sco_close)(struct file *filep); > +}; > + > +/* > + * NFS_FS > + */ > +struct nfs_ssc_client_ops { > + struct module *sco_owner; > + void (*sco_sb_deactive)(struct super_block *sb); > +}; > + > +struct nfs_ssc_client_ops_tbl { > + const struct nfs4_ssc_client_ops *ssc_nfs4_ops; > + const struct nfs_ssc_client_ops *ssc_nfs_ops; > +}; > + > +extern int nfs42_ssc_register_ops(void); > +extern void nfs42_ssc_unregister_ops(void); > + > +extern int nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops); > +extern void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops); > + > +#ifdef CONFIG_NFSD_V4_2_INTER_SSC > +static inline struct file *nfs42_ssc_open(struct vfsmount *ss_mnt, > + struct nfs_fh *src_fh, nfs4_stateid *stateid) > +{ > + struct file *file; > + > + if (!try_module_get(nfs_ssc_client_tbl.ssc_nfs4_ops->sco_owner)) > + return ERR_PTR(-EIO); The module load already happened back when we did the get_fs_type in nfsd4_interssc_connect(), and it's not going away at this point (or there's something already terribly wrong with ss_mnt). So I don't think we need any try_module_get()s or module_put()s. --b. > + file = (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_open)(ss_mnt, src_fh, stateid); > + module_put(nfs_ssc_client_tbl.ssc_nfs4_ops->sco_owner); > + return file; > +} > + > +static inline void nfs42_ssc_close(struct file *filep) > +{ > + if (!try_module_get(nfs_ssc_client_tbl.ssc_nfs4_ops->sco_owner)) > + return; > + (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_close)(filep); > + module_put(nfs_ssc_client_tbl.ssc_nfs4_ops->sco_owner); > +} > +#endif > + > +/* > + * NFS_FS > + */ > +extern int nfs_ssc_register(const struct nfs_ssc_client_ops *ops); > +extern void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops); > + > +static inline void nfs_do_sb_deactive(struct super_block *sb) > +{ > + if (!try_module_get(nfs_ssc_client_tbl.ssc_nfs_ops->sco_owner)) > + return; > + (*nfs_ssc_client_tbl.ssc_nfs_ops->sco_sb_deactive)(sb); > + module_put(nfs_ssc_client_tbl.ssc_nfs_ops->sco_owner); > +} > -- > 1.8.3.1