[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <39379ac2620e98987f185dcf3a20f7b273d7ca33.1755806649.git.josef@toxicpanda.com>
Date: Thu, 21 Aug 2025 16:18:15 -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 04/50] fs: hold an i_obj_count reference for the i_wb_list
If we're holding the inode on one of the writeback lists we need to have
a reference on that inode. Grab a reference when we add i_wb_list to
something, drop it when it's removed.
This is potentially dangerous, because we remove the inode from the
i_wb_list potentially under IRQ via folio_end_writeback(). This will be
mitigated by making sure all writeback is completed on the final iput,
before the final iobj_put, preventing a potential free under IRQ.
Signed-off-by: Josef Bacik <josef@...icpanda.com>
---
fs/fs-writeback.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 001773e6e95c..c2437e3d320a 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1332,6 +1332,7 @@ void sb_mark_inode_writeback(struct inode *inode)
if (list_empty(&inode->i_wb_list)) {
spin_lock_irqsave(&sb->s_inode_wblist_lock, flags);
if (list_empty(&inode->i_wb_list)) {
+ iobj_get(inode);
list_add_tail(&inode->i_wb_list, &sb->s_inodes_wb);
trace_sb_mark_inode_writeback(inode);
}
@@ -1346,15 +1347,26 @@ void sb_clear_inode_writeback(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
unsigned long flags;
+ bool drop = false;
if (!list_empty(&inode->i_wb_list)) {
spin_lock_irqsave(&sb->s_inode_wblist_lock, flags);
if (!list_empty(&inode->i_wb_list)) {
+ drop = true;
list_del_init(&inode->i_wb_list);
trace_sb_clear_inode_writeback(inode);
}
spin_unlock_irqrestore(&sb->s_inode_wblist_lock, flags);
}
+
+ /*
+ * This can be called in IRQ context when we're clearing writeback on
+ * the folio. This should not be the last iobj_put() on the inode, we
+ * run all of the writeback before we free the inode in order to avoid
+ * this possibility.
+ */
+ if (drop)
+ iobj_put(inode);
}
/*
@@ -2683,6 +2695,8 @@ static void wait_sb_inodes(struct super_block *sb)
* to preserve consistency between i_wb_list and the mapping
* writeback tag. Writeback completion is responsible to remove
* the inode from either list once the writeback tag is cleared.
+ * At that point the i_obj_count reference will be dropped for
+ * the i_wb_list reference.
*/
list_move_tail(&inode->i_wb_list, &sb->s_inodes_wb);
--
2.49.0
Powered by blists - more mailing lists