Btrfs: Wait for IO on the block device inodes of newly added devices
[linux-2.6-block.git] / fs / btrfs / volumes.c
index 1546fa6f4f7d025c6d363320debdc2771131f704..f63cf7621a01a3b46665fa87100dd31939e6c459 100644 (file)
@@ -64,8 +64,8 @@ static void lock_chunks(struct btrfs_root *root)
 
 static void unlock_chunks(struct btrfs_root *root)
 {
-       mutex_unlock(&root->fs_info->alloc_mutex);
        mutex_unlock(&root->fs_info->chunk_mutex);
+       mutex_unlock(&root->fs_info->alloc_mutex);
 }
 
 int btrfs_cleanup_fs_uuids(void)
@@ -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);
@@ -1268,7 +1269,7 @@ int btrfs_relocate_chunk(struct btrfs_root *root,
        em_tree = &root->fs_info->mapping_tree.map_tree;
 
        /* step one, relocate all the extents inside this chunk */
-       ret = btrfs_shrink_extent_tree(extent_root, chunk_offset);
+       ret = btrfs_relocate_block_group(extent_root, chunk_offset);
        BUG_ON(ret);
 
        trans = btrfs_start_transaction(root, 1);
@@ -1308,15 +1309,18 @@ int btrfs_relocate_chunk(struct btrfs_root *root,
                BUG_ON(ret);
        }
 
+       ret = btrfs_remove_block_group(trans, extent_root, chunk_offset);
+       BUG_ON(ret);
+
        spin_lock(&em_tree->lock);
        remove_extent_mapping(em_tree, em);
+       spin_unlock(&em_tree->lock);
+
        kfree(map);
        em->bdev = NULL;
 
        /* once for the tree */
        free_extent_map(em);
-       spin_unlock(&em_tree->lock);
-
        /* once for us */
        free_extent_map(em);
 
@@ -1668,8 +1672,13 @@ again:
        else
                min_free = calc_size;
 
-       /* we add 1MB because we never use the first 1MB of the device */
-       min_free += 1024 * 1024;
+       /*
+        * we add 1MB because we never use the first 1MB of the device, unless
+        * we've looped, then we are likely allocating the maximum amount of
+        * space left already
+        */
+       if (!looped)
+               min_free += 1024 * 1024;
 
        /* build a private list of devices we will allocate from */
        while(index < num_stripes) {
@@ -2075,20 +2084,11 @@ int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree,
 }
 
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
 static void end_bio_multi_stripe(struct bio *bio, int err)
-#else
-static int end_bio_multi_stripe(struct bio *bio,
-                                  unsigned int bytes_done, int err)
-#endif
 {
        struct btrfs_multi_bio *multi = bio->bi_private;
        int is_orig_bio = 0;
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
-       if (bio->bi_size)
-               return 1;
-#endif
        if (err)
                atomic_inc(&multi->error);
 
@@ -2117,17 +2117,10 @@ static int end_bio_multi_stripe(struct bio *bio,
                }
                kfree(multi);
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
-               bio_endio(bio, bio->bi_size, err);
-#else
                bio_endio(bio, err);
-#endif
        } else if (!is_orig_bio) {
                bio_put(bio);
        }
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
-       return 0;
-#endif
 }
 
 struct async_sched {
@@ -2243,11 +2236,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
                } else {
                        bio->bi_bdev = root->fs_info->fs_devices->latest_bdev;
                        bio->bi_sector = logical >> 9;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
-                       bio_endio(bio, bio->bi_size, -EIO);
-#else
                        bio_endio(bio, -EIO);
-#endif
                }
                dev_nr++;
        }