Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
[linux-2.6-microblaze.git] / fs / btrfs / volumes.c
index 40d850a..ec3a874 100644 (file)
@@ -38,7 +38,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .sub_stripes    = 2,
                .dev_stripes    = 1,
                .devs_max       = 0,    /* 0 == as many as possible */
-               .devs_min       = 4,
+               .devs_min       = 2,
                .tolerated_failures = 1,
                .devs_increment = 2,
                .ncopies        = 2,
@@ -103,7 +103,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .sub_stripes    = 1,
                .dev_stripes    = 1,
                .devs_max       = 0,
-               .devs_min       = 2,
+               .devs_min       = 1,
                .tolerated_failures = 0,
                .devs_increment = 1,
                .ncopies        = 1,
@@ -430,44 +430,6 @@ void __exit btrfs_cleanup_fs_uuids(void)
        }
 }
 
-/*
- * Returns a pointer to a new btrfs_device on success; ERR_PTR() on error.
- * Returned struct is not linked onto any lists and must be destroyed using
- * btrfs_free_device.
- */
-static struct btrfs_device *__alloc_device(struct btrfs_fs_info *fs_info)
-{
-       struct btrfs_device *dev;
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       /*
-        * Preallocate a bio that's always going to be used for flushing device
-        * barriers and matches the device lifespan
-        */
-       dev->flush_bio = bio_kmalloc(GFP_KERNEL, 0);
-       if (!dev->flush_bio) {
-               kfree(dev);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       INIT_LIST_HEAD(&dev->dev_list);
-       INIT_LIST_HEAD(&dev->dev_alloc_list);
-       INIT_LIST_HEAD(&dev->post_commit_list);
-
-       atomic_set(&dev->reada_in_flight, 0);
-       atomic_set(&dev->dev_stats_ccnt, 0);
-       btrfs_device_data_ordered_init(dev);
-       INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
-       INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
-       extent_io_tree_init(fs_info, &dev->alloc_state,
-                           IO_TREE_DEVICE_ALLOC_STATE, NULL);
-
-       return dev;
-}
-
 static noinline struct btrfs_fs_devices *find_fsid(
                const u8 *fsid, const u8 *metadata_fsid)
 {
@@ -1156,6 +1118,9 @@ static void btrfs_close_one_device(struct btrfs_device *device)
                fs_devices->rw_devices--;
        }
 
+       if (device->devid == BTRFS_DEV_REPLACE_DEVID)
+               clear_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
+
        if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state))
                fs_devices->missing_devices--;
 
@@ -1254,7 +1219,7 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices,
 static int devid_cmp(void *priv, const struct list_head *a,
                     const struct list_head *b)
 {
-       struct btrfs_device *dev1, *dev2;
+       const struct btrfs_device *dev1, *dev2;
 
        dev1 = list_entry(a, struct btrfs_device, dev_list);
        dev2 = list_entry(b, struct btrfs_device, dev_list);
@@ -1624,14 +1589,9 @@ again:
        key.offset = search_start;
        key.type = BTRFS_DEV_EXTENT_KEY;
 
-       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+       ret = btrfs_search_backwards(root, &key, path);
        if (ret < 0)
                goto out;
-       if (ret > 0) {
-               ret = btrfs_previous_item(root, path, key.objectid, key.type);
-               if (ret < 0)
-                       goto out;
-       }
 
        while (1) {
                l = path->nodes[0];
@@ -1987,12 +1947,8 @@ static int btrfs_check_raid_min_devices(struct btrfs_fs_info *fs_info,
                if (!(all_avail & btrfs_raid_array[i].bg_flag))
                        continue;
 
-               if (num_devices < btrfs_raid_array[i].devs_min) {
-                       int ret = btrfs_raid_array[i].mindev_error;
-
-                       if (ret)
-                               return ret;
-               }
+               if (num_devices < btrfs_raid_array[i].devs_min)
+                       return btrfs_raid_array[i].mindev_error;
        }
 
        return 0;
@@ -2121,7 +2077,7 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
 
        if (IS_ERR(device)) {
                if (PTR_ERR(device) == -ENOENT &&
-                   strcmp(device_path, "missing") == 0)
+                   device_path && strcmp(device_path, "missing") == 0)
                        ret = BTRFS_ERROR_DEV_MISSING_NOT_FOUND;
                else
                        ret = PTR_ERR(device);
@@ -3606,10 +3562,7 @@ static u64 calc_data_stripes(u64 type, int num_stripes)
        const int ncopies = btrfs_raid_array[index].ncopies;
        const int nparity = btrfs_raid_array[index].nparity;
 
-       if (nparity)
-               return num_stripes - nparity;
-       else
-               return num_stripes / ncopies;
+       return (num_stripes - nparity) / ncopies;
 }
 
 /* [pstart, pend) */
@@ -4009,6 +3962,13 @@ static inline int validate_convert_profile(struct btrfs_fs_info *fs_info,
        if (!(bargs->flags & BTRFS_BALANCE_ARGS_CONVERT))
                return true;
 
+       if (fs_info->sectorsize < PAGE_SIZE &&
+               bargs->target & BTRFS_BLOCK_GROUP_RAID56_MASK) {
+               btrfs_err(fs_info,
+               "RAID56 is not yet supported for sectorsize %u with page size %lu",
+                         fs_info->sectorsize, PAGE_SIZE);
+               return false;
+       }
        /* Profile is valid and does not have bits outside of the allowed set */
        if (alloc_profile_is_valid(bargs->target, 1) &&
            (bargs->target & ~allowed) == 0)
@@ -6857,9 +6817,31 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
        if (WARN_ON(!devid && !fs_info))
                return ERR_PTR(-EINVAL);
 
-       dev = __alloc_device(fs_info);
-       if (IS_ERR(dev))
-               return dev;
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       /*
+        * Preallocate a bio that's always going to be used for flushing device
+        * barriers and matches the device lifespan
+        */
+       dev->flush_bio = bio_kmalloc(GFP_KERNEL, 0);
+       if (!dev->flush_bio) {
+               kfree(dev);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       INIT_LIST_HEAD(&dev->dev_list);
+       INIT_LIST_HEAD(&dev->dev_alloc_list);
+       INIT_LIST_HEAD(&dev->post_commit_list);
+
+       atomic_set(&dev->reada_in_flight, 0);
+       atomic_set(&dev->dev_stats_ccnt, 0);
+       btrfs_device_data_ordered_init(dev);
+       INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
+       INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
+       extent_io_tree_init(fs_info, &dev->alloc_state,
+                           IO_TREE_DEVICE_ALLOC_STATE, NULL);
 
        if (devid)
                tmp = *devid;
@@ -6895,15 +6877,7 @@ static void btrfs_report_missing_device(struct btrfs_fs_info *fs_info,
 
 static u64 calc_stripe_length(u64 type, u64 chunk_len, int num_stripes)
 {
-       int index = btrfs_bg_flags_to_raid_index(type);
-       int ncopies = btrfs_raid_array[index].ncopies;
-       const int nparity = btrfs_raid_array[index].nparity;
-       int data_stripes;
-
-       if (nparity)
-               data_stripes = num_stripes - nparity;
-       else
-               data_stripes = num_stripes / ncopies;
+       const int data_stripes = calc_data_stripes(type, num_stripes);
 
        return div_u64(chunk_len, data_stripes);
 }