[PATCH] fs: Sync block devices via sync_inode()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jan Kara <jack@xxxxxxxx>

Currently we directly call filemap_fdatawrite() to issue IO when syncing
block devices. This works however especially for devices without mounted
filesystem it frequently happens that we race with flusher thread
issuing IO in parallel and thus generate interleaved IO streams. This
hurts especially for shingled drives. Fix the problem by using
sync_inode() instead. That "locks" inode via I_SYNC flag and thus gets
exclusion against flusher working on the same inode.

Signed-off-by: Jan Kara <jack@xxxxxxxx>
---
 fs/sync.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/fs/sync.c b/fs/sync.c
index fbc98ee62044..85bce626aaf7 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -79,9 +79,20 @@ static void sync_fs_one_sb(struct super_block *sb, void *arg)
 		sb->s_op->sync_fs(sb, *(int *)arg);
 }
 
-static void fdatawrite_one_bdev(struct block_device *bdev, void *arg)
+static void write_one_bdev(struct block_device *bdev, void *arg)
 {
-	filemap_fdatawrite(bdev->bd_inode->i_mapping);
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.range_start = 0,
+		.range_end = LLONG_MAX,
+		.nr_to_write = LONG_MAX,
+		.for_sync = 1,
+	};
+	/*
+	 * We use sync_inode() to get exclusion from flusher thread (via I_SYNC
+	 * flag) and thus avoid generating interleaved IO.
+	 */
+	sync_inode(bdev->bd_inode, &wbc);
 }
 
 static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
@@ -107,7 +118,7 @@ SYSCALL_DEFINE0(sync)
 	iterate_supers(sync_inodes_one_sb, NULL);
 	iterate_supers(sync_fs_one_sb, &nowait);
 	iterate_supers(sync_fs_one_sb, &wait);
-	iterate_bdevs(fdatawrite_one_bdev, NULL);
+	iterate_bdevs(write_one_bdev, NULL);
 	iterate_bdevs(fdatawait_one_bdev, NULL);
 	if (unlikely(laptop_mode))
 		laptop_sync_completion();
@@ -124,10 +135,10 @@ static void do_sync_work(struct work_struct *work)
 	 */
 	iterate_supers(sync_inodes_one_sb, &nowait);
 	iterate_supers(sync_fs_one_sb, &nowait);
-	iterate_bdevs(fdatawrite_one_bdev, NULL);
+	iterate_bdevs(write_one_bdev, NULL);
 	iterate_supers(sync_inodes_one_sb, &nowait);
 	iterate_supers(sync_fs_one_sb, &nowait);
-	iterate_bdevs(fdatawrite_one_bdev, NULL);
+	iterate_bdevs(write_one_bdev, NULL);
 	printk("Emergency Sync complete\n");
 	kfree(work);
 }
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux