diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-09-29 11:19:10 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-29 11:19:10 -0400 |
commit | 8c8bee1d7ca47fc75b6bd24a8085c525a2394c02 (patch) | |
tree | eb10010a7baa7ab73b068f9d9a95d15b7d79e300 /fs/btrfs/inode.c | |
parent | 1a40e23b95da45051ee4d74374c58ae87a14051c (diff) |
Btrfs: Wait for IO on the block device inodes of newly added devices
btrfs-vol -a /dev/xxx will zero the first and last two MB of the device.
The kernel code needs to wait for this IO to finish before it adds
the device.
btrfs metadata IO does not happen through the block device inode. A
separate address space is used, allowing the zero filled buffer heads in
the block device inode to be written to disk after FS metadata starts
going down to the disk via the btrfs metadata inode.
The end result is zero filled metadata blocks after adding new devices
into the filesystem.
The fix is a simple filemap_write_and_wait on the block device inode
before actually inserting it into the pool of available devices.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4516fbf01671..404704d26822 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3440,13 +3440,24 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root) | |||
3440 | list_del_init(&binode->delalloc_inodes); | 3440 | list_del_init(&binode->delalloc_inodes); |
3441 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); | 3441 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); |
3442 | if (inode) { | 3442 | if (inode) { |
3443 | filemap_write_and_wait(inode->i_mapping); | 3443 | filemap_flush(inode->i_mapping); |
3444 | iput(inode); | 3444 | iput(inode); |
3445 | } | 3445 | } |
3446 | cond_resched(); | 3446 | cond_resched(); |
3447 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); | 3447 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); |
3448 | } | 3448 | } |
3449 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); | 3449 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); |
3450 | |||
3451 | /* the filemap_flush will queue IO into the worker threads, but | ||
3452 | * we have to make sure the IO is actually started and that | ||
3453 | * ordered extents get created before we return | ||
3454 | */ | ||
3455 | atomic_inc(&root->fs_info->async_submit_draining); | ||
3456 | while(atomic_read(&root->fs_info->nr_async_submits)) { | ||
3457 | wait_event(root->fs_info->async_submit_wait, | ||
3458 | (atomic_read(&root->fs_info->nr_async_submits) == 0)); | ||
3459 | } | ||
3460 | atomic_dec(&root->fs_info->async_submit_draining); | ||
3450 | return 0; | 3461 | return 0; |
3451 | } | 3462 | } |
3452 | 3463 | ||