diff options
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 11 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 13 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 1 |
4 files changed, 22 insertions, 4 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 2775e270881e..0079b60b18f3 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -610,6 +610,7 @@ struct btrfs_fs_info { struct list_head dead_roots; atomic_t nr_async_submits; + atomic_t async_submit_draining; atomic_t nr_async_bios; atomic_t tree_log_writers; atomic_t tree_log_commit; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 45bc3132b054..45b4f7285275 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -460,6 +460,13 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, async->submit_bio_hook = submit_bio_hook; async->work.func = run_one_async_submit; async->work.flags = 0; + + while(atomic_read(&fs_info->async_submit_draining) && + atomic_read(&fs_info->nr_async_submits)) { + wait_event(fs_info->async_submit_wait, + (atomic_read(&fs_info->nr_async_submits) == 0)); + } + atomic_inc(&fs_info->nr_async_submits); btrfs_queue_worker(&fs_info->workers, &async->work); @@ -495,11 +502,8 @@ static int __btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, int mirror_num) { struct btrfs_root *root = BTRFS_I(inode)->root; - u64 offset; int ret; - offset = bio->bi_sector << 9; - /* * when we're called for a write, we're already in the async * submission context. Just jump into btrfs_map_bio @@ -1360,6 +1364,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, INIT_LIST_HEAD(&fs_info->space_info); btrfs_mapping_init(&fs_info->mapping_tree); atomic_set(&fs_info->nr_async_submits, 0); + atomic_set(&fs_info->async_submit_draining, 0); atomic_set(&fs_info->nr_async_bios, 0); atomic_set(&fs_info->throttles, 0); atomic_set(&fs_info->throttle_gen, 0); 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) list_del_init(&binode->delalloc_inodes); spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); if (inode) { - filemap_write_and_wait(inode->i_mapping); + filemap_flush(inode->i_mapping); iput(inode); } cond_resched(); spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); } spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); + + /* the filemap_flush will queue IO into the worker threads, but + * we have to make sure the IO is actually started and that + * ordered extents get created before we return + */ + atomic_inc(&root->fs_info->async_submit_draining); + while(atomic_read(&root->fs_info->nr_async_submits)) { + wait_event(root->fs_info->async_submit_wait, + (atomic_read(&root->fs_info->nr_async_submits) == 0)); + } + atomic_dec(&root->fs_info->async_submit_draining); return 0; } diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 51f113119b25..f63cf7621a01 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1038,6 +1038,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) return -EIO; } + filemap_write_and_wait(bdev->bd_inode->i_mapping); mutex_lock(&root->fs_info->volume_mutex); trans = btrfs_start_transaction(root, 1); |