Hi Tejun, > > White line contaminations. Fixed in v2. > Given that there's write_inode_now(@sync == true) call right above, > I'm not sure how waiting for I_SYNC once more time would make a > difference. Can you please explain how to trigger the issue? bdev_write_inode() calls write_inode_now() only if I_DIRTY is set for the inode. It is possible that I_DIRTY flags have been cleared by the writeback thread, but it hasn't run node_sync_complete() yet. I am able to reproduce the problem by adding articial delays in __blkdev_put() and writeback_sb_inodes(). Please see the repro patch below: diff --git a/fs/block_dev.c b/fs/block_dev.c index 2eca00ec4370..e3cfbba19a6c 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -33,6 +33,7 @@ #include <linux/task_io_accounting_ops.h> #include <linux/falloc.h> #include <linux/uaccess.h> +#include <linux/delay.h> #include "internal.h" struct bdev_inode { @@ -1875,6 +1876,8 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part) sync_blockdev(bdev); kill_bdev(bdev); + /* Allow time for writeback thread to clear I_DIRTY flags */ + mdelay(200); bdev_write_inode(bdev); /* * Detaching bdev inode from its wb in __destroy_inode() diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ef600591d96f..55073cbc1823 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -28,6 +28,7 @@ #include <linux/tracepoint.h> #include <linux/device.h> #include <linux/memcontrol.h> +#include <linux/delay.h> #include "internal.h" /* @@ -1585,6 +1586,10 @@ static long writeback_sb_inodes(struct super_block *sb, cond_resched(); } + /* Allow __blkdev_put() to run inode_detach_wb() */ + if (inode->i_ino == 0) + mdelay(200); + /* * Requeue @inode if still dirty. Be careful as @inode may * have been switched to another wb in the meantime. diff --git a/wb-detach-repro.sh b/wb-detach-repro.sh new file mode 100755 index 000000000000..66892d71cd20 --- /dev/null +++ b/wb-detach-repro.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -ex + +echo 100 > /proc/sys/vm/dirty_expire_centisecs +echo 100 > /proc/sys/vm/dirty_writeback_centisecs + +mount /dev/sdb /mnt/sdb +sleep 0.9 +echo 10 > /proc/sys/vm/dirty_writeback_centisecs +umount /dev/sdb