* [PATCH 0/2] Fixes for the NFS automounter @ 2025-08-04 1:29 Trond Myklebust 2025-08-04 1:29 ` [PATCH 1/2] NFS: Fix the setting of capabilities when automounting a new filesystem Trond Myklebust ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Trond Myklebust @ 2025-08-04 1:29 UTC (permalink / raw) To: linux-nfs From: Trond Myklebust <trond.myklebust@hammerspace.com> This series addresses 2 sets of issues with the NFS automount functionality: 1. Capabilities are being inherited from the parent directory instead of assuming that the subdirectory may have different properties than the parent. This is particularly problematic when the parent is a referral. 2. We appear to be repeating some operations unnecessarily when traversing a submount point. Trond Myklebust (2): NFS: Fix the setting of capabilities when automounting a new filesystem NFSv4: Remove duplicate lookups, capability probes and fsinfo calls fs/nfs/client.c | 44 +++++++++++++++++++++- fs/nfs/internal.h | 2 +- fs/nfs/nfs4_fs.h | 5 ++- fs/nfs/nfs4client.c | 20 +--------- fs/nfs/nfs4getroot.c | 14 +++---- fs/nfs/nfs4proc.c | 89 ++++++++++++++++++++------------------------ 6 files changed, 93 insertions(+), 81 deletions(-) -- 2.50.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] NFS: Fix the setting of capabilities when automounting a new filesystem 2025-08-04 1:29 [PATCH 0/2] Fixes for the NFS automounter Trond Myklebust @ 2025-08-04 1:29 ` Trond Myklebust 2025-08-04 16:07 ` Benjamin Coddington 2025-08-04 1:29 ` [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls Trond Myklebust 2025-08-24 7:00 ` [PATCH 0/2] Fixes for the NFS automounter Scott Haiden 2 siblings, 1 reply; 9+ messages in thread From: Trond Myklebust @ 2025-08-04 1:29 UTC (permalink / raw) To: linux-nfs From: Trond Myklebust <trond.myklebust@hammerspace.com> Capabilities cannot be inherited when we cross into a new filesystem. They need to be reset to the minimal defaults, and then probed for again. Fixes: 54ceac451598 ("NFS: Share NFS superblocks per-protocol per-server per-FSID") Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> --- fs/nfs/client.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- fs/nfs/internal.h | 2 +- fs/nfs/nfs4client.c | 20 +------------------- fs/nfs/nfs4proc.c | 2 +- 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index e13eb429b8b5..8fb4a950dd55 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -682,6 +682,44 @@ struct nfs_client *nfs_init_client(struct nfs_client *clp, } EXPORT_SYMBOL_GPL(nfs_init_client); +static void nfs4_server_set_init_caps(struct nfs_server *server) +{ +#if IS_ENABLED(CONFIG_NFS_V4) + /* Set the basic capabilities */ + server->caps = server->nfs_client->cl_mvops->init_caps; + if (server->flags & NFS_MOUNT_NORDIRPLUS) + server->caps &= ~NFS_CAP_READDIRPLUS; + if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA) + server->caps &= ~NFS_CAP_READ_PLUS; + + /* + * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower + * authentication. + */ + if (nfs4_disable_idmapping && + server->client->cl_auth->au_flavor == RPC_AUTH_UNIX) + server->caps |= NFS_CAP_UIDGID_NOMAP; +#endif +} + +void nfs_server_set_init_caps(struct nfs_server *server) +{ + switch (server->nfs_client->rpc_ops->version) { + case 2: + server->caps = NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; + break; + case 3: + server->caps = NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; + if (!(server->flags & NFS_MOUNT_NORDIRPLUS)) + server->caps |= NFS_CAP_READDIRPLUS; + break; + default: + nfs4_server_set_init_caps(server); + break; + } +} +EXPORT_SYMBOL_GPL(nfs_server_set_init_caps); + /* * Create a version 2 or 3 client */ @@ -726,7 +764,6 @@ static int nfs_init_server(struct nfs_server *server, /* Initialise the client representation from the mount data */ server->flags = ctx->flags; server->options = ctx->options; - server->caps |= NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; switch (clp->rpc_ops->version) { case 2: @@ -762,6 +799,8 @@ static int nfs_init_server(struct nfs_server *server, if (error < 0) goto error; + nfs_server_set_init_caps(server); + /* Preserve the values of mount_server-related mount options */ if (ctx->mount_server.addrlen) { memcpy(&server->mountd_address, &ctx->mount_server.address, @@ -934,7 +973,6 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour target->acregmax = source->acregmax; target->acdirmin = source->acdirmin; target->acdirmax = source->acdirmax; - target->caps = source->caps; target->options = source->options; target->auth_info = source->auth_info; target->port = source->port; @@ -1169,6 +1207,8 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, if (error < 0) goto out_free_server; + nfs_server_set_init_caps(server); + /* probe the filesystem info for this server filesystem */ error = nfs_probe_server(server, fh); if (error < 0) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 0143e0794d32..1a18d8d9be25 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -231,7 +231,7 @@ extern struct nfs_client * nfs4_find_client_sessionid(struct net *, const struct sockaddr *, struct nfs4_sessionid *, u32); extern struct nfs_server *nfs_create_server(struct fs_context *); -extern void nfs4_server_set_init_caps(struct nfs_server *); +extern void nfs_server_set_init_caps(struct nfs_server *); extern struct nfs_server *nfs4_create_server(struct fs_context *); extern struct nfs_server *nfs4_create_referral_server(struct fs_context *); extern int nfs4_update_server(struct nfs_server *server, const char *hostname, diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 2ea98f1f116f..6fddf43d729c 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -1074,24 +1074,6 @@ static void nfs4_session_limit_xasize(struct nfs_server *server) #endif } -void nfs4_server_set_init_caps(struct nfs_server *server) -{ - /* Set the basic capabilities */ - server->caps |= server->nfs_client->cl_mvops->init_caps; - if (server->flags & NFS_MOUNT_NORDIRPLUS) - server->caps &= ~NFS_CAP_READDIRPLUS; - if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA) - server->caps &= ~NFS_CAP_READ_PLUS; - - /* - * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower - * authentication. - */ - if (nfs4_disable_idmapping && - server->client->cl_auth->au_flavor == RPC_AUTH_UNIX) - server->caps |= NFS_CAP_UIDGID_NOMAP; -} - static int nfs4_server_common_setup(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_probe) { @@ -1110,7 +1092,7 @@ static int nfs4_server_common_setup(struct nfs_server *server, if (error < 0) return error; - nfs4_server_set_init_caps(server); + nfs_server_set_init_caps(server); /* Probe the root fh to retrieve its FSID and filehandle */ error = nfs4_get_rootfh(server, mntfh, auth_probe); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d7dc669d84c5..c7c7ec22f21d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4092,7 +4092,7 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) }; int err; - nfs4_server_set_init_caps(server); + nfs_server_set_init_caps(server); do { err = nfs4_handle_exception(server, _nfs4_server_capabilities(server, fhandle), -- 2.50.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] NFS: Fix the setting of capabilities when automounting a new filesystem 2025-08-04 1:29 ` [PATCH 1/2] NFS: Fix the setting of capabilities when automounting a new filesystem Trond Myklebust @ 2025-08-04 16:07 ` Benjamin Coddington 0 siblings, 0 replies; 9+ messages in thread From: Benjamin Coddington @ 2025-08-04 16:07 UTC (permalink / raw) To: Trond Myklebust; +Cc: linux-nfs On 3 Aug 2025, at 21:29, Trond Myklebust wrote: > From: Trond Myklebust <trond.myklebust@hammerspace.com> > > Capabilities cannot be inherited when we cross into a new filesystem. > They need to be reset to the minimal defaults, and then probed for > again. > > Fixes: 54ceac451598 ("NFS: Share NFS superblocks per-protocol per-server per-FSID") > Cc: stable@vger.kernel.org > Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Reviewed-by: Benjamin Coddington <bcodding@redhat.com> Ben ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls 2025-08-04 1:29 [PATCH 0/2] Fixes for the NFS automounter Trond Myklebust 2025-08-04 1:29 ` [PATCH 1/2] NFS: Fix the setting of capabilities when automounting a new filesystem Trond Myklebust @ 2025-08-04 1:29 ` Trond Myklebust 2025-08-04 16:43 ` Benjamin Coddington 2025-08-24 7:00 ` [PATCH 0/2] Fixes for the NFS automounter Scott Haiden 2 siblings, 1 reply; 9+ messages in thread From: Trond Myklebust @ 2025-08-04 1:29 UTC (permalink / raw) To: linux-nfs From: Trond Myklebust <trond.myklebust@hammerspace.com> When crossing into a new filesystem, the NFSv4 client will look up the new directory, and then call nfs4_server_capabilities() as well as nfs4_do_fsinfo() at least twice. This patch removes the duplicate calls, and reduces the initial lookup to retrieve just a minimal set of attributes. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> --- fs/nfs/nfs4_fs.h | 5 ++- fs/nfs/nfs4getroot.c | 14 +++---- fs/nfs/nfs4proc.c | 87 ++++++++++++++++++++------------------------ 3 files changed, 48 insertions(+), 58 deletions(-) diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index d3ca91f60fc1..c34c89af9c7d 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -63,7 +63,7 @@ struct nfs4_minor_version_ops { bool (*match_stateid)(const nfs4_stateid *, const nfs4_stateid *); int (*find_root_sec)(struct nfs_server *, struct nfs_fh *, - struct nfs_fsinfo *); + struct nfs_fattr *); void (*free_lock_state)(struct nfs_server *, struct nfs4_lock_state *); int (*test_and_free_expired)(struct nfs_server *, @@ -296,7 +296,8 @@ extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *, extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int, int); extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, const struct cred *, struct nfs4_setclientid_res *); extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, const struct cred *); -extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool); +extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, + struct nfs_fattr *, bool); extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, const struct cred *cred); extern int nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cred); extern int nfs4_destroy_clientid(struct nfs_client *clp); diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c index 1a69479a3a59..e67ea345de69 100644 --- a/fs/nfs/nfs4getroot.c +++ b/fs/nfs/nfs4getroot.c @@ -12,30 +12,28 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_probe) { - struct nfs_fsinfo fsinfo; + struct nfs_fattr *fattr = nfs_alloc_fattr(); int ret = -ENOMEM; - fsinfo.fattr = nfs_alloc_fattr(); - if (fsinfo.fattr == NULL) + if (fattr == NULL) goto out; /* Start by getting the root filehandle from the server */ - ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo, auth_probe); + ret = nfs4_proc_get_rootfh(server, mntfh, fattr, auth_probe); if (ret < 0) { dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret); goto out; } - if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE) - || !S_ISDIR(fsinfo.fattr->mode)) { + if (!(fattr->valid & NFS_ATTR_FATTR_TYPE) || !S_ISDIR(fattr->mode)) { printk(KERN_ERR "nfs4_get_rootfh:" " getroot encountered non-directory\n"); ret = -ENOTDIR; goto out; } - memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid)); + memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); out: - nfs_free_fattr(fsinfo.fattr); + nfs_free_fattr(fattr); return ret; } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c7c7ec22f21d..7d2b67e06cc3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4240,15 +4240,18 @@ static int nfs4_discover_trunking(struct nfs_server *server, } static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info) + struct nfs_fattr *fattr) { - u32 bitmask[3]; + u32 bitmask[3] = { + [0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE | + FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID, + }; struct nfs4_lookup_root_arg args = { .bitmask = bitmask, }; struct nfs4_lookup_res res = { .server = server, - .fattr = info->fattr, + .fattr = fattr, .fh = fhandle, }; struct rpc_message msg = { @@ -4257,27 +4260,20 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, .rpc_resp = &res, }; - bitmask[0] = nfs4_fattr_bitmap[0]; - bitmask[1] = nfs4_fattr_bitmap[1]; - /* - * Process the label in the upcoming getfattr - */ - bitmask[2] = nfs4_fattr_bitmap[2] & ~FATTR4_WORD2_SECURITY_LABEL; - - nfs_fattr_init(info->fattr); + nfs_fattr_init(fattr); return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info) + struct nfs_fattr *fattr) { struct nfs4_exception exception = { .interruptible = true, }; int err; do { - err = _nfs4_lookup_root(server, fhandle, info); - trace_nfs4_lookup_root(server, fhandle, info->fattr, err); + err = _nfs4_lookup_root(server, fhandle, fattr); + trace_nfs4_lookup_root(server, fhandle, fattr, err); switch (err) { case 0: case -NFS4ERR_WRONGSEC: @@ -4290,8 +4286,9 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, return err; } -static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info, rpc_authflavor_t flavor) +static int nfs4_lookup_root_sec(struct nfs_server *server, + struct nfs_fh *fhandle, struct nfs_fattr *fattr, + rpc_authflavor_t flavor) { struct rpc_auth_create_args auth_args = { .pseudoflavor = flavor, @@ -4301,7 +4298,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl auth = rpcauth_create(&auth_args, server->client); if (IS_ERR(auth)) return -EACCES; - return nfs4_lookup_root(server, fhandle, info); + return nfs4_lookup_root(server, fhandle, fattr); } /* @@ -4314,7 +4311,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl * negative errno value. */ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info) + struct nfs_fattr *fattr) { /* Per 3530bis 15.33.5 */ static const rpc_authflavor_t flav_array[] = { @@ -4330,8 +4327,9 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, if (server->auth_info.flavor_len > 0) { /* try each flavor specified by user */ for (i = 0; i < server->auth_info.flavor_len; i++) { - status = nfs4_lookup_root_sec(server, fhandle, info, - server->auth_info.flavors[i]); + status = nfs4_lookup_root_sec( + server, fhandle, fattr, + server->auth_info.flavors[i]); if (status == -NFS4ERR_WRONGSEC || status == -EACCES) continue; break; @@ -4339,7 +4337,7 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, } else { /* no flavors specified by user, try default list */ for (i = 0; i < ARRAY_SIZE(flav_array); i++) { - status = nfs4_lookup_root_sec(server, fhandle, info, + status = nfs4_lookup_root_sec(server, fhandle, fattr, flav_array[i]); if (status == -NFS4ERR_WRONGSEC || status == -EACCES) continue; @@ -4363,28 +4361,22 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, * nfs4_proc_get_rootfh - get file handle for server's pseudoroot * @server: initialized nfs_server handle * @fhandle: we fill in the pseudo-fs root file handle - * @info: we fill in an FSINFO struct + * @fattr: we fill in a bare bones struct fattr * @auth_probe: probe the auth flavours * * Returns zero on success, or a negative errno. */ int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info, - bool auth_probe) + struct nfs_fattr *fattr, bool auth_probe) { int status = 0; if (!auth_probe) - status = nfs4_lookup_root(server, fhandle, info); + status = nfs4_lookup_root(server, fhandle, fattr); if (auth_probe || status == NFS4ERR_WRONGSEC) - status = server->nfs_client->cl_mvops->find_root_sec(server, - fhandle, info); - - if (status == 0) - status = nfs4_server_capabilities(server, fhandle); - if (status == 0) - status = nfs4_do_fsinfo(server, fhandle, info); + status = server->nfs_client->cl_mvops->find_root_sec( + server, fhandle, fattr); return nfs4_map_errors(status); } @@ -10351,10 +10343,10 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if * possible) as per RFC3530bis and RFC5661 Security Considerations sections */ -static int -_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info, - struct nfs4_secinfo_flavors *flavors, bool use_integrity) +static int _nfs41_proc_secinfo_no_name(struct nfs_server *server, + struct nfs_fh *fhandle, + struct nfs4_secinfo_flavors *flavors, + bool use_integrity) { struct nfs41_secinfo_no_name_args args = { .style = SECINFO_STYLE_CURRENT_FH, @@ -10398,9 +10390,9 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, return status; } -static int -nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors) +static int nfs41_proc_secinfo_no_name(struct nfs_server *server, + struct nfs_fh *fhandle, + struct nfs4_secinfo_flavors *flavors) { struct nfs4_exception exception = { .interruptible = true, @@ -10412,7 +10404,7 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, /* try to use integrity protection with machine cred */ if (_nfs4_is_integrity_protected(server->nfs_client)) - err = _nfs41_proc_secinfo_no_name(server, fhandle, info, + err = _nfs41_proc_secinfo_no_name(server, fhandle, flavors, true); /* @@ -10422,7 +10414,7 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, * the current filesystem's rpc_client and the user cred. */ if (err == -NFS4ERR_WRONGSEC) - err = _nfs41_proc_secinfo_no_name(server, fhandle, info, + err = _nfs41_proc_secinfo_no_name(server, fhandle, flavors, false); switch (err) { @@ -10438,9 +10430,8 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, return err; } -static int -nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info) +static int nfs41_find_root_sec(struct nfs_server *server, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { int err; struct page *page; @@ -10456,14 +10447,14 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, } flavors = page_address(page); - err = nfs41_proc_secinfo_no_name(server, fhandle, info, flavors); + err = nfs41_proc_secinfo_no_name(server, fhandle, flavors); /* * Fall back on "guess and check" method if * the server doesn't support SECINFO_NO_NAME */ if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) { - err = nfs4_find_root_sec(server, fhandle, info); + err = nfs4_find_root_sec(server, fhandle, fattr); goto out_freepage; } if (err) @@ -10488,8 +10479,8 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, flavor = RPC_AUTH_MAXFLAVOR; if (flavor != RPC_AUTH_MAXFLAVOR) { - err = nfs4_lookup_root_sec(server, fhandle, - info, flavor); + err = nfs4_lookup_root_sec(server, fhandle, fattr, + flavor); if (!err) break; } -- 2.50.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls 2025-08-04 1:29 ` [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls Trond Myklebust @ 2025-08-04 16:43 ` Benjamin Coddington 2025-08-04 16:54 ` Trond Myklebust 0 siblings, 1 reply; 9+ messages in thread From: Benjamin Coddington @ 2025-08-04 16:43 UTC (permalink / raw) To: Trond Myklebust; +Cc: linux-nfs On 3 Aug 2025, at 21:29, Trond Myklebust wrote: > From: Trond Myklebust <trond.myklebust@hammerspace.com> > > When crossing into a new filesystem, the NFSv4 client will look up the > new directory, and then call nfs4_server_capabilities() as well as > nfs4_do_fsinfo() at least twice. > > This patch removes the duplicate calls, and reduces the initial lookup > to retrieve just a minimal set of attributes. > > Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> > --- > fs/nfs/nfs4_fs.h | 5 ++- > fs/nfs/nfs4getroot.c | 14 +++---- > fs/nfs/nfs4proc.c | 87 ++++++++++++++++++++------------------------ > 3 files changed, 48 insertions(+), 58 deletions(-) > > diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h > index d3ca91f60fc1..c34c89af9c7d 100644 > --- a/fs/nfs/nfs4_fs.h > +++ b/fs/nfs/nfs4_fs.h > @@ -63,7 +63,7 @@ struct nfs4_minor_version_ops { > bool (*match_stateid)(const nfs4_stateid *, > const nfs4_stateid *); > int (*find_root_sec)(struct nfs_server *, struct nfs_fh *, > - struct nfs_fsinfo *); > + struct nfs_fattr *); > void (*free_lock_state)(struct nfs_server *, > struct nfs4_lock_state *); > int (*test_and_free_expired)(struct nfs_server *, > @@ -296,7 +296,8 @@ extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *, > extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int, int); > extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, const struct cred *, struct nfs4_setclientid_res *); > extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, const struct cred *); > -extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool); > +extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, > + struct nfs_fattr *, bool); > extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, const struct cred *cred); > extern int nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cred); > extern int nfs4_destroy_clientid(struct nfs_client *clp); > diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c > index 1a69479a3a59..e67ea345de69 100644 > --- a/fs/nfs/nfs4getroot.c > +++ b/fs/nfs/nfs4getroot.c > @@ -12,30 +12,28 @@ > > int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_probe) > { > - struct nfs_fsinfo fsinfo; > + struct nfs_fattr *fattr = nfs_alloc_fattr(); > int ret = -ENOMEM; > > - fsinfo.fattr = nfs_alloc_fattr(); > - if (fsinfo.fattr == NULL) > + if (fattr == NULL) > goto out; > > /* Start by getting the root filehandle from the server */ > - ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo, auth_probe); > + ret = nfs4_proc_get_rootfh(server, mntfh, fattr, auth_probe); > if (ret < 0) { > dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret); > goto out; > } > > - if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE) > - || !S_ISDIR(fsinfo.fattr->mode)) { > + if (!(fattr->valid & NFS_ATTR_FATTR_TYPE) || !S_ISDIR(fattr->mode)) { > printk(KERN_ERR "nfs4_get_rootfh:" > " getroot encountered non-directory\n"); > ret = -ENOTDIR; > goto out; > } > > - memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid)); > + memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); > out: > - nfs_free_fattr(fsinfo.fattr); > + nfs_free_fattr(fattr); > return ret; > } > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c > index c7c7ec22f21d..7d2b67e06cc3 100644 > --- a/fs/nfs/nfs4proc.c > +++ b/fs/nfs/nfs4proc.c > @@ -4240,15 +4240,18 @@ static int nfs4_discover_trunking(struct nfs_server *server, > } > > static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, > - struct nfs_fsinfo *info) > + struct nfs_fattr *fattr) > { > - u32 bitmask[3]; > + u32 bitmask[3] = { > + [0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE | > + FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID, Just a thought when noticing this change -- Don't we want at least FATTR4_WORD0_FILEID and FATTR4_WORD1_MOUNTED_ON_FILEID as well here? Reviewed-by: Benjamin Coddington <bcodding@redhat.com> Ben ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls 2025-08-04 16:43 ` Benjamin Coddington @ 2025-08-04 16:54 ` Trond Myklebust 2025-08-04 19:07 ` Benjamin Coddington 0 siblings, 1 reply; 9+ messages in thread From: Trond Myklebust @ 2025-08-04 16:54 UTC (permalink / raw) To: Benjamin Coddington; +Cc: linux-nfs On Mon, 2025-08-04 at 12:43 -0400, Benjamin Coddington wrote: > On 3 Aug 2025, at 21:29, Trond Myklebust wrote: > > > From: Trond Myklebust <trond.myklebust@hammerspace.com> > > > > When crossing into a new filesystem, the NFSv4 client will look up > > the > > new directory, and then call nfs4_server_capabilities() as well as > > nfs4_do_fsinfo() at least twice. > > > > This patch removes the duplicate calls, and reduces the initial > > lookup > > to retrieve just a minimal set of attributes. > > > > Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> > > --- > > fs/nfs/nfs4_fs.h | 5 ++- > > fs/nfs/nfs4getroot.c | 14 +++---- > > fs/nfs/nfs4proc.c | 87 ++++++++++++++++++++-------------------- > > ---- > > 3 files changed, 48 insertions(+), 58 deletions(-) > > > > diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h > > index d3ca91f60fc1..c34c89af9c7d 100644 > > --- a/fs/nfs/nfs4_fs.h > > +++ b/fs/nfs/nfs4_fs.h > > @@ -63,7 +63,7 @@ struct nfs4_minor_version_ops { > > bool (*match_stateid)(const nfs4_stateid *, > > const nfs4_stateid *); > > int (*find_root_sec)(struct nfs_server *, struct > > nfs_fh *, > > - struct nfs_fsinfo *); > > + struct nfs_fattr *); > > void (*free_lock_state)(struct nfs_server *, > > struct nfs4_lock_state *); > > int (*test_and_free_expired)(struct nfs_server *, > > @@ -296,7 +296,8 @@ extern int nfs4_call_sync(struct rpc_clnt *, > > struct nfs_server *, > > extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct > > nfs4_sequence_res *, int, int); > > extern int nfs4_proc_setclientid(struct nfs_client *, u32, > > unsigned short, const struct cred *, struct nfs4_setclientid_res > > *); > > extern int nfs4_proc_setclientid_confirm(struct nfs_client *, > > struct nfs4_setclientid_res *arg, const struct cred *); > > -extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh > > *, struct nfs_fsinfo *, bool); > > +extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh > > *, > > + struct nfs_fattr *, bool); > > extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, > > const struct cred *cred); > > extern int nfs4_proc_exchange_id(struct nfs_client *clp, const > > struct cred *cred); > > extern int nfs4_destroy_clientid(struct nfs_client *clp); > > diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c > > index 1a69479a3a59..e67ea345de69 100644 > > --- a/fs/nfs/nfs4getroot.c > > +++ b/fs/nfs/nfs4getroot.c > > @@ -12,30 +12,28 @@ > > > > int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh > > *mntfh, bool auth_probe) > > { > > - struct nfs_fsinfo fsinfo; > > + struct nfs_fattr *fattr = nfs_alloc_fattr(); > > int ret = -ENOMEM; > > > > - fsinfo.fattr = nfs_alloc_fattr(); > > - if (fsinfo.fattr == NULL) > > + if (fattr == NULL) > > goto out; > > > > /* Start by getting the root filehandle from the server */ > > - ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo, > > auth_probe); > > + ret = nfs4_proc_get_rootfh(server, mntfh, fattr, > > auth_probe); > > if (ret < 0) { > > dprintk("nfs4_get_rootfh: getroot error = %d\n", - > > ret); > > goto out; > > } > > > > - if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE) > > - || !S_ISDIR(fsinfo.fattr->mode)) { > > + if (!(fattr->valid & NFS_ATTR_FATTR_TYPE) || > > !S_ISDIR(fattr->mode)) { > > printk(KERN_ERR "nfs4_get_rootfh:" > > " getroot encountered non-directory\n"); > > ret = -ENOTDIR; > > goto out; > > } > > > > - memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server- > > >fsid)); > > + memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); > > out: > > - nfs_free_fattr(fsinfo.fattr); > > + nfs_free_fattr(fattr); > > return ret; > > } > > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c > > index c7c7ec22f21d..7d2b67e06cc3 100644 > > --- a/fs/nfs/nfs4proc.c > > +++ b/fs/nfs/nfs4proc.c > > @@ -4240,15 +4240,18 @@ static int nfs4_discover_trunking(struct > > nfs_server *server, > > } > > > > static int _nfs4_lookup_root(struct nfs_server *server, struct > > nfs_fh *fhandle, > > - struct nfs_fsinfo *info) > > + struct nfs_fattr *fattr) > > { > > - u32 bitmask[3]; > > + u32 bitmask[3] = { > > + [0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE | > > + FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID, > > Just a thought when noticing this change -- > > Don't we want at least FATTR4_WORD0_FILEID and > FATTR4_WORD1_MOUNTED_ON_FILEID as well here? Only FATTR4_WORD0_TYPE and FATTR4_WORD0_FSID are used by the caller, so we don't actually need FATTR4_WORD0_CHANGE or FATTR4_WORD0_SIZE either. I put them in so that the test for the auth flavour would have more chances of catching a problem. Note that neither FATTR4_WORD0_FILEID or FATTR4_WORD1_MOUNTED_ON_FILEID are mandatory attributes, so I also chose to avoid them + all the timestamps for that reason. > > Reviewed-by: Benjamin Coddington <bcodding@redhat.com> > > Ben > -- Trond Myklebust Linux NFS client maintainer, Hammerspace trondmy@kernel.org, trond.myklebust@hammerspace.com ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls 2025-08-04 16:54 ` Trond Myklebust @ 2025-08-04 19:07 ` Benjamin Coddington 2025-08-05 13:35 ` Benjamin Coddington 0 siblings, 1 reply; 9+ messages in thread From: Benjamin Coddington @ 2025-08-04 19:07 UTC (permalink / raw) To: Trond Myklebust; +Cc: linux-nfs On 4 Aug 2025, at 12:54, Trond Myklebust wrote: > On Mon, 2025-08-04 at 12:43 -0400, Benjamin Coddington wrote: >> On 3 Aug 2025, at 21:29, Trond Myklebust wrote: >> >>> From: Trond Myklebust <trond.myklebust@hammerspace.com> >>> >>> When crossing into a new filesystem, the NFSv4 client will look up >>> the >>> new directory, and then call nfs4_server_capabilities() as well as >>> nfs4_do_fsinfo() at least twice. >>> >>> This patch removes the duplicate calls, and reduces the initial >>> lookup >>> to retrieve just a minimal set of attributes. >>> >>> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> >>> --- >>> fs/nfs/nfs4_fs.h | 5 ++- >>> fs/nfs/nfs4getroot.c | 14 +++---- >>> fs/nfs/nfs4proc.c | 87 ++++++++++++++++++++-------------------- >>> ---- >>> 3 files changed, 48 insertions(+), 58 deletions(-) >>> >>> diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h >>> index d3ca91f60fc1..c34c89af9c7d 100644 >>> --- a/fs/nfs/nfs4_fs.h >>> +++ b/fs/nfs/nfs4_fs.h >>> @@ -63,7 +63,7 @@ struct nfs4_minor_version_ops { >>> bool (*match_stateid)(const nfs4_stateid *, >>> const nfs4_stateid *); >>> int (*find_root_sec)(struct nfs_server *, struct >>> nfs_fh *, >>> - struct nfs_fsinfo *); >>> + struct nfs_fattr *); >>> void (*free_lock_state)(struct nfs_server *, >>> struct nfs4_lock_state *); >>> int (*test_and_free_expired)(struct nfs_server *, >>> @@ -296,7 +296,8 @@ extern int nfs4_call_sync(struct rpc_clnt *, >>> struct nfs_server *, >>> extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct >>> nfs4_sequence_res *, int, int); >>> extern int nfs4_proc_setclientid(struct nfs_client *, u32, >>> unsigned short, const struct cred *, struct nfs4_setclientid_res >>> *); >>> extern int nfs4_proc_setclientid_confirm(struct nfs_client *, >>> struct nfs4_setclientid_res *arg, const struct cred *); >>> -extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh >>> *, struct nfs_fsinfo *, bool); >>> +extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh >>> *, >>> + struct nfs_fattr *, bool); >>> extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, >>> const struct cred *cred); >>> extern int nfs4_proc_exchange_id(struct nfs_client *clp, const >>> struct cred *cred); >>> extern int nfs4_destroy_clientid(struct nfs_client *clp); >>> diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c >>> index 1a69479a3a59..e67ea345de69 100644 >>> --- a/fs/nfs/nfs4getroot.c >>> +++ b/fs/nfs/nfs4getroot.c >>> @@ -12,30 +12,28 @@ >>> >>> int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh >>> *mntfh, bool auth_probe) >>> { >>> - struct nfs_fsinfo fsinfo; >>> + struct nfs_fattr *fattr = nfs_alloc_fattr(); >>> int ret = -ENOMEM; >>> >>> - fsinfo.fattr = nfs_alloc_fattr(); >>> - if (fsinfo.fattr == NULL) >>> + if (fattr == NULL) >>> goto out; >>> >>> /* Start by getting the root filehandle from the server */ >>> - ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo, >>> auth_probe); >>> + ret = nfs4_proc_get_rootfh(server, mntfh, fattr, >>> auth_probe); >>> if (ret < 0) { >>> dprintk("nfs4_get_rootfh: getroot error = %d\n", - >>> ret); >>> goto out; >>> } >>> >>> - if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE) >>> - || !S_ISDIR(fsinfo.fattr->mode)) { >>> + if (!(fattr->valid & NFS_ATTR_FATTR_TYPE) || >>> !S_ISDIR(fattr->mode)) { >>> printk(KERN_ERR "nfs4_get_rootfh:" >>> " getroot encountered non-directory\n"); >>> ret = -ENOTDIR; >>> goto out; >>> } .. now I think we won't have fattr->mode here, more below: >>> >>> - memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server- >>>> fsid)); >>> + memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); >>> out: >>> - nfs_free_fattr(fsinfo.fattr); >>> + nfs_free_fattr(fattr); >>> return ret; >>> } >>> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c >>> index c7c7ec22f21d..7d2b67e06cc3 100644 >>> --- a/fs/nfs/nfs4proc.c >>> +++ b/fs/nfs/nfs4proc.c >>> @@ -4240,15 +4240,18 @@ static int nfs4_discover_trunking(struct >>> nfs_server *server, >>> } >>> >>> static int _nfs4_lookup_root(struct nfs_server *server, struct >>> nfs_fh *fhandle, >>> - struct nfs_fsinfo *info) >>> + struct nfs_fattr *fattr) >>> { >>> - u32 bitmask[3]; >>> + u32 bitmask[3] = { >>> + [0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE | >>> + FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID, >> >> Just a thought when noticing this change -- >> >> Don't we want at least FATTR4_WORD0_FILEID and >> FATTR4_WORD1_MOUNTED_ON_FILEID as well here? > > > Only FATTR4_WORD0_TYPE and FATTR4_WORD0_FSID are used by the caller, so > we don't actually need FATTR4_WORD0_CHANGE or FATTR4_WORD0_SIZE either. > I put them in so that the test for the auth flavour would have more > chances of catching a problem. Ah, I see now... we're going to call ->fsinfo() again (as you stated in the description). But I don't see how _CHANGE or _SIZE are used.. and as I was hunting around there's that check in nfs4_get_rootfh() (above) for S_ISDIR(fattr->mode), but this dropped the fsinfo call out of nfs4_proc_get_rootfh(), so I think fattr->mode will never be set. > Note that neither FATTR4_WORD0_FILEID or FATTR4_WORD1_MOUNTED_ON_FILEID > are mandatory attributes, so I also chose to avoid them + all the > timestamps for that reason. Gotcha, making sense. This is tricky for me to review, maybe I should just test it.. :) Ben ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls 2025-08-04 19:07 ` Benjamin Coddington @ 2025-08-05 13:35 ` Benjamin Coddington 0 siblings, 0 replies; 9+ messages in thread From: Benjamin Coddington @ 2025-08-05 13:35 UTC (permalink / raw) To: Trond Myklebust; +Cc: linux-nfs On 4 Aug 2025, at 15:07, Benjamin Coddington wrote: > On 4 Aug 2025, at 12:54, Trond Myklebust wrote: > >> On Mon, 2025-08-04 at 12:43 -0400, Benjamin Coddington wrote: >>> On 3 Aug 2025, at 21:29, Trond Myklebust wrote: >>> >>>> From: Trond Myklebust <trond.myklebust@hammerspace.com> >>>> >>>> When crossing into a new filesystem, the NFSv4 client will look up >>>> the >>>> new directory, and then call nfs4_server_capabilities() as well as >>>> nfs4_do_fsinfo() at least twice. >>>> >>>> This patch removes the duplicate calls, and reduces the initial >>>> lookup >>>> to retrieve just a minimal set of attributes. >>>> >>>> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> >>>> --- >>>> fs/nfs/nfs4_fs.h | 5 ++- >>>> fs/nfs/nfs4getroot.c | 14 +++---- >>>> fs/nfs/nfs4proc.c | 87 ++++++++++++++++++++-------------------- >>>> ---- >>>> 3 files changed, 48 insertions(+), 58 deletions(-) >>>> >>>> diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h >>>> index d3ca91f60fc1..c34c89af9c7d 100644 >>>> --- a/fs/nfs/nfs4_fs.h >>>> +++ b/fs/nfs/nfs4_fs.h >>>> @@ -63,7 +63,7 @@ struct nfs4_minor_version_ops { >>>> bool (*match_stateid)(const nfs4_stateid *, >>>> const nfs4_stateid *); >>>> int (*find_root_sec)(struct nfs_server *, struct >>>> nfs_fh *, >>>> - struct nfs_fsinfo *); >>>> + struct nfs_fattr *); >>>> void (*free_lock_state)(struct nfs_server *, >>>> struct nfs4_lock_state *); >>>> int (*test_and_free_expired)(struct nfs_server *, >>>> @@ -296,7 +296,8 @@ extern int nfs4_call_sync(struct rpc_clnt *, >>>> struct nfs_server *, >>>> extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct >>>> nfs4_sequence_res *, int, int); >>>> extern int nfs4_proc_setclientid(struct nfs_client *, u32, >>>> unsigned short, const struct cred *, struct nfs4_setclientid_res >>>> *); >>>> extern int nfs4_proc_setclientid_confirm(struct nfs_client *, >>>> struct nfs4_setclientid_res *arg, const struct cred *); >>>> -extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh >>>> *, struct nfs_fsinfo *, bool); >>>> +extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh >>>> *, >>>> + struct nfs_fattr *, bool); >>>> extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, >>>> const struct cred *cred); >>>> extern int nfs4_proc_exchange_id(struct nfs_client *clp, const >>>> struct cred *cred); >>>> extern int nfs4_destroy_clientid(struct nfs_client *clp); >>>> diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c >>>> index 1a69479a3a59..e67ea345de69 100644 >>>> --- a/fs/nfs/nfs4getroot.c >>>> +++ b/fs/nfs/nfs4getroot.c >>>> @@ -12,30 +12,28 @@ >>>> >>>> int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh >>>> *mntfh, bool auth_probe) >>>> { >>>> - struct nfs_fsinfo fsinfo; >>>> + struct nfs_fattr *fattr = nfs_alloc_fattr(); >>>> int ret = -ENOMEM; >>>> >>>> - fsinfo.fattr = nfs_alloc_fattr(); >>>> - if (fsinfo.fattr == NULL) >>>> + if (fattr == NULL) >>>> goto out; >>>> >>>> /* Start by getting the root filehandle from the server */ >>>> - ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo, >>>> auth_probe); >>>> + ret = nfs4_proc_get_rootfh(server, mntfh, fattr, >>>> auth_probe); >>>> if (ret < 0) { >>>> dprintk("nfs4_get_rootfh: getroot error = %d\n", - >>>> ret); >>>> goto out; >>>> } >>>> >>>> - if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE) >>>> - || !S_ISDIR(fsinfo.fattr->mode)) { >>>> + if (!(fattr->valid & NFS_ATTR_FATTR_TYPE) || >>>> !S_ISDIR(fattr->mode)) { >>>> printk(KERN_ERR "nfs4_get_rootfh:" >>>> " getroot encountered non-directory\n"); >>>> ret = -ENOTDIR; >>>> goto out; >>>> } > > .. now I think we won't have fattr->mode here, more below: > >>>> >>>> - memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server- >>>>> fsid)); >>>> + memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); >>>> out: >>>> - nfs_free_fattr(fsinfo.fattr); >>>> + nfs_free_fattr(fattr); >>>> return ret; >>>> } >>>> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c >>>> index c7c7ec22f21d..7d2b67e06cc3 100644 >>>> --- a/fs/nfs/nfs4proc.c >>>> +++ b/fs/nfs/nfs4proc.c >>>> @@ -4240,15 +4240,18 @@ static int nfs4_discover_trunking(struct >>>> nfs_server *server, >>>> } >>>> >>>> static int _nfs4_lookup_root(struct nfs_server *server, struct >>>> nfs_fh *fhandle, >>>> - struct nfs_fsinfo *info) >>>> + struct nfs_fattr *fattr) >>>> { >>>> - u32 bitmask[3]; >>>> + u32 bitmask[3] = { >>>> + [0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE | >>>> + FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID, >>> >>> Just a thought when noticing this change -- >>> >>> Don't we want at least FATTR4_WORD0_FILEID and >>> FATTR4_WORD1_MOUNTED_ON_FILEID as well here? >> >> >> Only FATTR4_WORD0_TYPE and FATTR4_WORD0_FSID are used by the caller, so >> we don't actually need FATTR4_WORD0_CHANGE or FATTR4_WORD0_SIZE either. >> I put them in so that the test for the auth flavour would have more >> chances of catching a problem. > > Ah, I see now... we're going to call ->fsinfo() again (as you stated in the > description). > > But I don't see how _CHANGE or _SIZE are used.. and as I was hunting around > there's that check in nfs4_get_rootfh() (above) for S_ISDIR(fattr->mode), but this > dropped the fsinfo call out of nfs4_proc_get_rootfh(), so I think > fattr->mode will never be set. I ran this through some basic testing, and I see now that _TYPE gets into fattr->mode when we decode, which of course makes sense. So, FWIW - this makes sense and looks good to me now. Ben ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] Fixes for the NFS automounter 2025-08-04 1:29 [PATCH 0/2] Fixes for the NFS automounter Trond Myklebust 2025-08-04 1:29 ` [PATCH 1/2] NFS: Fix the setting of capabilities when automounting a new filesystem Trond Myklebust 2025-08-04 1:29 ` [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls Trond Myklebust @ 2025-08-24 7:00 ` Scott Haiden 2 siblings, 0 replies; 9+ messages in thread From: Scott Haiden @ 2025-08-24 7:00 UTC (permalink / raw) To: trondmy; +Cc: linux-nfs Hello, I think this patch (https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=b01f21cacde9f2878492cf318fee61bf4ccad323) might have broken the getxattr system call over NFS. On v6.16.1, I was able to call `getxattr` on files in an NFS 4.2 mount, but with this patch, running the same command I get: $ cd /path/to/nfs4.2/mount $ getfattr -n user.hash.sha512 'S01E01 - Kassa.mkv' S01E01 - Kassa.mkv: user.hash.sha512: Operation not supported Without this patch, it just returns the xattr with no problem. Am I missing a mount option? Or, is it possible this commit introduced a bug? I ran a git bisect between v6.16.1 and v6.16.2 and it pointed to this patch's backport to the stable tree. Thanks, --Scott ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-08-24 7:00 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-08-04 1:29 [PATCH 0/2] Fixes for the NFS automounter Trond Myklebust 2025-08-04 1:29 ` [PATCH 1/2] NFS: Fix the setting of capabilities when automounting a new filesystem Trond Myklebust 2025-08-04 16:07 ` Benjamin Coddington 2025-08-04 1:29 ` [PATCH 2/2] NFSv4: Remove duplicate lookups, capability probes and fsinfo calls Trond Myklebust 2025-08-04 16:43 ` Benjamin Coddington 2025-08-04 16:54 ` Trond Myklebust 2025-08-04 19:07 ` Benjamin Coddington 2025-08-05 13:35 ` Benjamin Coddington 2025-08-24 7:00 ` [PATCH 0/2] Fixes for the NFS automounter Scott Haiden
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).