Btrfs: flush out and clean up any block device pages during mount
authorChris Mason <chris.mason@oracle.com>
Tue, 27 Mar 2012 22:56:56 +0000 (18:56 -0400)
committerChris Mason <chris.mason@oracle.com>
Thu, 29 Mar 2012 00:33:58 +0000 (20:33 -0400)
Btrfs puts the filesystem metadata into its own address space, and
somehow the block device address space isn't getting onto disk properly
before a mount.  The end result is that a loop of mkfs and mounting the
filesystem will sometimes find stale or incorrect data.

This commit should fix it by sprinkling fdatawrites and invalidate_bdev
calls around.  This is a short term measure to make sure it is fixed.
The block devices really should be flushed and cleaned up higher in the
stack.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/disk-io.c
fs/btrfs/volumes.c

index 7b55eee15a51265e3d670cafa57c2772b8f0614a..fd43f6b2f43811bfb1a60d4054d59a0257958019 100644 (file)
@@ -2031,6 +2031,7 @@ int open_ctree(struct super_block *sb,
        __setup_root(4096, 4096, 4096, 4096, tree_root,
                     fs_info, BTRFS_ROOT_TREE_OBJECTID);
 
+       invalidate_bdev(fs_devices->latest_bdev);
        bh = btrfs_read_dev_super(fs_devices->latest_bdev);
        if (!bh) {
                err = -EINVAL;
index 68a1754fe3674c933501966e50598c473d772443..a872b48be0ae15fd77eff56e2c529470ddde0b7f 100644 (file)
@@ -622,6 +622,8 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
                        printk(KERN_INFO "open %s failed\n", device->name);
                        goto error;
                }
+               filemap_write_and_wait(bdev->bd_inode->i_mapping);
+               invalidate_bdev(bdev);
                set_blocksize(bdev, 4096);
 
                bh = btrfs_read_dev_super(bdev);
@@ -1354,6 +1356,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
                }
 
                set_blocksize(bdev, 4096);
+               invalidate_bdev(bdev);
                bh = btrfs_read_dev_super(bdev);
                if (!bh) {
                        ret = -EINVAL;