Re: [PATCH AUTOSEL 6.1 3/9] NFSv4: Always set NLINK even if the server doesn't support it

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 6 Jun 2025 at 17:48, Sasha Levin <sashal@xxxxxxxxxx> wrote:
>
> From: Han Young <hanyang.tony@xxxxxxxxxxxxx>
>
> [ Upstream commit 3a3065352f73381d3a1aa0ccab44aec3a5a9b365 ]
>
> fattr4_numlinks is a recommended attribute, so the client should emulate
> it even if the server doesn't support it. In decode_attr_nlink function
> in nfs4xdr.c, nlink is initialized to 1. However, this default value
> isn't set to the inode due to the check in nfs_fhget.
>
> So if the server doesn't support numlinks, inode's nlink will be zero,
> the mount will fail with error "Stale file handle". Set the nlink to 1
> if the server doesn't support it.
>
> Signed-off-by: Han Young <hanyang.tony@xxxxxxxxxxxxx>
> Signed-off-by: Anna Schumaker <anna.schumaker@xxxxxxxxxx>
> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
> ---
>
> Based on my analysis of the commit and the kernel source code, here is
> my determination: **YES** This commit should be backported to stable
> kernel trees. Here's my extensive analysis: ## Critical Bug Fix Analysis
> ### 1. **Root Cause Understanding** The commit addresses a critical
> issue where NFSv4 mounts fail with "Stale file handle" errors when the
> server doesn't support the `fattr4_numlinks` (NLINK) attribute. Looking
> at the code: - In `/home/sasha/linux/fs/nfs/nfs4xdr.c:3969`, the
> `decode_attr_nlink` function initializes `*nlink = 1` as a default -
> However, in `/home/sasha/linux/fs/nfs/inode.c:556-559`, the current
> logic only sets the inode's nlink if `fattr->valid &
> NFS_ATTR_FATTR_NLINK` is true - When the server doesn't support
> numlinks, the `fattr->valid` flag isn't set, so the inode's nlink
> remains 0 (from initial inode allocation) ### 2. **Impact of Zero
> nlink** From `/home/sasha/linux/fs/nfs/dir.c:1578-1582`, I can see the
> critical check: ```c if (inode->i_nlink > 0 || (inode->i_nlink == 0 &&
> test_bit(NFS_INO_PRESERVE_UNLINKED, &NFS_I(inode)->flags))) return 0;
> else return -ESTALE; ``` When `i_nlink == 0` and the
> `NFS_INO_PRESERVE_UNLINKED` flag isn't set, NFS returns `-ESTALE`,
> causing "Stale file handle" errors and mount failures. ### 3. **Backport
> Suitability Criteria** **✅ Fixes important user-affecting bug**: Mount
> failures prevent basic filesystem functionality **✅ Small and contained
> fix**: The change adds only 2 lines: ```c else if (fattr_supported &
> NFS_ATTR_FATTR_NLINK) nfs_set_cache_invalid(inode,
> NFS_INO_INVALID_NLINK); +else + set_nlink(inode, 1); ``` **✅ Minimal
> regression risk**: Setting nlink=1 as fallback is safe and follows the
> NFSv4 spec (fattr4_numlinks is a "recommended" attribute, so emulation
> is appropriate) **✅ No architectural changes**: This is a targeted fix
> within existing error handling logic **✅ Follows stable tree rules**:
> It's an important bugfix with minimal risk ### 4. **Comparison with
> Similar Commits** Unlike the provided similar commits that were marked
> "NO" (which involved more complex nlink management, cache invalidation
> changes, or feature additions), this commit: - Fixes a fundamental
> compatibility issue - Prevents complete mount failures - Is minimal and
> defensive - Addresses server interoperability problems ### 5. **Server
> Compatibility** This fix ensures NFSv4 clients remain functional with
> servers that don't fully implement all recommended attributes, which is
> critical for real-world deployments where server implementations vary.
> The commit directly prevents mount failures that would otherwise require
> server-side fixes or workarounds, making it essential for stable kernel
> trees where users expect reliable NFS functionality.
>
>  fs/nfs/inode.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
> index f2e66b946f4b4..e774cfc85eeed 100644
> --- a/fs/nfs/inode.c
> +++ b/fs/nfs/inode.c
> @@ -555,6 +555,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
>                         set_nlink(inode, fattr->nlink);
>                 else if (fattr_supported & NFS_ATTR_FATTR_NLINK)
>                         nfs_set_cache_invalid(inode, NFS_INO_INVALID_NLINK);
> +               else
> +                       set_nlink(inode, 1);
>                 if (fattr->valid & NFS_ATTR_FATTR_OWNER)
>                         inode->i_uid = fattr->uid;
>                 else if (fattr_supported & NFS_ATTR_FATTR_OWNER)

How can an application then test whether a filesystem supports hard
links, or not?

Lionel





[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux