[PATCH 3/7] block: use sb_for_each_inodes() in sync_bdevs()
Julian Sun
sunjunchao at bytedance.com
Wed Sep 9 09:01:08 UTC 2026
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 <sunjunchao at bytedance.com>
---
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
More information about the Linux-security-module-archive
mailing list