[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <50a0e1a914673759079507c22fed039def0c4bfd.1755806649.git.josef@toxicpanda.com>
Date: Thu, 21 Aug 2025 16:18:16 -0400
From: Josef Bacik <josef@...icpanda.com>
To: linux-fsdevel@...r.kernel.org,
linux-btrfs@...r.kernel.org,
kernel-team@...com,
linux-ext4@...r.kernel.org,
linux-xfs@...r.kernel.org,
brauner@...nel.org,
viro@...IV.linux.org.uk
Subject: [PATCH 05/50] fs: hold an i_obj_count reference for the i_io_list
While the inode is attached to a list with its i_io_list member we need
to hold a reference on the object.
The put is under the i_lock in some cases which could potentially be
unsafe. It isn't currently because we're holding the i_obj_count
throughout the entire lifetime of the inode, so it won't be the last
currently. Subsequent patches will make sure we're holding an
i_obj_count reference while we're manipulating this list to ensure this
continues to be safe.
Signed-off-by: Josef Bacik <josef@...icpanda.com>
---
fs/fs-writeback.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index c2437e3d320a..24fccb299de4 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -72,6 +72,14 @@ static inline struct inode *wb_inode(struct list_head *head)
return list_entry(head, struct inode, i_io_list);
}
+static inline void inode_delete_from_io_list(struct inode *inode)
+{
+ if (!list_empty(&inode->i_io_list)) {
+ list_del_init(&inode->i_io_list);
+ iobj_put(inode);
+ }
+}
+
/*
* Include the creation of the trace points after defining the
* wb_writeback_work structure and inline functions so that the definition
@@ -123,6 +131,8 @@ static bool inode_io_list_move_locked(struct inode *inode,
assert_spin_locked(&inode->i_lock);
WARN_ON_ONCE(inode->i_state & I_FREEING);
+ if (list_empty(&inode->i_io_list))
+ iobj_get(inode);
list_move(&inode->i_io_list, head);
/* dirty_time doesn't count as dirty_io until expiration */
@@ -310,7 +320,7 @@ static void inode_cgwb_move_to_attached(struct inode *inode,
if (wb != &wb->bdi->wb)
list_move(&inode->i_io_list, &wb->b_attached);
else
- list_del_init(&inode->i_io_list);
+ inode_delete_from_io_list(inode);
wb_io_lists_depopulated(wb);
}
@@ -1200,7 +1210,7 @@ static void inode_cgwb_move_to_attached(struct inode *inode,
WARN_ON_ONCE(inode->i_state & I_FREEING);
inode->i_state &= ~I_SYNC_QUEUED;
- list_del_init(&inode->i_io_list);
+ inode_delete_from_io_list(inode);
wb_io_lists_depopulated(wb);
}
@@ -1308,16 +1318,23 @@ void wb_start_background_writeback(struct bdi_writeback *wb)
void inode_io_list_del(struct inode *inode)
{
struct bdi_writeback *wb;
+ bool drop = false;
wb = inode_to_wb_and_lock_list(inode);
spin_lock(&inode->i_lock);
inode->i_state &= ~I_SYNC_QUEUED;
- list_del_init(&inode->i_io_list);
+ if (!list_empty(&inode->i_io_list)) {
+ drop = true;
+ list_del_init(&inode->i_io_list);
+ }
wb_io_lists_depopulated(wb);
spin_unlock(&inode->i_lock);
spin_unlock(&wb->list_lock);
+
+ if (drop)
+ iobj_put(inode);
}
EXPORT_SYMBOL(inode_io_list_del);
@@ -1389,7 +1406,7 @@ static void redirty_tail_locked(struct inode *inode, struct bdi_writeback *wb)
* trigger assertions in inode_io_list_move_locked().
*/
if (inode->i_state & I_FREEING) {
- list_del_init(&inode->i_io_list);
+ inode_delete_from_io_list(inode);
wb_io_lists_depopulated(wb);
return;
}
--
2.49.0
Powered by blists - more mailing lists