Change generated with coccinelle and fixed up by hand as appropriate.
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
---
cheat sheet:
If ->i_lock is held, then:
state = inode->i_state => state = inode_state_read(inode)
inode->i_state |= (I_A | I_B) => inode_state_set(inode, I_A | I_B)
inode->i_state &= ~(I_A | I_B) => inode_state_clear(inode, I_A | I_B)
inode->i_state = I_A | I_B => inode_state_assign(inode, I_A | I_B)
If ->i_lock is not held or only held conditionally:
state = inode->i_state => state = inode_state_read_once(inode)
inode->i_state |= (I_A | I_B) => inode_state_set_raw(inode, I_A | I_B)
inode->i_state &= ~(I_A | I_B) => inode_state_clear_raw(inode, I_A | I_B)
inode->i_state = I_A | I_B => inode_state_assign_raw(inode, I_A | I_B)
fs/xfs/scrub/common.c | 2 +-
fs/xfs/scrub/inode_repair.c | 2 +-
fs/xfs/scrub/parent.c | 2 +-
fs/xfs/xfs_bmap_util.c | 2 +-
fs/xfs/xfs_health.c | 4 ++--
fs/xfs/xfs_icache.c | 6 +++---
fs/xfs/xfs_inode.c | 6 +++---
fs/xfs/xfs_inode_item.c | 4 ++--
fs/xfs/xfs_iops.c | 2 +-
fs/xfs/xfs_reflink.h | 2 +-
10 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index 2ef7742be7d3..7bfa37c99480 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -1249,7 +1249,7 @@ xchk_irele(
* hits do not clear DONTCACHE, so we must do it here.
*/
spin_lock(&VFS_I(ip)->i_lock);
- VFS_I(ip)->i_state &= ~I_DONTCACHE;
+ inode_state_clear(VFS_I(ip), I_DONTCACHE);
spin_unlock(&VFS_I(ip)->i_lock);
}
diff --git a/fs/xfs/scrub/inode_repair.c b/fs/xfs/scrub/inode_repair.c
index a90a011c7e5f..4f7040c9ddf0 100644
--- a/fs/xfs/scrub/inode_repair.c
+++ b/fs/xfs/scrub/inode_repair.c
@@ -1933,7 +1933,7 @@ xrep_inode_pptr(
* Unlinked inodes that cannot be added to the directory tree will not
* have a parent pointer.
*/
- if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
+ if (inode->i_nlink == 0 && !(inode_state_read_once(inode) & I_LINKABLE))
return 0;
/* Children of the superblock do not have parent pointers. */
diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
index 3b692c4acc1e..11d5de10fd56 100644
--- a/fs/xfs/scrub/parent.c
+++ b/fs/xfs/scrub/parent.c
@@ -915,7 +915,7 @@ xchk_pptr_looks_zapped(
* Temporary files that cannot be linked into the directory tree do not
* have attr forks because they cannot ever have parents.
*/
- if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
+ if (inode->i_nlink == 0 && !(inode_state_read_once(inode) & I_LINKABLE))
return false;
/*
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 06ca11731e43..2208a720ec3f 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -514,7 +514,7 @@ xfs_can_free_eofblocks(
* Caller must either hold the exclusive io lock; or be inactivating
* the inode, which guarantees there are no other users of the inode.
*/
- if (!(VFS_I(ip)->i_state & I_FREEING))
+ if (!(inode_state_read_once(VFS_I(ip)) & I_FREEING))
xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL);
/* prealloc/delalloc exists only on regular files */
diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c
index 7c541fb373d5..3c1557fb1cf0 100644
--- a/fs/xfs/xfs_health.c
+++ b/fs/xfs/xfs_health.c
@@ -285,7 +285,7 @@ xfs_inode_mark_sick(
* is not the case here.
*/
spin_lock(&VFS_I(ip)->i_lock);
- VFS_I(ip)->i_state &= ~I_DONTCACHE;
+ inode_state_clear(VFS_I(ip), I_DONTCACHE);
spin_unlock(&VFS_I(ip)->i_lock);
}
@@ -309,7 +309,7 @@ xfs_inode_mark_corrupt(
* is not the case here.
*/
spin_lock(&VFS_I(ip)->i_lock);
- VFS_I(ip)->i_state &= ~I_DONTCACHE;
+ inode_state_clear(VFS_I(ip), I_DONTCACHE);
spin_unlock(&VFS_I(ip)->i_lock);
}
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index e44040206851..f3fc4d21bfe1 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -334,7 +334,7 @@ xfs_reinit_inode(
dev_t dev = inode->i_rdev;
kuid_t uid = inode->i_uid;
kgid_t gid = inode->i_gid;
- unsigned long state = inode->i_state;
+ unsigned long state = inode_state_read_once(inode);
error = inode_init_always(mp->m_super, inode);
@@ -345,7 +345,7 @@ xfs_reinit_inode(
inode->i_rdev = dev;
inode->i_uid = uid;
inode->i_gid = gid;
- inode->i_state = state;
+ inode_state_assign_raw(inode, state);
mapping_set_folio_min_order(inode->i_mapping,
M_IGEO(mp)->min_folio_order);
return error;
@@ -411,7 +411,7 @@ xfs_iget_recycle(
ip->i_flags |= XFS_INEW;
xfs_perag_clear_inode_tag(pag, XFS_INO_TO_AGINO(mp, ip->i_ino),
XFS_ICI_RECLAIM_TAG);
- inode->i_state = I_NEW;
+ inode_state_assign_raw(inode, I_NEW);
spin_unlock(&ip->i_flags_lock);
spin_unlock(&pag->pag_ici_lock);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 36b39539e561..f1f88e48fe22 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1580,7 +1580,7 @@ xfs_iunlink_reload_next(
next_ip->i_prev_unlinked = prev_agino;
trace_xfs_iunlink_reload_next(next_ip);
rele:
- ASSERT(!(VFS_I(next_ip)->i_state & I_DONTCACHE));
+ ASSERT(!(inode_state_read_once(VFS_I(next_ip)) & I_DONTCACHE));
if (xfs_is_quotacheck_running(mp) && next_ip)
xfs_iflags_set(next_ip, XFS_IQUOTAUNCHECKED);
xfs_irele(next_ip);
@@ -2111,7 +2111,7 @@ xfs_rename_alloc_whiteout(
*/
xfs_setup_iops(tmpfile);
xfs_finish_inode_setup(tmpfile);
- VFS_I(tmpfile)->i_state |= I_LINKABLE;
+ inode_state_set_raw(VFS_I(tmpfile), I_LINKABLE);
*wip = tmpfile;
return 0;
@@ -2330,7 +2330,7 @@ xfs_rename(
* flag from the inode so it doesn't accidentally get misused in
* future.
*/
- VFS_I(du_wip.ip)->i_state &= ~I_LINKABLE;
+ inode_state_clear_raw(VFS_I(du_wip.ip), I_LINKABLE);
}
out_commit:
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 1bd411a1114c..2eb0c6011a2e 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -113,9 +113,9 @@ xfs_inode_item_precommit(
* to log the timestamps, or will clear already cleared fields in the
* worst case.
*/
- if (inode->i_state & I_DIRTY_TIME) {
+ if (inode_state_read_once(inode) & I_DIRTY_TIME) {
spin_lock(&inode->i_lock);
- inode->i_state &= ~I_DIRTY_TIME;
+ inode_state_clear(inode, I_DIRTY_TIME);
spin_unlock(&inode->i_lock);
}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index caff0125faea..ad94fbf55014 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1420,7 +1420,7 @@ xfs_setup_inode(
bool is_meta = xfs_is_internal_inode(ip);
inode->i_ino = ip->i_ino;
- inode->i_state |= I_NEW;
+ inode_state_set_raw(inode, I_NEW);
inode_sb_list_add(inode);
/* make the inode look hashed for the writeback code */
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index 36cda724da89..9d1ed9bb0bee 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -17,7 +17,7 @@ xfs_can_free_cowblocks(struct xfs_inode *ip)
{
struct inode *inode = VFS_I(ip);
- if ((inode->i_state & I_DIRTY_PAGES) ||
+ if ((inode_state_read_once(inode) & I_DIRTY_PAGES) ||
mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY) ||
mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK) ||
atomic_read(&inode->i_dio_count))
--
2.34.1
On Thu 09-10-25 09:59:27, Mateusz Guzik wrote: > Change generated with coccinelle and fixed up by hand as appropriate. > > Signed-off-by: Mateusz Guzik <mjguzik@gmail.com> ... > @@ -2111,7 +2111,7 @@ xfs_rename_alloc_whiteout( > */ > xfs_setup_iops(tmpfile); > xfs_finish_inode_setup(tmpfile); > - VFS_I(tmpfile)->i_state |= I_LINKABLE; > + inode_state_set_raw(VFS_I(tmpfile), I_LINKABLE); > > *wip = tmpfile; > return 0; > @@ -2330,7 +2330,7 @@ xfs_rename( > * flag from the inode so it doesn't accidentally get misused in > * future. > */ > - VFS_I(du_wip.ip)->i_state &= ~I_LINKABLE; > + inode_state_clear_raw(VFS_I(du_wip.ip), I_LINKABLE); > } > > out_commit: These two accesses look fishy (not your fault but when we are doing this i_state exercise better make sure all the places are correct before papering over bugs with _raw function variant). How come they cannot race with other i_state modifications and thus corrupt i_state? > diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c > index caff0125faea..ad94fbf55014 100644 > --- a/fs/xfs/xfs_iops.c > +++ b/fs/xfs/xfs_iops.c > @@ -1420,7 +1420,7 @@ xfs_setup_inode( > bool is_meta = xfs_is_internal_inode(ip); > > inode->i_ino = ip->i_ino; > - inode->i_state |= I_NEW; > + inode_state_set_raw(inode, I_NEW); > > inode_sb_list_add(inode); > /* make the inode look hashed for the writeback code */ Frankly, the XFS i_state handling is kind of messy and I suspect we should be getting i_state == 0 here. But we need to confirm with XFS guys. I'm poking into this because this is actually the only case where we need inode_state_set_raw() or inode_state_clear_raw() outside of core VFS and I'd like to get rid of these functions because IMHO they are actively dangerous to use. Honza -- Jan Kara <jack@suse.com> SUSE Labs, CR
On Fri, Oct 10, 2025 at 4:41 PM Jan Kara <jack@suse.cz> wrote: > > On Thu 09-10-25 09:59:27, Mateusz Guzik wrote: > > Change generated with coccinelle and fixed up by hand as appropriate. > > > > Signed-off-by: Mateusz Guzik <mjguzik@gmail.com> > > ... > > > @@ -2111,7 +2111,7 @@ xfs_rename_alloc_whiteout( > > */ > > xfs_setup_iops(tmpfile); > > xfs_finish_inode_setup(tmpfile); > > - VFS_I(tmpfile)->i_state |= I_LINKABLE; > > + inode_state_set_raw(VFS_I(tmpfile), I_LINKABLE); > > > > *wip = tmpfile; > > return 0; > > @@ -2330,7 +2330,7 @@ xfs_rename( > > * flag from the inode so it doesn't accidentally get misused in > > * future. > > */ > > - VFS_I(du_wip.ip)->i_state &= ~I_LINKABLE; > > + inode_state_clear_raw(VFS_I(du_wip.ip), I_LINKABLE); > > } > > > > out_commit: > > These two accesses look fishy (not your fault but when we are doing this > i_state exercise better make sure all the places are correct before > papering over bugs with _raw function variant). How come they cannot race > with other i_state modifications and thus corrupt i_state? > I asked about this here: https://lore.kernel.org/linux-xfs/CAGudoHEi05JGkTQ9PbM20D98S9fv0hTqpWRd5fWjEwkExSiVSw@mail.gmail.com/ > > diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c > > index caff0125faea..ad94fbf55014 100644 > > --- a/fs/xfs/xfs_iops.c > > +++ b/fs/xfs/xfs_iops.c > > @@ -1420,7 +1420,7 @@ xfs_setup_inode( > > bool is_meta = xfs_is_internal_inode(ip); > > > > inode->i_ino = ip->i_ino; > > - inode->i_state |= I_NEW; > > + inode_state_set_raw(inode, I_NEW); > > > > inode_sb_list_add(inode); > > /* make the inode look hashed for the writeback code */ > > Frankly, the XFS i_state handling is kind of messy and I suspect we should > be getting i_state == 0 here. But we need to confirm with XFS guys. I'm > poking into this because this is actually the only case where we need > inode_state_set_raw() or inode_state_clear_raw() outside of core VFS and > I'd like to get rid of these functions because IMHO they are actively > dangerous to use. > I'm going to address this in the other e-mail.
© 2016 - 2025 Red Hat, Inc.