@@ -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);
}