[PATCH 3/7] block: use sb_for_each_inodes() in sync_bdevs()
From: Julian Sun <hidden>
Date: 2026-09-09 09:01:30
Also in:
gfs2, linux-block, linux-fsdevel
Subsystem:
block layer, the rest · Maintainers:
Jens Axboe, Linus Torvalds
Convert sync_bdevs() to sb_for_each_inodes() and move device writeback into a callback. The iterator preserves the walk position, allowing the callback to iput() its inode before reacquiring the list lock and removing the old_inode reference carried across iterations. Signed-off-by: Julian Sun <redacted> --- block/bdev.c | 85 +++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 44 deletions(-)
diff --git a/block/bdev.c b/block/bdev.c
index cd8323083740..ae472a062e51 100644
--- a/block/bdev.c
+++ b/block/bdev.c@@ -1336,56 +1336,53 @@ void bdev_mark_dead(struct block_device *bdev, bool surprise) */ EXPORT_SYMBOL_GPL(bdev_mark_dead); -void sync_bdevs(bool wait) +static int sync_bdevs_inode_iter_cb(struct inode *inode, void *data) { - struct inode *inode, *old_inode = NULL; - - spin_lock(&blockdev_superblock->s_inode_list_lock); - list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) { - struct address_space *mapping = inode->i_mapping; - struct block_device *bdev; + bool wait = (bool)data; + struct block_device *bdev; + struct address_space *mapping = inode->i_mapping; - spin_lock(&inode->i_lock); - if (inode_state_read(inode) & (I_FREEING | I_WILL_FREE | I_NEW) || - mapping->nrpages == 0) { - spin_unlock(&inode->i_lock); - continue; - } - __iget(inode); + if (mapping->nrpages == 0) { spin_unlock(&inode->i_lock); - spin_unlock(&blockdev_superblock->s_inode_list_lock); + return 0; + } + + /* + * We hold a reference to 'inode' so it couldn't have been + * removed from s_inodes list while we dropped the + * s_inode_list_lock. + */ + __iget(inode); + spin_unlock(&inode->i_lock); + spin_unlock(&blockdev_superblock->s_inode_list_lock); + bdev = I_BDEV(inode); + + mutex_lock(&bdev->bd_disk->open_mutex); + if (!atomic_read(&bdev->bd_openers)) { + ; /* skip */ + } else if (wait) { /* - * We hold a reference to 'inode' so it couldn't have been - * removed from s_inodes list while we dropped the - * s_inode_list_lock We cannot iput the inode now as we can - * be holding the last reference and we cannot iput it under - * s_inode_list_lock. So we keep the reference and iput it - * later. + * We keep the error status of individual mapping so + * that applications can catch the writeback error using + * fsync(2). See filemap_fdatawait_keep_errors() for + * details. */ - iput(old_inode); - old_inode = inode; - bdev = I_BDEV(inode); - - mutex_lock(&bdev->bd_disk->open_mutex); - if (!atomic_read(&bdev->bd_openers)) { - ; /* skip */ - } else if (wait) { - /* - * We keep the error status of individual mapping so - * that applications can catch the writeback error using - * fsync(2). See filemap_fdatawait_keep_errors() for - * details. - */ - filemap_fdatawait_keep_errors(inode->i_mapping); - } else { - filemap_fdatawrite(inode->i_mapping); - } - mutex_unlock(&bdev->bd_disk->open_mutex); - - spin_lock(&blockdev_superblock->s_inode_list_lock); + filemap_fdatawait_keep_errors(inode->i_mapping); + } else { + filemap_fdatawrite(inode->i_mapping); } - spin_unlock(&blockdev_superblock->s_inode_list_lock); - iput(old_inode); + mutex_unlock(&bdev->bd_disk->open_mutex); + iput(inode); + + spin_lock(&blockdev_superblock->s_inode_list_lock); + + return 0; +} + +void sync_bdevs(bool wait) +{ + sb_for_each_inodes(blockdev_superblock, INODE_ITER_NORMAL, + sync_bdevs_inode_iter_cb, (void *)wait); } /*
--
2.39.5