From 0cad7630425f4c9ee0dfa376ff8bf60c88ff2566 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 12 May 2026 12:12:42 -0400 Subject: nfs: store the full NFS fileid in inode->i_ino Now that inode->i_ino is a 64-bit value, store the full NFS fileid in it directly instead of an XOR-folded hash. This makes NFS_FILEID() and set_nfs_fileid() operate on inode->i_ino rather than the separate nfsi->fileid field. Since iget5_locked() and ilookup5() now accept a u64 hashval, pass the full fileid as the hash parameter directly. Convert direct nfsi->fileid accesses in nfs_check_inode_attributes(), nfs_update_inode(), and nfs_same_file() to use inode->i_ino. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Jeff Layton Signed-off-by: Anna Schumaker --- include/linux/nfs_fs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 4623262da3c0..8e48053b3069 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -396,12 +396,12 @@ static inline int NFS_STALE(const struct inode *inode) static inline __u64 NFS_FILEID(const struct inode *inode) { - return NFS_I(inode)->fileid; + return inode->i_ino; } static inline void set_nfs_fileid(struct inode *inode, __u64 fileid) { - NFS_I(inode)->fileid = fileid; + inode->i_ino = fileid; } static inline void nfs_mark_for_revalidate(struct inode *inode) -- cgit v1.2.3 From 0e06a884f5ba6226829441bfc656ff9f5e9e90ac Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 12 May 2026 12:12:43 -0400 Subject: nfs: remove nfs_compat_user_ino64() and deprecate enable_ino64 Now that inode->i_ino stores the full 64-bit NFS fileid, the nfs_compat_user_ino64() function is no longer needed. generic_fillattr() already copies inode->i_ino into stat->ino, so the explicit override in nfs_getattr() is also redundant. Also remove the now-unused nfs_fileid_to_ino_t() and nfs_fattr_to_ino_t() helper functions that were used to XOR-fold 64-bit fileids into the old unsigned long i_ino. Keep the enable_ino64 module parameter as a deprecated stub that accepts but ignores the value, logging a notice when set. This avoids breaking existing configurations that pass nfs.enable_ino64 on the kernel command line or in modprobe.d. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Jeff Layton Signed-off-by: Anna Schumaker --- include/linux/nfs_fs.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'include') diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 8e48053b3069..6d6fa62ede10 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -473,7 +473,6 @@ extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context extern void nfs_file_clear_open_context(struct file *flip); extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx); extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); -extern u64 nfs_compat_user_ino64(u64 fileid); extern void nfs_fattr_init(struct nfs_fattr *fattr); extern void nfs_fattr_set_barrier(struct nfs_fattr *fattr); extern unsigned long nfs_inc_attr_generation_counter(void); @@ -668,15 +667,6 @@ static inline loff_t nfs_size_to_loff_t(__u64 size) return min_t(u64, size, OFFSET_MAX); } -static inline ino_t -nfs_fileid_to_ino_t(u64 fileid) -{ - ino_t ino = (ino_t) fileid; - if (sizeof(ino_t) < sizeof(u64)) - ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; - return ino; -} - static inline void nfs_ooo_clear(struct nfs_inode *nfsi) { nfsi->cache_validity &= ~NFS_INO_DATA_INVAL_DEFER; -- cgit v1.2.3 From 2026c8a96afe6e5783497860c4af0a0e1a53991b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 12 May 2026 12:12:44 -0400 Subject: nfs: replace NFS_FILEID() and nfsi->fileid with inode->i_ino Now that inode->i_ino stores the full 64-bit NFS fileid, replace all uses of NFS_FILEID(), set_nfs_fileid(), and direct nfsi->fileid accesses with inode->i_ino throughout the NFS client. Remove the NFS_FILEID() and set_nfs_fileid() helper functions from include/linux/nfs_fs.h since they are no longer needed. Also fix two pre-existing truncation bugs in nfs4trace.h where fileid trace fields were declared as u32 instead of u64. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Jeff Layton Signed-off-by: Anna Schumaker --- include/linux/nfs_fs.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'include') diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 6d6fa62ede10..83063f4ab488 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -394,16 +394,6 @@ static inline int NFS_STALE(const struct inode *inode) return test_bit(NFS_INO_STALE, &NFS_I(inode)->flags); } -static inline __u64 NFS_FILEID(const struct inode *inode) -{ - return inode->i_ino; -} - -static inline void set_nfs_fileid(struct inode *inode, __u64 fileid) -{ - inode->i_ino = fileid; -} - static inline void nfs_mark_for_revalidate(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); -- cgit v1.2.3 From bd5e6b056bd0900d8efde90da7a5877dc50842c7 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 12 May 2026 12:12:45 -0400 Subject: nfs: remove fileid field from struct nfs_inode Now that all NFS client code uses inode->i_ino directly to store and access the 64-bit NFS fileid, the separate fileid field in struct nfs_inode is unused. Remove it to save 8 bytes per NFS inode. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Jeff Layton Signed-off-by: Anna Schumaker --- include/linux/nfs_fs.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'include') diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 83063f4ab488..ec17e602c979 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -145,11 +145,6 @@ struct nfs4_xattr_cache; * nfs fs inode data in memory */ struct nfs_inode { - /* - * The 64bit 'inode number' - */ - __u64 fileid; - /* * NFS file handle */ -- cgit v1.2.3 From 3ff72e1cdf5c337b6acfcf3fcef748c5b9a5316b Mon Sep 17 00:00:00 2001 From: Clark Wang Date: Tue, 2 Jun 2026 19:04:38 +0800 Subject: nfs: keep PG_UPTODATE clear after read errors in page groups When a read request is split into multiple subrequests, earlier completions may advance PG_UPTODATE state for the page group once their bytes fall within hdr->good_bytes. If a later subrequest in the same group then completes with NFS_IOHDR_ERROR, the read path needs to clear any accumulated PG_UPTODATE state and keep later completions from rebuilding it. Otherwise, a subsequent successful subrequest can re-enter nfs_page_group_set_uptodate(), restore the page-group sync state, and leave stale PG_UPTODATE behind for nfs_page_group_destroy() to trip over in nfs_free_request(). Add a sticky page-group read-failed flag. Once any subrequest in the group is known to be bad, mark the group failed, clear any accumulated PG_UPTODATE state, and refuse further PG_UPTODATE synchronization for the rest of the completion walk. Fixes: 67d0338edd71 ("nfs: page group syncing in read path") Signed-off-by: Clark Wang Signed-off-by: Anna Schumaker --- include/linux/nfs_page.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index afe1d8f09d89..4b9a35dbc062 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -33,6 +33,7 @@ enum { PG_TEARDOWN, /* page group sync for destroy */ PG_UNLOCKPAGE, /* page group sync bit in read path */ PG_UPTODATE, /* page group sync bit in read path */ + PG_READ_FAILED, /* page group saw a read error */ PG_WB_END, /* page group sync bit in write path */ PG_REMOVE, /* page group sync bit in write path */ PG_CONTENDED1, /* Is someone waiting for a lock? */ -- cgit v1.2.3 From 4837fb36219e6c08b666bc31a86841bad8526358 Mon Sep 17 00:00:00 2001 From: Yang Erkun Date: Thu, 26 Feb 2026 09:22:03 +0800 Subject: nfs: use nfsi->rwsem to protect traversal of the file lock list Lingfeng identified a bug and suggested two solutions, but both appear to have issues. Generally, we cannot release flc_lock while iterating over the file lock list to avoid use-after-free (UAF) problems with file locks. However, functions like nfs_delegation_claim_locks and nfs4_reclaim_locks cannot adhere to this rule because recover_lock or nfs4_lock_delegation_recall may take a long time. To resolve this, NFS switches to using nfsi->rwsem for the same protection, and nfs_reclaim_locks follows this approach. Although nfs_delegation_claim_locks uses so_delegreturn_mutex instead, this is inadequate since a single inode can have multiple nfs4_state instances. Therefore, the fix is to also use nfsi->rwsem in this case. Furthermore, after commit c69899a17ca4 ("NFSv4: Update of VFS byte range lock must be atomic with the stateid update"), the functions nfs4_locku_done and nfs4_lock_done also break this rule because they call locks_lock_inode_wait without holding nfsi->rwsem. Simply adding this protection could cause many deadlocks, so instead, the call to locks_lock_inode_wait is moved into _nfs4_proc_setlk. Regarding the bug fixed by commit c69899a17ca4 ("NFSv4: Update of VFS byte range lock must be atomic with the stateid update"), it has been resolved after commit 0460253913e5 ("NFSv4: nfs4_do_open() is incorrectly triggering state recovery") because all slots are drained before calling nfs4_do_reclaim, which prevents concurrent stateid changes along this path. Also, nfs_delegation_claim_locks does not cause this concurrency either since when _nfs4_proc_setlk is called with NFS_DELEGATED_STATE, no RPC is sent, so nfs4_lock_done is not called. Therefore, nfs4_lock_delegation_recall from nfs_delegation_claim_locks is the first time the stateid is set. Reported-by: Li Lingfeng Closes: https://lore.kernel.org/all/20250419085709.1452492-1-lilingfeng3@huawei.com/ Closes: https://lore.kernel.org/all/20250715030559.2906634-1-lilingfeng3@huawei.com/ Fixes: c69899a17ca4 ("NFSv4: Update of VFS byte range lock must be atomic with the stateid update") Signed-off-by: Yang Erkun Reviewed-by: Jeff Layton Signed-off-by: Anna Schumaker --- include/linux/nfs_xdr.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index fcbd21b5685f..40417e3a7f85 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -580,7 +580,6 @@ struct nfs_lock_args { struct nfs_lowner lock_owner; unsigned char block : 1; unsigned char reclaim : 1; - unsigned char new_lock : 1; unsigned char new_lock_owner : 1; }; -- cgit v1.2.3