diff options
| author | Chris Mason <chris.mason@oracle.com> | 2008-07-08 14:19:17 -0400 |
|---|---|---|
| committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:04 -0400 |
| commit | 7d9eb12c8739e7dc80c78c6b3596f912ecd8f941 (patch) | |
| tree | 000608285b44920f22e0888753b36299bc762cef | |
| parent | a7a16fd772620605c76e8ac8bdbc8ccc9e3df1a0 (diff) | |
Btrfs: Add locking around volume management (device add/remove/balance)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
| -rw-r--r-- | fs/btrfs/ctree.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 73 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 58 |
6 files changed, 103 insertions, 40 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index c6759fc1004a..bbf9bf374066 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -1251,10 +1251,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1251 | WARN_ON(p->nodes[0] != NULL); | 1251 | WARN_ON(p->nodes[0] != NULL); |
| 1252 | WARN_ON(cow && root == root->fs_info->extent_root && | 1252 | WARN_ON(cow && root == root->fs_info->extent_root && |
| 1253 | !mutex_is_locked(&root->fs_info->alloc_mutex)); | 1253 | !mutex_is_locked(&root->fs_info->alloc_mutex)); |
| 1254 | WARN_ON(root == root->fs_info->chunk_root && | ||
| 1255 | !mutex_is_locked(&root->fs_info->chunk_mutex)); | ||
| 1256 | WARN_ON(root == root->fs_info->dev_root && | ||
| 1257 | !mutex_is_locked(&root->fs_info->chunk_mutex)); | ||
| 1258 | if (ins_len < 0) | 1254 | if (ins_len < 0) |
| 1259 | lowest_unlock = 2; | 1255 | lowest_unlock = 2; |
| 1260 | again: | 1256 | again: |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index a28796482b4a..f3783dbd9b60 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -523,6 +523,7 @@ struct btrfs_fs_info { | |||
| 523 | struct mutex alloc_mutex; | 523 | struct mutex alloc_mutex; |
| 524 | struct mutex chunk_mutex; | 524 | struct mutex chunk_mutex; |
| 525 | struct mutex drop_mutex; | 525 | struct mutex drop_mutex; |
| 526 | struct mutex volume_mutex; | ||
| 526 | struct list_head trans_list; | 527 | struct list_head trans_list; |
| 527 | struct list_head hashers; | 528 | struct list_head hashers; |
| 528 | struct list_head dead_roots; | 529 | struct list_head dead_roots; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 4cdc0b6a2672..8f4c40033e92 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -1287,6 +1287,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1287 | mutex_init(&fs_info->chunk_mutex); | 1287 | mutex_init(&fs_info->chunk_mutex); |
| 1288 | mutex_init(&fs_info->transaction_kthread_mutex); | 1288 | mutex_init(&fs_info->transaction_kthread_mutex); |
| 1289 | mutex_init(&fs_info->cleaner_mutex); | 1289 | mutex_init(&fs_info->cleaner_mutex); |
| 1290 | mutex_init(&fs_info->volume_mutex); | ||
| 1290 | 1291 | ||
| 1291 | #if 0 | 1292 | #if 0 |
| 1292 | ret = add_hasher(fs_info, "crc32c"); | 1293 | ret = add_hasher(fs_info, "crc32c"); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 5e0857ffbc35..8ebfa6be0790 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -245,6 +245,7 @@ static int noinline find_search_start(struct btrfs_root *root, | |||
| 245 | u64 search_start = *start_ret; | 245 | u64 search_start = *start_ret; |
| 246 | int wrapped = 0; | 246 | int wrapped = 0; |
| 247 | 247 | ||
| 248 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | ||
| 248 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | 249 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); |
| 249 | free_space_cache = &root->fs_info->free_space_cache; | 250 | free_space_cache = &root->fs_info->free_space_cache; |
| 250 | 251 | ||
| @@ -1242,6 +1243,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
| 1242 | u64 start; | 1243 | u64 start; |
| 1243 | u64 end; | 1244 | u64 end; |
| 1244 | 1245 | ||
| 1246 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | ||
| 1245 | while(total) { | 1247 | while(total) { |
| 1246 | cache = btrfs_lookup_block_group(info, bytenr); | 1248 | cache = btrfs_lookup_block_group(info, bytenr); |
| 1247 | if (!cache) { | 1249 | if (!cache) { |
| @@ -1297,6 +1299,7 @@ static int update_pinned_extents(struct btrfs_root *root, | |||
| 1297 | struct btrfs_block_group_cache *cache; | 1299 | struct btrfs_block_group_cache *cache; |
| 1298 | struct btrfs_fs_info *fs_info = root->fs_info; | 1300 | struct btrfs_fs_info *fs_info = root->fs_info; |
| 1299 | 1301 | ||
| 1302 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | ||
| 1300 | if (pin) { | 1303 | if (pin) { |
| 1301 | set_extent_dirty(&fs_info->pinned_extents, | 1304 | set_extent_dirty(&fs_info->pinned_extents, |
| 1302 | bytenr, bytenr + num - 1, GFP_NOFS); | 1305 | bytenr, bytenr + num - 1, GFP_NOFS); |
| @@ -1391,6 +1394,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, | |||
| 1391 | int level; | 1394 | int level; |
| 1392 | int err = 0; | 1395 | int err = 0; |
| 1393 | 1396 | ||
| 1397 | WARN_ON(!mutex_is_locked(&extent_root->fs_info->alloc_mutex)); | ||
| 1394 | btrfs_set_stack_extent_refs(&extent_item, 1); | 1398 | btrfs_set_stack_extent_refs(&extent_item, 1); |
| 1395 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 1399 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
| 1396 | path = btrfs_alloc_path(); | 1400 | path = btrfs_alloc_path(); |
| @@ -1437,6 +1441,7 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, | |||
| 1437 | { | 1441 | { |
| 1438 | int err = 0; | 1442 | int err = 0; |
| 1439 | 1443 | ||
| 1444 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | ||
| 1440 | if (!pending) { | 1445 | if (!pending) { |
| 1441 | struct extent_buffer *buf; | 1446 | struct extent_buffer *buf; |
| 1442 | buf = btrfs_find_tree_block(root, bytenr, num_bytes); | 1447 | buf = btrfs_find_tree_block(root, bytenr, num_bytes); |
| @@ -1490,6 +1495,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1490 | struct btrfs_extent_item *ei; | 1495 | struct btrfs_extent_item *ei; |
| 1491 | u32 refs; | 1496 | u32 refs; |
| 1492 | 1497 | ||
| 1498 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | ||
| 1493 | key.objectid = bytenr; | 1499 | key.objectid = bytenr; |
| 1494 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 1500 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| 1495 | key.offset = num_bytes; | 1501 | key.offset = num_bytes; |
| @@ -1619,6 +1625,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
| 1619 | struct extent_io_tree *pending_del; | 1625 | struct extent_io_tree *pending_del; |
| 1620 | struct extent_io_tree *pinned_extents; | 1626 | struct extent_io_tree *pinned_extents; |
| 1621 | 1627 | ||
| 1628 | WARN_ON(!mutex_is_locked(&extent_root->fs_info->alloc_mutex)); | ||
| 1622 | pending_del = &extent_root->fs_info->pending_del; | 1629 | pending_del = &extent_root->fs_info->pending_del; |
| 1623 | pinned_extents = &extent_root->fs_info->pinned_extents; | 1630 | pinned_extents = &extent_root->fs_info->pinned_extents; |
| 1624 | 1631 | ||
| @@ -2428,6 +2435,10 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 2428 | btrfs_node_key(node, &found_key, path->slots[level]); | 2435 | btrfs_node_key(node, &found_key, path->slots[level]); |
| 2429 | WARN_ON(memcmp(&found_key, &root_item->drop_progress, | 2436 | WARN_ON(memcmp(&found_key, &root_item->drop_progress, |
| 2430 | sizeof(found_key))); | 2437 | sizeof(found_key))); |
| 2438 | /* | ||
| 2439 | * unlock our path, this is safe because only this | ||
| 2440 | * function is allowed to delete this snapshot | ||
| 2441 | */ | ||
| 2431 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { | 2442 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { |
| 2432 | if (path->nodes[i] && path->locks[i]) { | 2443 | if (path->nodes[i] && path->locks[i]) { |
| 2433 | path->locks[i] = 0; | 2444 | path->locks[i] = 0; |
| @@ -2611,7 +2622,6 @@ static int find_root_for_ref(struct btrfs_root *root, | |||
| 2611 | u64 root_search_start = BTRFS_FS_TREE_OBJECTID; | 2622 | u64 root_search_start = BTRFS_FS_TREE_OBJECTID; |
| 2612 | u64 found_bytenr; | 2623 | u64 found_bytenr; |
| 2613 | int ret; | 2624 | int ret; |
| 2614 | int i; | ||
| 2615 | 2625 | ||
| 2616 | root_location.offset = (u64)-1; | 2626 | root_location.offset = (u64)-1; |
| 2617 | root_location.type = BTRFS_ROOT_ITEM_KEY; | 2627 | root_location.type = BTRFS_ROOT_ITEM_KEY; |
| @@ -2635,12 +2645,6 @@ static int find_root_for_ref(struct btrfs_root *root, | |||
| 2635 | found_bytenr = path->nodes[level]->start; | 2645 | found_bytenr = path->nodes[level]->start; |
| 2636 | } | 2646 | } |
| 2637 | 2647 | ||
| 2638 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { | ||
| 2639 | if (!path->nodes[i]) | ||
| 2640 | break; | ||
| 2641 | free_extent_buffer(path->nodes[i]); | ||
| 2642 | path->nodes[i] = NULL; | ||
| 2643 | } | ||
| 2644 | btrfs_release_path(cur_root, path); | 2648 | btrfs_release_path(cur_root, path); |
| 2645 | 2649 | ||
| 2646 | if (found_bytenr == bytenr) { | 2650 | if (found_bytenr == bytenr) { |
| @@ -2689,6 +2693,8 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
| 2689 | int ret; | 2693 | int ret; |
| 2690 | int level; | 2694 | int level; |
| 2691 | 2695 | ||
| 2696 | WARN_ON(!mutex_is_locked(&extent_root->fs_info->alloc_mutex)); | ||
| 2697 | |||
| 2692 | ref = btrfs_item_ptr(path->nodes[0], path->slots[0], | 2698 | ref = btrfs_item_ptr(path->nodes[0], path->slots[0], |
| 2693 | struct btrfs_extent_ref); | 2699 | struct btrfs_extent_ref); |
| 2694 | ref_root = btrfs_ref_root(path->nodes[0], ref); | 2700 | ref_root = btrfs_ref_root(path->nodes[0], ref); |
| @@ -2707,6 +2713,7 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
| 2707 | found_root = btrfs_read_fs_root_no_name(extent_root->fs_info, | 2713 | found_root = btrfs_read_fs_root_no_name(extent_root->fs_info, |
| 2708 | &root_location); | 2714 | &root_location); |
| 2709 | BUG_ON(!found_root); | 2715 | BUG_ON(!found_root); |
| 2716 | mutex_unlock(&extent_root->fs_info->alloc_mutex); | ||
| 2710 | 2717 | ||
| 2711 | if (ref_objectid >= BTRFS_FIRST_FREE_OBJECTID) { | 2718 | if (ref_objectid >= BTRFS_FIRST_FREE_OBJECTID) { |
| 2712 | found_key.objectid = ref_objectid; | 2719 | found_key.objectid = ref_objectid; |
| @@ -2748,9 +2755,9 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
| 2748 | /* this can happen if the reference is not against | 2755 | /* this can happen if the reference is not against |
| 2749 | * the latest version of the tree root | 2756 | * the latest version of the tree root |
| 2750 | */ | 2757 | */ |
| 2751 | if (is_bad_inode(inode)) { | 2758 | if (is_bad_inode(inode)) |
| 2752 | goto out; | 2759 | goto out; |
| 2753 | } | 2760 | |
| 2754 | *last_file_objectid = inode->i_ino; | 2761 | *last_file_objectid = inode->i_ino; |
| 2755 | *last_file_root = found_root->root_key.objectid; | 2762 | *last_file_root = found_root->root_key.objectid; |
| 2756 | *last_file_offset = ref_offset; | 2763 | *last_file_offset = ref_offset; |
| @@ -2760,7 +2767,7 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
| 2760 | } else { | 2767 | } else { |
| 2761 | struct btrfs_trans_handle *trans; | 2768 | struct btrfs_trans_handle *trans; |
| 2762 | struct extent_buffer *eb; | 2769 | struct extent_buffer *eb; |
| 2763 | int i; | 2770 | int needs_lock = 0; |
| 2764 | 2771 | ||
| 2765 | eb = read_tree_block(found_root, extent_key->objectid, | 2772 | eb = read_tree_block(found_root, extent_key->objectid, |
| 2766 | extent_key->offset, 0); | 2773 | extent_key->offset, 0); |
| @@ -2782,26 +2789,40 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
| 2782 | if (ret) | 2789 | if (ret) |
| 2783 | goto out; | 2790 | goto out; |
| 2784 | 2791 | ||
| 2792 | /* | ||
| 2793 | * right here almost anything could happen to our key, | ||
| 2794 | * but that's ok. The cow below will either relocate it | ||
| 2795 | * or someone else will have relocated it. Either way, | ||
| 2796 | * it is in a different spot than it was before and | ||
| 2797 | * we're happy. | ||
| 2798 | */ | ||
| 2799 | |||
| 2785 | trans = btrfs_start_transaction(found_root, 1); | 2800 | trans = btrfs_start_transaction(found_root, 1); |
| 2786 | 2801 | ||
| 2802 | if (found_root == extent_root->fs_info->extent_root || | ||
| 2803 | found_root == extent_root->fs_info->chunk_root || | ||
| 2804 | found_root == extent_root->fs_info->dev_root) { | ||
| 2805 | needs_lock = 1; | ||
| 2806 | mutex_lock(&extent_root->fs_info->alloc_mutex); | ||
| 2807 | } | ||
| 2808 | |||
| 2787 | path->lowest_level = level; | 2809 | path->lowest_level = level; |
| 2788 | path->reada = 2; | 2810 | path->reada = 2; |
| 2789 | ret = btrfs_search_slot(trans, found_root, &found_key, path, | 2811 | ret = btrfs_search_slot(trans, found_root, &found_key, path, |
| 2790 | 0, 1); | 2812 | 0, 1); |
| 2791 | path->lowest_level = 0; | 2813 | path->lowest_level = 0; |
| 2792 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { | ||
| 2793 | if (!path->nodes[i]) | ||
| 2794 | break; | ||
| 2795 | free_extent_buffer(path->nodes[i]); | ||
| 2796 | path->nodes[i] = NULL; | ||
| 2797 | } | ||
| 2798 | btrfs_release_path(found_root, path); | 2814 | btrfs_release_path(found_root, path); |
| 2815 | |||
| 2799 | if (found_root == found_root->fs_info->extent_root) | 2816 | if (found_root == found_root->fs_info->extent_root) |
| 2800 | btrfs_extent_post_op(trans, found_root); | 2817 | btrfs_extent_post_op(trans, found_root); |
| 2818 | if (needs_lock) | ||
| 2819 | mutex_unlock(&extent_root->fs_info->alloc_mutex); | ||
| 2820 | |||
| 2801 | btrfs_end_transaction(trans, found_root); | 2821 | btrfs_end_transaction(trans, found_root); |
| 2802 | } | ||
| 2803 | 2822 | ||
| 2823 | } | ||
| 2804 | out: | 2824 | out: |
| 2825 | mutex_lock(&extent_root->fs_info->alloc_mutex); | ||
| 2805 | return 0; | 2826 | return 0; |
| 2806 | } | 2827 | } |
| 2807 | 2828 | ||
| @@ -2943,7 +2964,10 @@ int __alloc_chunk_for_shrink(struct btrfs_root *root, | |||
| 2943 | 2964 | ||
| 2944 | if (btrfs_block_group_used(&shrink_block_group->item) > 0) { | 2965 | if (btrfs_block_group_used(&shrink_block_group->item) > 0) { |
| 2945 | 2966 | ||
| 2967 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
| 2946 | trans = btrfs_start_transaction(root, 1); | 2968 | trans = btrfs_start_transaction(root, 1); |
| 2969 | mutex_lock(&root->fs_info->alloc_mutex); | ||
| 2970 | |||
| 2947 | new_alloc_flags = update_block_group_flags(root, | 2971 | new_alloc_flags = update_block_group_flags(root, |
| 2948 | shrink_block_group->flags); | 2972 | shrink_block_group->flags); |
| 2949 | if (new_alloc_flags != shrink_block_group->flags) { | 2973 | if (new_alloc_flags != shrink_block_group->flags) { |
| @@ -2954,7 +2978,10 @@ int __alloc_chunk_for_shrink(struct btrfs_root *root, | |||
| 2954 | } | 2978 | } |
| 2955 | do_chunk_alloc(trans, root->fs_info->extent_root, | 2979 | do_chunk_alloc(trans, root->fs_info->extent_root, |
| 2956 | calc + 2 * 1024 * 1024, new_alloc_flags, force); | 2980 | calc + 2 * 1024 * 1024, new_alloc_flags, force); |
| 2981 | |||
| 2982 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
| 2957 | btrfs_end_transaction(trans, root); | 2983 | btrfs_end_transaction(trans, root); |
| 2984 | mutex_lock(&root->fs_info->alloc_mutex); | ||
| 2958 | } | 2985 | } |
| 2959 | return 0; | 2986 | return 0; |
| 2960 | } | 2987 | } |
| @@ -3031,9 +3058,9 @@ again: | |||
| 3031 | if (ret < 0) | 3058 | if (ret < 0) |
| 3032 | goto out; | 3059 | goto out; |
| 3033 | 3060 | ||
| 3061 | next: | ||
| 3034 | leaf = path->nodes[0]; | 3062 | leaf = path->nodes[0]; |
| 3035 | nritems = btrfs_header_nritems(leaf); | 3063 | nritems = btrfs_header_nritems(leaf); |
| 3036 | next: | ||
| 3037 | if (path->slots[0] >= nritems) { | 3064 | if (path->slots[0] >= nritems) { |
| 3038 | ret = btrfs_next_leaf(root, path); | 3065 | ret = btrfs_next_leaf(root, path); |
| 3039 | if (ret < 0) | 3066 | if (ret < 0) |
| @@ -3083,6 +3110,7 @@ next: | |||
| 3083 | printk("btrfs relocate found %llu last extent was %llu\n", | 3110 | printk("btrfs relocate found %llu last extent was %llu\n", |
| 3084 | (unsigned long long)total_found, | 3111 | (unsigned long long)total_found, |
| 3085 | (unsigned long long)found_key.objectid); | 3112 | (unsigned long long)found_key.objectid); |
| 3113 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
| 3086 | trans = btrfs_start_transaction(tree_root, 1); | 3114 | trans = btrfs_start_transaction(tree_root, 1); |
| 3087 | btrfs_commit_transaction(trans, tree_root); | 3115 | btrfs_commit_transaction(trans, tree_root); |
| 3088 | 3116 | ||
| @@ -3090,6 +3118,7 @@ next: | |||
| 3090 | 3118 | ||
| 3091 | trans = btrfs_start_transaction(tree_root, 1); | 3119 | trans = btrfs_start_transaction(tree_root, 1); |
| 3092 | btrfs_commit_transaction(trans, tree_root); | 3120 | btrfs_commit_transaction(trans, tree_root); |
| 3121 | mutex_lock(&root->fs_info->alloc_mutex); | ||
| 3093 | goto again; | 3122 | goto again; |
| 3094 | } | 3123 | } |
| 3095 | 3124 | ||
| @@ -3097,7 +3126,10 @@ next: | |||
| 3097 | * we've freed all the extents, now remove the block | 3126 | * we've freed all the extents, now remove the block |
| 3098 | * group item from the tree | 3127 | * group item from the tree |
| 3099 | */ | 3128 | */ |
| 3129 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
| 3130 | |||
| 3100 | trans = btrfs_start_transaction(root, 1); | 3131 | trans = btrfs_start_transaction(root, 1); |
| 3132 | mutex_lock(&root->fs_info->alloc_mutex); | ||
| 3101 | memcpy(&key, &shrink_block_group->key, sizeof(key)); | 3133 | memcpy(&key, &shrink_block_group->key, sizeof(key)); |
| 3102 | 3134 | ||
| 3103 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 3135 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
| @@ -3119,8 +3151,12 @@ next: | |||
| 3119 | kfree(shrink_block_group); | 3151 | kfree(shrink_block_group); |
| 3120 | 3152 | ||
| 3121 | btrfs_del_item(trans, root, path); | 3153 | btrfs_del_item(trans, root, path); |
| 3154 | btrfs_release_path(root, path); | ||
| 3155 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
| 3122 | btrfs_commit_transaction(trans, root); | 3156 | btrfs_commit_transaction(trans, root); |
| 3123 | 3157 | ||
| 3158 | mutex_lock(&root->fs_info->alloc_mutex); | ||
| 3159 | |||
| 3124 | /* the code to unpin extents might set a few bits in the free | 3160 | /* the code to unpin extents might set a few bits in the free |
| 3125 | * space cache for this range again | 3161 | * space cache for this range again |
| 3126 | */ | 3162 | */ |
| @@ -3263,6 +3299,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, | |||
| 3263 | struct btrfs_block_group_cache *cache; | 3299 | struct btrfs_block_group_cache *cache; |
| 3264 | struct extent_io_tree *block_group_cache; | 3300 | struct extent_io_tree *block_group_cache; |
| 3265 | 3301 | ||
| 3302 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | ||
| 3266 | extent_root = root->fs_info->extent_root; | 3303 | extent_root = root->fs_info->extent_root; |
| 3267 | block_group_cache = &root->fs_info->block_group_cache; | 3304 | block_group_cache = &root->fs_info->block_group_cache; |
| 3268 | 3305 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 026039a2ac58..83f17a5cbd6a 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -307,8 +307,7 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
| 307 | goto out; | 307 | goto out; |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | mutex_lock(&root->fs_info->alloc_mutex); | 310 | mutex_lock(&root->fs_info->volume_mutex); |
| 311 | mutex_lock(&root->fs_info->chunk_mutex); | ||
| 312 | sizestr = vol_args->name; | 311 | sizestr = vol_args->name; |
| 313 | devstr = strchr(sizestr, ':'); | 312 | devstr = strchr(sizestr, ':'); |
| 314 | if (devstr) { | 313 | if (devstr) { |
| @@ -378,8 +377,7 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
| 378 | } | 377 | } |
| 379 | 378 | ||
| 380 | out_unlock: | 379 | out_unlock: |
| 381 | mutex_lock(&root->fs_info->alloc_mutex); | 380 | mutex_unlock(&root->fs_info->volume_mutex); |
| 382 | mutex_lock(&root->fs_info->chunk_mutex); | ||
| 383 | out: | 381 | out: |
| 384 | kfree(vol_args); | 382 | kfree(vol_args); |
| 385 | return ret; | 383 | return ret; |
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 | ||
| 59 | static 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 | |||
| 65 | static 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 | |||
| 59 | int btrfs_cleanup_fs_uuids(void) | 71 | int 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); |
| 857 | out: | 870 | out: |
| 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); |
| 990 | out: | 1003 | out: |
| 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++; |
| 1067 | out: | 1079 | out: |
| 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 | ||
| 1125 | int btrfs_grow_device(struct btrfs_trans_handle *trans, | 1137 | static 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 | ||
| 1149 | int 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 | |||
| 1137 | static int btrfs_free_chunk(struct btrfs_trans_handle *trans, | 1159 | static 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; |
| 1381 | error: | 1406 | error: |
| 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; |
