aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-07-08 14:19:17 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:04 -0400
commit7d9eb12c8739e7dc80c78c6b3596f912ecd8f941 (patch)
tree000608285b44920f22e0888753b36299bc762cef /fs/btrfs/volumes.c
parenta7a16fd772620605c76e8ac8bdbc8ccc9e3df1a0 (diff)
Btrfs: Add locking around volume management (device add/remove/balance)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c58
1 files changed, 44 insertions, 14 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 4e7cee27aab5..5e6ee7a6f738 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -56,6 +56,18 @@ void btrfs_unlock_volumes(void)
56 mutex_unlock(&uuid_mutex); 56 mutex_unlock(&uuid_mutex);
57} 57}
58 58
59static void lock_chunks(struct btrfs_root *root)
60{
61 mutex_lock(&root->fs_info->alloc_mutex);
62 mutex_lock(&root->fs_info->chunk_mutex);
63}
64
65static void unlock_chunks(struct btrfs_root *root)
66{
67 mutex_unlock(&root->fs_info->alloc_mutex);
68 mutex_unlock(&root->fs_info->chunk_mutex);
69}
70
59int btrfs_cleanup_fs_uuids(void) 71int btrfs_cleanup_fs_uuids(void)
60{ 72{
61 struct btrfs_fs_devices *fs_devices; 73 struct btrfs_fs_devices *fs_devices;
@@ -822,6 +834,7 @@ static int btrfs_rm_dev_item(struct btrfs_root *root,
822 key.objectid = BTRFS_DEV_ITEMS_OBJECTID; 834 key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
823 key.type = BTRFS_DEV_ITEM_KEY; 835 key.type = BTRFS_DEV_ITEM_KEY;
824 key.offset = device->devid; 836 key.offset = device->devid;
837 lock_chunks(root);
825 838
826 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 839 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
827 if (ret < 0) 840 if (ret < 0)
@@ -856,6 +869,7 @@ static int btrfs_rm_dev_item(struct btrfs_root *root,
856 total_bytes - 1); 869 total_bytes - 1);
857out: 870out:
858 btrfs_free_path(path); 871 btrfs_free_path(path);
872 unlock_chunks(root);
859 btrfs_commit_transaction(trans, root); 873 btrfs_commit_transaction(trans, root);
860 return ret; 874 return ret;
861} 875}
@@ -870,9 +884,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
870 u64 devid; 884 u64 devid;
871 int ret = 0; 885 int ret = 0;
872 886
873 mutex_lock(&root->fs_info->alloc_mutex);
874 mutex_lock(&root->fs_info->chunk_mutex);
875 mutex_lock(&uuid_mutex); 887 mutex_lock(&uuid_mutex);
888 mutex_lock(&root->fs_info->volume_mutex);
876 889
877 all_avail = root->fs_info->avail_data_alloc_bits | 890 all_avail = root->fs_info->avail_data_alloc_bits |
878 root->fs_info->avail_system_alloc_bits | 891 root->fs_info->avail_system_alloc_bits |
@@ -988,9 +1001,8 @@ error_close:
988 if (bdev) 1001 if (bdev)
989 close_bdev_excl(bdev); 1002 close_bdev_excl(bdev);
990out: 1003out:
1004 mutex_unlock(&root->fs_info->volume_mutex);
991 mutex_unlock(&uuid_mutex); 1005 mutex_unlock(&uuid_mutex);
992 mutex_unlock(&root->fs_info->chunk_mutex);
993 mutex_unlock(&root->fs_info->alloc_mutex);
994 return ret; 1006 return ret;
995} 1007}
996 1008
@@ -1010,10 +1022,10 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1010 return -EIO; 1022 return -EIO;
1011 } 1023 }
1012 1024
1013 mutex_lock(&root->fs_info->alloc_mutex); 1025 mutex_lock(&root->fs_info->volume_mutex);
1014 mutex_lock(&root->fs_info->chunk_mutex);
1015 1026
1016 trans = btrfs_start_transaction(root, 1); 1027 trans = btrfs_start_transaction(root, 1);
1028 lock_chunks(root);
1017 devices = &root->fs_info->fs_devices->devices; 1029 devices = &root->fs_info->fs_devices->devices;
1018 list_for_each(cur, devices) { 1030 list_for_each(cur, devices) {
1019 device = list_entry(cur, struct btrfs_device, dev_list); 1031 device = list_entry(cur, struct btrfs_device, dev_list);
@@ -1065,9 +1077,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1065 root->fs_info->fs_devices->num_devices++; 1077 root->fs_info->fs_devices->num_devices++;
1066 root->fs_info->fs_devices->open_devices++; 1078 root->fs_info->fs_devices->open_devices++;
1067out: 1079out:
1080 unlock_chunks(root);
1068 btrfs_end_transaction(trans, root); 1081 btrfs_end_transaction(trans, root);
1069 mutex_unlock(&root->fs_info->chunk_mutex); 1082 mutex_unlock(&root->fs_info->volume_mutex);
1070 mutex_unlock(&root->fs_info->alloc_mutex);
1071 1083
1072 return ret; 1084 return ret;
1073 1085
@@ -1122,7 +1134,7 @@ out:
1122 return ret; 1134 return ret;
1123} 1135}
1124 1136
1125int btrfs_grow_device(struct btrfs_trans_handle *trans, 1137static int __btrfs_grow_device(struct btrfs_trans_handle *trans,
1126 struct btrfs_device *device, u64 new_size) 1138 struct btrfs_device *device, u64 new_size)
1127{ 1139{
1128 struct btrfs_super_block *super_copy = 1140 struct btrfs_super_block *super_copy =
@@ -1134,6 +1146,16 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
1134 return btrfs_update_device(trans, device); 1146 return btrfs_update_device(trans, device);
1135} 1147}
1136 1148
1149int btrfs_grow_device(struct btrfs_trans_handle *trans,
1150 struct btrfs_device *device, u64 new_size)
1151{
1152 int ret;
1153 lock_chunks(device->dev_root);
1154 ret = __btrfs_grow_device(trans, device, new_size);
1155 unlock_chunks(device->dev_root);
1156 return ret;
1157}
1158
1137static int btrfs_free_chunk(struct btrfs_trans_handle *trans, 1159static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
1138 struct btrfs_root *root, 1160 struct btrfs_root *root,
1139 u64 chunk_tree, u64 chunk_objectid, 1161 u64 chunk_tree, u64 chunk_objectid,
@@ -1234,6 +1256,8 @@ int btrfs_relocate_chunk(struct btrfs_root *root,
1234 trans = btrfs_start_transaction(root, 1); 1256 trans = btrfs_start_transaction(root, 1);
1235 BUG_ON(!trans); 1257 BUG_ON(!trans);
1236 1258
1259 lock_chunks(root);
1260
1237 /* 1261 /*
1238 * step two, delete the device extents and the 1262 * step two, delete the device extents and the
1239 * chunk tree entries 1263 * chunk tree entries
@@ -1278,6 +1302,7 @@ int btrfs_relocate_chunk(struct btrfs_root *root,
1278 /* once for us */ 1302 /* once for us */
1279 free_extent_map(em); 1303 free_extent_map(em);
1280 1304
1305 unlock_chunks(root);
1281 btrfs_end_transaction(trans, root); 1306 btrfs_end_transaction(trans, root);
1282 return 0; 1307 return 0;
1283} 1308}
@@ -1308,8 +1333,7 @@ int btrfs_balance(struct btrfs_root *dev_root)
1308 struct btrfs_key found_key; 1333 struct btrfs_key found_key;
1309 1334
1310 1335
1311 BUG(); /* FIXME, needs locking */ 1336 mutex_lock(&dev_root->fs_info->volume_mutex);
1312
1313 dev_root = dev_root->fs_info->dev_root; 1337 dev_root = dev_root->fs_info->dev_root;
1314 1338
1315 /* step one make some room on all the devices */ 1339 /* step one make some room on all the devices */
@@ -1355,13 +1379,14 @@ int btrfs_balance(struct btrfs_root *dev_root)
1355 1379
1356 ret = btrfs_previous_item(chunk_root, path, 0, 1380 ret = btrfs_previous_item(chunk_root, path, 0,
1357 BTRFS_CHUNK_ITEM_KEY); 1381 BTRFS_CHUNK_ITEM_KEY);
1358 if (ret) { 1382 if (ret)
1359 break; 1383 break;
1360 } 1384
1361 btrfs_item_key_to_cpu(path->nodes[0], &found_key, 1385 btrfs_item_key_to_cpu(path->nodes[0], &found_key,
1362 path->slots[0]); 1386 path->slots[0]);
1363 if (found_key.objectid != key.objectid) 1387 if (found_key.objectid != key.objectid)
1364 break; 1388 break;
1389
1365 chunk = btrfs_item_ptr(path->nodes[0], 1390 chunk = btrfs_item_ptr(path->nodes[0],
1366 path->slots[0], 1391 path->slots[0],
1367 struct btrfs_chunk); 1392 struct btrfs_chunk);
@@ -1370,16 +1395,17 @@ int btrfs_balance(struct btrfs_root *dev_root)
1370 if (key.offset == 0) 1395 if (key.offset == 0)
1371 break; 1396 break;
1372 1397
1398 btrfs_release_path(chunk_root, path);
1373 ret = btrfs_relocate_chunk(chunk_root, 1399 ret = btrfs_relocate_chunk(chunk_root,
1374 chunk_root->root_key.objectid, 1400 chunk_root->root_key.objectid,
1375 found_key.objectid, 1401 found_key.objectid,
1376 found_key.offset); 1402 found_key.offset);
1377 BUG_ON(ret); 1403 BUG_ON(ret);
1378 btrfs_release_path(chunk_root, path);
1379 } 1404 }
1380 ret = 0; 1405 ret = 0;
1381error: 1406error:
1382 btrfs_free_path(path); 1407 btrfs_free_path(path);
1408 mutex_unlock(&dev_root->fs_info->volume_mutex);
1383 return ret; 1409 return ret;
1384} 1410}
1385 1411
@@ -1419,14 +1445,18 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
1419 1445
1420 path->reada = 2; 1446 path->reada = 2;
1421 1447
1448 lock_chunks(root);
1449
1422 device->total_bytes = new_size; 1450 device->total_bytes = new_size;
1423 ret = btrfs_update_device(trans, device); 1451 ret = btrfs_update_device(trans, device);
1424 if (ret) { 1452 if (ret) {
1453 unlock_chunks(root);
1425 btrfs_end_transaction(trans, root); 1454 btrfs_end_transaction(trans, root);
1426 goto done; 1455 goto done;
1427 } 1456 }
1428 WARN_ON(diff > old_total); 1457 WARN_ON(diff > old_total);
1429 btrfs_set_super_total_bytes(super_copy, old_total - diff); 1458 btrfs_set_super_total_bytes(super_copy, old_total - diff);
1459 unlock_chunks(root);
1430 btrfs_end_transaction(trans, root); 1460 btrfs_end_transaction(trans, root);
1431 1461
1432 key.objectid = device->devid; 1462 key.objectid = device->devid;