From 769e143b115a4af75ecbc6d4e39d58b3e6fe2099 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Tue, 21 Apr 2026 20:25:36 +0200 Subject: fs: add icount_read_once() and stop open-coding ->i_count loads Similarly to inode_state_read_once(), it makes the caller spell out they acknowledge instability of the returned value. Signed-off-by: Mateusz Guzik Link: https://patch.msgid.link/20260421182538.1215894-2-mjguzik@gmail.com Reviewed-by: Jan Kara Signed-off-by: Christian Brauner --- include/linux/fs.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include/linux') diff --git a/include/linux/fs.h b/include/linux/fs.h index 11559c513dfb..61ce251ad83e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2218,8 +2218,21 @@ static inline void mark_inode_dirty_sync(struct inode *inode) __mark_inode_dirty(inode, I_DIRTY_SYNC); } +/* + * returns the refcount on the inode. it can change arbitrarily. + */ +static inline int icount_read_once(const struct inode *inode) +{ + return atomic_read(&inode->i_count); +} + +/* + * returns the refcount on the inode. The lock guarantees no new references + * are added, but references can be dropped as long as the result is > 0. + */ static inline int icount_read(const struct inode *inode) { + lockdep_assert_held(&inode->i_lock); return atomic_read(&inode->i_count); } -- cgit v1.2.3 From c678577e8896829f9da08635d6075dddefbaf684 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Tue, 21 Apr 2026 20:25:38 +0200 Subject: fs: allow lockless ->i_count bumps as long as it does not transition 0->1 With this change only 0->1 and 1->0 transitions need the lock. I verified all places which look at the refcount either only care about it staying 0 (and have the lock enforce it) or don't hold the inode lock to begin with (making the above change irrelevant to their correcness or lack thereof). I also confirmed nfs and btrfs like to call into these a lot and now avoid the lock in the common case, shaving off some atomics. Signed-off-by: Mateusz Guzik Link: https://patch.msgid.link/20260421182538.1215894-4-mjguzik@gmail.com Reviewed-by: Jan Kara Signed-off-by: Christian Brauner --- include/linux/fs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/fs.h b/include/linux/fs.h index 61ce251ad83e..c5c31a6f7ed5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2227,8 +2227,8 @@ static inline int icount_read_once(const struct inode *inode) } /* - * returns the refcount on the inode. The lock guarantees no new references - * are added, but references can be dropped as long as the result is > 0. + * returns the refcount on the inode. The lock guarantees no 0->1 or 1->0 transitions + * of the count are going to take place, otherwise it changes arbitrarily. */ static inline int icount_read(const struct inode *inode) { -- cgit v1.2.3