Revert "btrfs: let btrfs_delete_unused_bgs() to clean relocated bgs"
[cascardo/linux.git] / fs / btrfs / volumes.c
index 035efce..71a60cc 100644 (file)
@@ -859,7 +859,7 @@ static void btrfs_close_bdev(struct btrfs_device *device)
                blkdev_put(device->bdev, device->mode);
 }
 
-static void btrfs_close_one_device(struct btrfs_device *device)
+static void btrfs_prepare_close_one_device(struct btrfs_device *device)
 {
        struct btrfs_fs_devices *fs_devices = device->fs_devices;
        struct btrfs_device *new_device;
@@ -877,8 +877,6 @@ static void btrfs_close_one_device(struct btrfs_device *device)
        if (device->missing)
                fs_devices->missing_devices--;
 
-       btrfs_close_bdev(device);
-
        new_device = btrfs_alloc_device(NULL, &device->devid,
                                        device->uuid);
        BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
@@ -892,23 +890,39 @@ static void btrfs_close_one_device(struct btrfs_device *device)
 
        list_replace_rcu(&device->dev_list, &new_device->dev_list);
        new_device->fs_devices = device->fs_devices;
-
-       call_rcu(&device->rcu, free_device);
 }
 
 static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
 {
        struct btrfs_device *device, *tmp;
+       struct list_head pending_put;
+
+       INIT_LIST_HEAD(&pending_put);
 
        if (--fs_devices->opened > 0)
                return 0;
 
        mutex_lock(&fs_devices->device_list_mutex);
        list_for_each_entry_safe(device, tmp, &fs_devices->devices, dev_list) {
-               btrfs_close_one_device(device);
+               btrfs_prepare_close_one_device(device);
+               list_add(&device->dev_list, &pending_put);
        }
        mutex_unlock(&fs_devices->device_list_mutex);
 
+       /*
+        * btrfs_show_devname() is using the device_list_mutex,
+        * sometimes call to blkdev_put() leads vfs calling
+        * into this func. So do put outside of device_list_mutex,
+        * as of now.
+        */
+       while (!list_empty(&pending_put)) {
+               device = list_first_entry(&pending_put,
+                               struct btrfs_device, dev_list);
+               list_del(&device->dev_list);
+               btrfs_close_bdev(device);
+               call_rcu(&device->rcu, free_device);
+       }
+
        WARN_ON(fs_devices->open_devices);
        WARN_ON(fs_devices->rw_devices);
        fs_devices->opened = 0;
@@ -1140,12 +1154,12 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
        ret = device_list_add(path, disk_super, devid, fs_devices_ret);
        if (ret > 0) {
                if (disk_super->label[0]) {
-                       printk(KERN_INFO "BTRFS: device label %s ", disk_super->label);
+                       pr_info("BTRFS: device label %s ", disk_super->label);
                } else {
-                       printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid);
+                       pr_info("BTRFS: device fsid %pU ", disk_super->fsid);
                }
 
-               printk(KERN_CONT "devid %llu transid %llu %s\n", devid, transid, path);
+               pr_cont("devid %llu transid %llu %s\n", devid, transid, path);
                ret = 0;
        }
        if (!ret && fs_devices_ret)
@@ -1846,7 +1860,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
        u64 num_devices;
        int ret = 0;
        bool clear_super = false;
-       char *dev_name = NULL;
 
        mutex_lock(&uuid_mutex);
 
@@ -1882,11 +1895,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
                list_del_init(&device->dev_alloc_list);
                device->fs_devices->rw_devices--;
                unlock_chunks(root);
-               dev_name = kstrdup(device->name->str, GFP_KERNEL);
-               if (!dev_name) {
-                       ret = -ENOMEM;
-                       goto error_undo;
-               }
                clear_super = true;
        }
 
@@ -1936,14 +1944,21 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
                btrfs_sysfs_rm_device_link(root->fs_info->fs_devices, device);
        }
 
-       btrfs_close_bdev(device);
-
-       call_rcu(&device->rcu, free_device);
-
        num_devices = btrfs_super_num_devices(root->fs_info->super_copy) - 1;
        btrfs_set_super_num_devices(root->fs_info->super_copy, num_devices);
        mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
 
+       /*
+        * at this point, the device is zero sized and detached from
+        * the devices list.  All that's left is to zero out the old
+        * supers and free the device.
+        */
+       if (device->writeable)
+               btrfs_scratch_superblocks(device->bdev, device->name->str);
+
+       btrfs_close_bdev(device);
+       call_rcu(&device->rcu, free_device);
+
        if (cur_devices->open_devices == 0) {
                struct btrfs_fs_devices *fs_devices;
                fs_devices = root->fs_info->fs_devices;
@@ -1962,24 +1977,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
        root->fs_info->num_tolerated_disk_barrier_failures =
                btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info);
 
-       /*
-        * at this point, the device is zero sized.  We want to
-        * remove it from the devices list and zero out the old super
-        */
-       if (clear_super) {
-               struct block_device *bdev;
-
-               bdev = blkdev_get_by_path(dev_name, FMODE_READ | FMODE_EXCL,
-                                               root->fs_info->bdev_holder);
-               if (!IS_ERR(bdev)) {
-                       btrfs_scratch_superblocks(bdev, dev_name);
-                       blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
-               }
-       }
-
 out:
-       kfree(dev_name);
-
        mutex_unlock(&uuid_mutex);
        return ret;
 
@@ -2494,9 +2492,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
                ret = btrfs_relocate_sys_chunks(root);
                if (ret < 0)
                        btrfs_handle_fs_error(root->fs_info, ret,
-                                   "Failed to relocate sys chunks after "
-                                   "device initialization. This can be fixed "
-                                   "using the \"btrfs balance\" command.");
+                                   "Failed to relocate sys chunks after device initialization. This can be fixed using the \"btrfs balance\" command.");
                trans = btrfs_attach_transaction(root);
                if (IS_ERR(trans)) {
                        if (PTR_ERR(trans) == -ENOENT)
@@ -2555,7 +2551,8 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
        devices = &fs_info->fs_devices->devices;
        list_for_each_entry(device, devices, dev_list) {
                if (device->bdev == bdev) {
-                       btrfs_err(fs_info, "target device is in the filesystem!");
+                       btrfs_err(fs_info,
+                                 "target device is in the filesystem!");
                        ret = -EEXIST;
                        goto error;
                }
@@ -2564,7 +2561,8 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
 
        if (i_size_read(bdev->bd_inode) <
            btrfs_device_get_total_bytes(srcdev)) {
-               btrfs_err(fs_info, "target device is smaller than source device!");
+               btrfs_err(fs_info,
+                         "target device is smaller than source device!");
                ret = -EINVAL;
                goto error;
        }
@@ -3698,7 +3696,7 @@ error:
        btrfs_free_path(path);
        if (enospc_errors) {
                btrfs_info(fs_info, "%d enospc errors during balance",
-                      enospc_errors);
+                          enospc_errors);
                if (!ret)
                        ret = -ENOSPC;
        }
@@ -3792,8 +3790,8 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
                if (!(bctl->flags & BTRFS_BALANCE_DATA) ||
                    !(bctl->flags & BTRFS_BALANCE_METADATA) ||
                    memcmp(&bctl->data, &bctl->meta, sizeof(bctl->data))) {
-                       btrfs_err(fs_info, "with mixed groups data and "
-                                  "metadata balance options must be the same");
+                       btrfs_err(fs_info,
+                                 "with mixed groups data and metadata balance options must be the same");
                        ret = -EINVAL;
                        goto out;
                }
@@ -3815,23 +3813,23 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
                allowed |= (BTRFS_BLOCK_GROUP_RAID10 |
                            BTRFS_BLOCK_GROUP_RAID6);
        if (validate_convert_profile(&bctl->data, allowed)) {
-               btrfs_err(fs_info, "unable to start balance with target "
-                          "data profile %llu",
-                      bctl->data.target);
+               btrfs_err(fs_info,
+                         "unable to start balance with target data profile %llu",
+                         bctl->data.target);
                ret = -EINVAL;
                goto out;
        }
        if (validate_convert_profile(&bctl->meta, allowed)) {
                btrfs_err(fs_info,
-                          "unable to start balance with target metadata profile %llu",
-                      bctl->meta.target);
+                         "unable to start balance with target metadata profile %llu",
+                         bctl->meta.target);
                ret = -EINVAL;
                goto out;
        }
        if (validate_convert_profile(&bctl->sys, allowed)) {
                btrfs_err(fs_info,
-                          "unable to start balance with target system profile %llu",
-                      bctl->sys.target);
+                         "unable to start balance with target system profile %llu",
+                         bctl->sys.target);
                ret = -EINVAL;
                goto out;
        }
@@ -3851,10 +3849,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
                     (fs_info->avail_metadata_alloc_bits & allowed) &&
                     !(bctl->meta.target & allowed))) {
                        if (bctl->flags & BTRFS_BALANCE_FORCE) {
-                               btrfs_info(fs_info, "force reducing metadata integrity");
+                               btrfs_info(fs_info,
+                                          "force reducing metadata integrity");
                        } else {
-                               btrfs_err(fs_info, "balance will reduce metadata "
-                                          "integrity, use force if you want this");
+                               btrfs_err(fs_info,
+                                         "balance will reduce metadata integrity, use force if you want this");
                                ret = -EINVAL;
                                goto out;
                        }
@@ -3864,8 +3863,8 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
        if (btrfs_get_num_tolerated_disk_barrier_failures(bctl->meta.target) <
                btrfs_get_num_tolerated_disk_barrier_failures(bctl->data.target)) {
                btrfs_warn(fs_info,
-       "metadata profile 0x%llx has lower redundancy than data profile 0x%llx",
-                       bctl->meta.target, bctl->data.target);
+                          "metadata profile 0x%llx has lower redundancy than data profile 0x%llx",
+                          bctl->meta.target, bctl->data.target);
        }
 
        if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
@@ -4221,7 +4220,7 @@ out:
        if (ret)
                btrfs_warn(fs_info, "btrfs_uuid_scan_kthread failed %d", ret);
        else
-               fs_info->update_uuid_tree_gen = 1;
+               set_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags);
        up(&fs_info->uuid_tree_rescan_sem);
        return 0;
 }
@@ -4913,15 +4912,16 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
        read_unlock(&em_tree->lock);
 
        if (!em) {
-               btrfs_crit(extent_root->fs_info, "unable to find logical "
-                          "%Lu len %Lu", chunk_offset, chunk_size);
+               btrfs_crit(extent_root->fs_info,
+                          "unable to find logical %Lu len %Lu",
+                          chunk_offset, chunk_size);
                return -EINVAL;
        }
 
        if (em->start != chunk_offset || em->len != chunk_size) {
-               btrfs_crit(extent_root->fs_info, "found a bad mapping, wanted"
-                         " %Lu-%Lu, found %Lu-%Lu", chunk_offset,
-                         chunk_size, em->start, em->len);
+               btrfs_crit(extent_root->fs_info,
+                          "found a bad mapping, wanted %Lu-%Lu, found %Lu-%Lu",
+                           chunk_offset, chunk_size, em->start, em->len);
                free_extent_map(em);
                return -EINVAL;
        }
@@ -5154,9 +5154,9 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
        }
 
        if (em->start > logical || em->start + em->len < logical) {
-               btrfs_crit(fs_info, "Invalid mapping for %Lu-%Lu, got "
-                           "%Lu-%Lu", logical, logical+len, em->start,
-                           em->start + em->len);
+               btrfs_crit(fs_info, "Invalid mapping for %Lu-%Lu, got %Lu-%Lu",
+                          logical, logical+len, em->start,
+                          em->start + em->len);
                free_extent_map(em);
                return 1;
        }
@@ -5370,9 +5370,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int op,
        }
 
        if (em->start > logical || em->start + em->len < logical) {
-               btrfs_crit(fs_info, "found a bad mapping, wanted %Lu, "
-                          "found %Lu-%Lu", logical, em->start,
-                          em->start + em->len);
+               btrfs_crit(fs_info,
+                          "found a bad mapping, wanted %Lu, found %Lu-%Lu",
+                          logical, em->start, em->start + em->len);
                free_extent_map(em);
                return -EINVAL;
        }
@@ -5390,9 +5390,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int op,
 
        stripe_offset = stripe_nr * stripe_len;
        if (offset < stripe_offset) {
-               btrfs_crit(fs_info, "stripe math has gone wrong, "
-                          "stripe_offset=%llu, offset=%llu, start=%llu, "
-                          "logical=%llu, stripe_len=%llu",
+               btrfs_crit(fs_info,
+                          "stripe math has gone wrong, stripe_offset=%llu, offset=%llu, start=%llu, logical=%llu, stripe_len=%llu",
                           stripe_offset, offset, em->start, logical,
                           stripe_len);
                free_extent_map(em);
@@ -5642,8 +5641,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int op,
                mirror_num = stripe_index + 1;
        }
        if (stripe_index >= map->num_stripes) {
-               btrfs_crit(fs_info, "stripe index math went horribly wrong, "
-                          "got stripe_index=%u, num_stripes=%u",
+               btrfs_crit(fs_info,
+                          "stripe index math went horribly wrong, got stripe_index=%u, num_stripes=%u",
                           stripe_index, map->num_stripes);
                ret = -EINVAL;
                goto out;
@@ -5907,10 +5906,11 @@ int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int op,
                                 mirror_num, need_raid_map);
 }
 
-int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
+int btrfs_rmap_block(struct btrfs_fs_info *fs_info,
                     u64 chunk_start, u64 physical, u64 devid,
                     u64 **logical, int *naddrs, int *stripe_len)
 {
+       struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
        struct extent_map_tree *em_tree = &map_tree->map_tree;
        struct extent_map *em;
        struct map_lookup *map;
@@ -5926,13 +5926,13 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
        read_unlock(&em_tree->lock);
 
        if (!em) {
-               printk(KERN_ERR "BTRFS: couldn't find em for chunk %Lu\n",
-                      chunk_start);
+               btrfs_err(fs_info, "couldn't find em for chunk %Lu",
+                       chunk_start);
                return -EIO;
        }
 
        if (em->start != chunk_start) {
-               printk(KERN_ERR "BTRFS: bad chunk start, em=%Lu, wanted=%Lu\n",
+               btrfs_err(fs_info, "bad chunk start, em=%Lu, wanted=%Lu",
                       em->start, chunk_start);
                free_extent_map(em);
                return -EIO;
@@ -6137,10 +6137,12 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
 
                rcu_read_lock();
                name = rcu_dereference(dev->name);
-               pr_debug("btrfs_map_bio: rw %d 0x%x, sector=%llu, dev=%lu "
-                        "(%s id %llu), size=%u\n", bio_op(bio), bio->bi_opf,
-                        (u64)bio->bi_iter.bi_sector, (u_long)dev->bdev->bd_dev,
-                        name->str, dev->devid, bio->bi_iter.bi_size);
+               btrfs_debug(fs_info,
+                       "btrfs_map_bio: rw %d 0x%x, sector=%llu, dev=%lu (%s id %llu), size=%u",
+                       bio_op(bio), bio->bi_opf,
+                       (u64)bio->bi_iter.bi_sector,
+                       (u_long)dev->bdev->bd_dev, name->str, dev->devid,
+                       bio->bi_iter.bi_size);
                rcu_read_unlock();
        }
 #endif
@@ -6215,8 +6217,9 @@ int btrfs_map_bio(struct btrfs_root *root, struct bio *bio,
        }
 
        if (map_length < length) {
-               btrfs_crit(root->fs_info, "mapping failed logical %llu bio len %llu len %llu",
-                       logical, length, map_length);
+               btrfs_crit(root->fs_info,
+                          "mapping failed logical %llu bio len %llu len %llu",
+                          logical, length, map_length);
                BUG();
        }
 
@@ -6483,8 +6486,9 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
                                free_extent_map(em);
                                return -EIO;
                        }
-                       btrfs_warn(root->fs_info, "devid %llu uuid %pU is missing",
-                                               devid, uuid);
+                       btrfs_warn(root->fs_info,
+                                  "devid %llu uuid %pU is missing",
+                                  devid, uuid);
                }
                map->stripes[i].dev->in_fs_metadata = 1;
        }
@@ -6661,7 +6665,8 @@ static int read_one_dev(struct btrfs_root *root,
 
 int btrfs_read_sys_array(struct btrfs_root *root)
 {
-       struct btrfs_super_block *super_copy = root->fs_info->super_copy;
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct btrfs_super_block *super_copy = fs_info->super_copy;
        struct extent_buffer *sb;
        struct btrfs_disk_key *disk_key;
        struct btrfs_chunk *chunk;
@@ -6732,8 +6737,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
 
                        num_stripes = btrfs_chunk_num_stripes(sb, chunk);
                        if (!num_stripes) {
-                               printk(KERN_ERR
-           "BTRFS: invalid number of stripes %u in sys_array at offset %u\n",
+                               btrfs_err(fs_info,
+                                       "invalid number of stripes %u in sys_array at offset %u",
                                        num_stripes, cur_offset);
                                ret = -EIO;
                                break;
@@ -6741,7 +6746,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
 
                        type = btrfs_chunk_type(sb, chunk);
                        if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) {
-                               btrfs_err(root->fs_info,
+                               btrfs_err(fs_info,
                            "invalid chunk type %llu in sys_array at offset %u",
                                        type, cur_offset);
                                ret = -EIO;
@@ -6756,9 +6761,9 @@ int btrfs_read_sys_array(struct btrfs_root *root)
                        if (ret)
                                break;
                } else {
-                       printk(KERN_ERR
-               "BTRFS: unexpected item type %u in sys_array at offset %u\n",
-                               (u32)key.type, cur_offset);
+                       btrfs_err(fs_info,
+                           "unexpected item type %u in sys_array at offset %u",
+                                 (u32)key.type, cur_offset);
                        ret = -EIO;
                        break;
                }
@@ -6771,7 +6776,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
        return ret;
 
 out_short_read:
-       printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n",
+       btrfs_err(fs_info, "sys_array too short to read %u bytes at offset %u",
                        len, cur_offset);
        clear_extent_buffer_uptodate(sb);
        free_extent_buffer_stale(sb);
@@ -7095,10 +7100,12 @@ int btrfs_get_dev_stats(struct btrfs_root *root,
        mutex_unlock(&fs_devices->device_list_mutex);
 
        if (!dev) {
-               btrfs_warn(root->fs_info, "get dev_stats failed, device not found");
+               btrfs_warn(root->fs_info,
+                          "get dev_stats failed, device not found");
                return -ENODEV;
        } else if (!dev->dev_stats_valid) {
-               btrfs_warn(root->fs_info, "get dev_stats failed, not yet valid");
+               btrfs_warn(root->fs_info,
+                          "get dev_stats failed, not yet valid");
                return -ENODEV;
        } else if (stats->flags & BTRFS_DEV_STATS_RESET) {
                for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) {