aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-09-03 09:35:41 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:38:42 -0400
commit2196d6e8a71fc901e31c1d81581fc6cc6c64913e (patch)
tree41d1aaaafcd9e6792a3a368407f4416c6d4b7ac8 /fs/btrfs/volumes.c
parent15484377f597ca98ee84de87caa13667ea68bb14 (diff)
Btrfs: Fix misuse of chunk mutex
There were several problems about chunk mutex usage: - Lock chunk mutex when updating metadata. It would cause the nested deadlock because updating metadata might need allocate new chunks that need acquire chunk mutex. We remove chunk mutex at this case, because b-tree lock and other lock mechanism can help us. - ABBA deadlock occured between device_list_mutex and chunk_mutex. When we update device status, we must acquire device_list_mutex at the beginning, and then we might get chunk_mutex during the device status update because we need allocate new chunks for metadata COW. But at most place, we acquire chunk_mutex at first and then acquire device list mutex. We need change the lock order. - Some place we needn't acquire chunk_mutex. For example we needn't get chunk_mutex when we free a empty seed fs_devices structure. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c129
1 files changed, 62 insertions, 67 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 9f22398d465f..105c5fe004db 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1264,7 +1264,7 @@ out:
1264 1264
1265static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, 1265static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
1266 struct btrfs_device *device, 1266 struct btrfs_device *device,
1267 u64 start) 1267 u64 start, u64 *dev_extent_len)
1268{ 1268{
1269 int ret; 1269 int ret;
1270 struct btrfs_path *path; 1270 struct btrfs_path *path;
@@ -1306,13 +1306,8 @@ again:
1306 goto out; 1306 goto out;
1307 } 1307 }
1308 1308
1309 if (device->bytes_used > 0) { 1309 *dev_extent_len = btrfs_dev_extent_length(leaf, extent);
1310 u64 len = btrfs_dev_extent_length(leaf, extent); 1310
1311 btrfs_device_set_bytes_used(device, device->bytes_used - len);
1312 spin_lock(&root->fs_info->free_chunk_lock);
1313 root->fs_info->free_chunk_space += len;
1314 spin_unlock(&root->fs_info->free_chunk_lock);
1315 }
1316 ret = btrfs_del_item(trans, root, path); 1311 ret = btrfs_del_item(trans, root, path);
1317 if (ret) { 1312 if (ret) {
1318 btrfs_error(root->fs_info, ret, 1313 btrfs_error(root->fs_info, ret,
@@ -1521,7 +1516,6 @@ static int btrfs_rm_dev_item(struct btrfs_root *root,
1521 key.objectid = BTRFS_DEV_ITEMS_OBJECTID; 1516 key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
1522 key.type = BTRFS_DEV_ITEM_KEY; 1517 key.type = BTRFS_DEV_ITEM_KEY;
1523 key.offset = device->devid; 1518 key.offset = device->devid;
1524 lock_chunks(root);
1525 1519
1526 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 1520 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
1527 if (ret < 0) 1521 if (ret < 0)
@@ -1537,7 +1531,6 @@ static int btrfs_rm_dev_item(struct btrfs_root *root,
1537 goto out; 1531 goto out;
1538out: 1532out:
1539 btrfs_free_path(path); 1533 btrfs_free_path(path);
1540 unlock_chunks(root);
1541 btrfs_commit_transaction(trans, root); 1534 btrfs_commit_transaction(trans, root);
1542 return ret; 1535 return ret;
1543} 1536}
@@ -1726,9 +1719,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
1726 fs_devices = fs_devices->seed; 1719 fs_devices = fs_devices->seed;
1727 } 1720 }
1728 cur_devices->seed = NULL; 1721 cur_devices->seed = NULL;
1729 lock_chunks(root);
1730 __btrfs_close_devices(cur_devices); 1722 __btrfs_close_devices(cur_devices);
1731 unlock_chunks(root);
1732 free_fs_devices(cur_devices); 1723 free_fs_devices(cur_devices);
1733 } 1724 }
1734 1725
@@ -1990,11 +1981,12 @@ static int btrfs_prepare_sprout(struct btrfs_root *root)
1990 mutex_lock(&root->fs_info->fs_devices->device_list_mutex); 1981 mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
1991 list_splice_init_rcu(&fs_devices->devices, &seed_devices->devices, 1982 list_splice_init_rcu(&fs_devices->devices, &seed_devices->devices,
1992 synchronize_rcu); 1983 synchronize_rcu);
1984 list_for_each_entry(device, &seed_devices->devices, dev_list)
1985 device->fs_devices = seed_devices;
1993 1986
1987 lock_chunks(root);
1994 list_splice_init(&fs_devices->alloc_list, &seed_devices->alloc_list); 1988 list_splice_init(&fs_devices->alloc_list, &seed_devices->alloc_list);
1995 list_for_each_entry(device, &seed_devices->devices, dev_list) { 1989 unlock_chunks(root);
1996 device->fs_devices = seed_devices;
1997 }
1998 1990
1999 fs_devices->seeding = 0; 1991 fs_devices->seeding = 0;
2000 fs_devices->num_devices = 0; 1992 fs_devices->num_devices = 0;
@@ -2155,8 +2147,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
2155 goto error; 2147 goto error;
2156 } 2148 }
2157 2149
2158 lock_chunks(root);
2159
2160 q = bdev_get_queue(bdev); 2150 q = bdev_get_queue(bdev);
2161 if (blk_queue_discard(q)) 2151 if (blk_queue_discard(q))
2162 device->can_discard = 1; 2152 device->can_discard = 1;
@@ -2185,6 +2175,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
2185 device->fs_devices = root->fs_info->fs_devices; 2175 device->fs_devices = root->fs_info->fs_devices;
2186 2176
2187 mutex_lock(&root->fs_info->fs_devices->device_list_mutex); 2177 mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
2178 lock_chunks(root);
2188 list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices); 2179 list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices);
2189 list_add(&device->dev_alloc_list, 2180 list_add(&device->dev_alloc_list,
2190 &root->fs_info->fs_devices->alloc_list); 2181 &root->fs_info->fs_devices->alloc_list);
@@ -2212,15 +2203,34 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
2212 /* add sysfs device entry */ 2203 /* add sysfs device entry */
2213 btrfs_kobj_add_device(root->fs_info, device); 2204 btrfs_kobj_add_device(root->fs_info, device);
2214 2205
2206 /*
2207 * we've got more storage, clear any full flags on the space
2208 * infos
2209 */
2210 btrfs_clear_space_info_full(root->fs_info);
2211
2212 unlock_chunks(root);
2215 mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); 2213 mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
2216 2214
2217 if (seeding_dev) { 2215 if (seeding_dev) {
2218 char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 2216 lock_chunks(root);
2219 ret = init_first_rw_device(trans, root, device); 2217 ret = init_first_rw_device(trans, root, device);
2218 unlock_chunks(root);
2220 if (ret) { 2219 if (ret) {
2221 btrfs_abort_transaction(trans, root, ret); 2220 btrfs_abort_transaction(trans, root, ret);
2222 goto error_trans; 2221 goto error_trans;
2223 } 2222 }
2223 }
2224
2225 ret = btrfs_add_device(trans, root, device);
2226 if (ret) {
2227 btrfs_abort_transaction(trans, root, ret);
2228 goto error_trans;
2229 }
2230
2231 if (seeding_dev) {
2232 char fsid_buf[BTRFS_UUID_UNPARSED_SIZE];
2233
2224 ret = btrfs_finish_sprout(trans, root); 2234 ret = btrfs_finish_sprout(trans, root);
2225 if (ret) { 2235 if (ret) {
2226 btrfs_abort_transaction(trans, root, ret); 2236 btrfs_abort_transaction(trans, root, ret);
@@ -2234,21 +2244,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
2234 root->fs_info->fsid); 2244 root->fs_info->fsid);
2235 if (kobject_rename(&root->fs_info->super_kobj, fsid_buf)) 2245 if (kobject_rename(&root->fs_info->super_kobj, fsid_buf))
2236 goto error_trans; 2246 goto error_trans;
2237 } else {
2238 ret = btrfs_add_device(trans, root, device);
2239 if (ret) {
2240 btrfs_abort_transaction(trans, root, ret);
2241 goto error_trans;
2242 }
2243 } 2247 }
2244 2248
2245 /*
2246 * we've got more storage, clear any full flags on the space
2247 * infos
2248 */
2249 btrfs_clear_space_info_full(root->fs_info);
2250
2251 unlock_chunks(root);
2252 root->fs_info->num_tolerated_disk_barrier_failures = 2249 root->fs_info->num_tolerated_disk_barrier_failures =
2253 btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info); 2250 btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info);
2254 ret = btrfs_commit_transaction(trans, root); 2251 ret = btrfs_commit_transaction(trans, root);
@@ -2280,7 +2277,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
2280 return ret; 2277 return ret;
2281 2278
2282error_trans: 2279error_trans:
2283 unlock_chunks(root);
2284 btrfs_end_transaction(trans, root); 2280 btrfs_end_transaction(trans, root);
2285 rcu_string_free(device->name); 2281 rcu_string_free(device->name);
2286 btrfs_kobj_rm_device(root->fs_info, device); 2282 btrfs_kobj_rm_device(root->fs_info, device);
@@ -2449,20 +2445,27 @@ out:
2449 return ret; 2445 return ret;
2450} 2446}
2451 2447
2452static int __btrfs_grow_device(struct btrfs_trans_handle *trans, 2448int btrfs_grow_device(struct btrfs_trans_handle *trans,
2453 struct btrfs_device *device, u64 new_size) 2449 struct btrfs_device *device, u64 new_size)
2454{ 2450{
2455 struct btrfs_super_block *super_copy = 2451 struct btrfs_super_block *super_copy =
2456 device->dev_root->fs_info->super_copy; 2452 device->dev_root->fs_info->super_copy;
2457 struct btrfs_fs_devices *fs_devices; 2453 struct btrfs_fs_devices *fs_devices;
2458 u64 old_total = btrfs_super_total_bytes(super_copy); 2454 u64 old_total;
2459 u64 diff = new_size - device->total_bytes; 2455 u64 diff;
2460 2456
2461 if (!device->writeable) 2457 if (!device->writeable)
2462 return -EACCES; 2458 return -EACCES;
2459
2460 lock_chunks(device->dev_root);
2461 old_total = btrfs_super_total_bytes(super_copy);
2462 diff = new_size - device->total_bytes;
2463
2463 if (new_size <= device->total_bytes || 2464 if (new_size <= device->total_bytes ||
2464 device->is_tgtdev_for_dev_replace) 2465 device->is_tgtdev_for_dev_replace) {
2466 unlock_chunks(device->dev_root);
2465 return -EINVAL; 2467 return -EINVAL;
2468 }
2466 2469
2467 fs_devices = device->dev_root->fs_info->fs_devices; 2470 fs_devices = device->dev_root->fs_info->fs_devices;
2468 2471
@@ -2475,20 +2478,11 @@ static int __btrfs_grow_device(struct btrfs_trans_handle *trans,
2475 if (list_empty(&device->resized_list)) 2478 if (list_empty(&device->resized_list))
2476 list_add_tail(&device->resized_list, 2479 list_add_tail(&device->resized_list,
2477 &fs_devices->resized_devices); 2480 &fs_devices->resized_devices);
2481 unlock_chunks(device->dev_root);
2478 2482
2479 return btrfs_update_device(trans, device); 2483 return btrfs_update_device(trans, device);
2480} 2484}
2481 2485
2482int btrfs_grow_device(struct btrfs_trans_handle *trans,
2483 struct btrfs_device *device, u64 new_size)
2484{
2485 int ret;
2486 lock_chunks(device->dev_root);
2487 ret = __btrfs_grow_device(trans, device, new_size);
2488 unlock_chunks(device->dev_root);
2489 return ret;
2490}
2491
2492static int btrfs_free_chunk(struct btrfs_trans_handle *trans, 2486static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
2493 struct btrfs_root *root, 2487 struct btrfs_root *root,
2494 u64 chunk_tree, u64 chunk_objectid, 2488 u64 chunk_tree, u64 chunk_objectid,
@@ -2540,6 +2534,7 @@ static int btrfs_del_sys_chunk(struct btrfs_root *root, u64 chunk_objectid, u64
2540 u32 cur; 2534 u32 cur;
2541 struct btrfs_key key; 2535 struct btrfs_key key;
2542 2536
2537 lock_chunks(root);
2543 array_size = btrfs_super_sys_array_size(super_copy); 2538 array_size = btrfs_super_sys_array_size(super_copy);
2544 2539
2545 ptr = super_copy->sys_chunk_array; 2540 ptr = super_copy->sys_chunk_array;
@@ -2569,6 +2564,7 @@ static int btrfs_del_sys_chunk(struct btrfs_root *root, u64 chunk_objectid, u64
2569 cur += len; 2564 cur += len;
2570 } 2565 }
2571 } 2566 }
2567 unlock_chunks(root);
2572 return ret; 2568 return ret;
2573} 2569}
2574 2570
@@ -2579,8 +2575,10 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
2579 struct extent_map_tree *em_tree; 2575 struct extent_map_tree *em_tree;
2580 struct btrfs_root *extent_root; 2576 struct btrfs_root *extent_root;
2581 struct btrfs_trans_handle *trans; 2577 struct btrfs_trans_handle *trans;
2578 struct btrfs_device *device;
2582 struct extent_map *em; 2579 struct extent_map *em;
2583 struct map_lookup *map; 2580 struct map_lookup *map;
2581 u64 dev_extent_len = 0;
2584 int ret; 2582 int ret;
2585 int i; 2583 int i;
2586 2584
@@ -2604,8 +2602,6 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
2604 return ret; 2602 return ret;
2605 } 2603 }
2606 2604
2607 lock_chunks(root);
2608
2609 /* 2605 /*
2610 * step two, delete the device extents and the 2606 * step two, delete the device extents and the
2611 * chunk tree entries 2607 * chunk tree entries
@@ -2619,10 +2615,23 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
2619 map = (struct map_lookup *)em->bdev; 2615 map = (struct map_lookup *)em->bdev;
2620 2616
2621 for (i = 0; i < map->num_stripes; i++) { 2617 for (i = 0; i < map->num_stripes; i++) {
2622 ret = btrfs_free_dev_extent(trans, map->stripes[i].dev, 2618 device = map->stripes[i].dev;
2623 map->stripes[i].physical); 2619 ret = btrfs_free_dev_extent(trans, device,
2620 map->stripes[i].physical,
2621 &dev_extent_len);
2624 BUG_ON(ret); 2622 BUG_ON(ret);
2625 2623
2624 if (device->bytes_used > 0) {
2625 lock_chunks(root);
2626 btrfs_device_set_bytes_used(device,
2627 device->bytes_used - dev_extent_len);
2628 spin_lock(&root->fs_info->free_chunk_lock);
2629 root->fs_info->free_chunk_space += dev_extent_len;
2630 spin_unlock(&root->fs_info->free_chunk_lock);
2631 btrfs_clear_space_info_full(root->fs_info);
2632 unlock_chunks(root);
2633 }
2634
2626 if (map->stripes[i].dev) { 2635 if (map->stripes[i].dev) {
2627 ret = btrfs_update_device(trans, map->stripes[i].dev); 2636 ret = btrfs_update_device(trans, map->stripes[i].dev);
2628 BUG_ON(ret); 2637 BUG_ON(ret);
@@ -2652,7 +2661,6 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
2652 /* once for us */ 2661 /* once for us */
2653 free_extent_map(em); 2662 free_extent_map(em);
2654 2663
2655 unlock_chunks(root);
2656 btrfs_end_transaction(trans, root); 2664 btrfs_end_transaction(trans, root);
2657 return 0; 2665 return 0;
2658} 2666}
@@ -4029,16 +4037,12 @@ again:
4029 list_add_tail(&device->resized_list, 4037 list_add_tail(&device->resized_list,
4030 &root->fs_info->fs_devices->resized_devices); 4038 &root->fs_info->fs_devices->resized_devices);
4031 4039
4032 /* Now btrfs_update_device() will change the on-disk size. */
4033 ret = btrfs_update_device(trans, device);
4034 if (ret) {
4035 unlock_chunks(root);
4036 btrfs_end_transaction(trans, root);
4037 goto done;
4038 }
4039 WARN_ON(diff > old_total); 4040 WARN_ON(diff > old_total);
4040 btrfs_set_super_total_bytes(super_copy, old_total - diff); 4041 btrfs_set_super_total_bytes(super_copy, old_total - diff);
4041 unlock_chunks(root); 4042 unlock_chunks(root);
4043
4044 /* Now btrfs_update_device() will change the on-disk size. */
4045 ret = btrfs_update_device(trans, device);
4042 btrfs_end_transaction(trans, root); 4046 btrfs_end_transaction(trans, root);
4043done: 4047done:
4044 btrfs_free_path(path); 4048 btrfs_free_path(path);
@@ -4612,15 +4616,6 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
4612 alloc_profile = btrfs_get_alloc_profile(fs_info->chunk_root, 0); 4616 alloc_profile = btrfs_get_alloc_profile(fs_info->chunk_root, 0);
4613 ret = __btrfs_alloc_chunk(trans, extent_root, sys_chunk_offset, 4617 ret = __btrfs_alloc_chunk(trans, extent_root, sys_chunk_offset,
4614 alloc_profile); 4618 alloc_profile);
4615 if (ret) {
4616 btrfs_abort_transaction(trans, root, ret);
4617 goto out;
4618 }
4619
4620 ret = btrfs_add_device(trans, fs_info->chunk_root, device);
4621 if (ret)
4622 btrfs_abort_transaction(trans, root, ret);
4623out:
4624 return ret; 4619 return ret;
4625} 4620}
4626 4621