aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-06-25 16:01:30 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:03 -0400
commita213501153fd66e2359e091b1612841305ba6551 (patch)
tree1f4c316c9d3cad0eb6d9be14cb0e67e46e815dce /fs/btrfs/ctree.c
parent925baeddc5b0764a53f2214a1253251bab0e0324 (diff)
Btrfs: Replace the big fs_mutex with a collection of other locks
Extent alloctions are still protected by a large alloc_mutex. Objectid allocations are covered by a objectid mutex Other btree operations are protected by a lock on individual btree nodes Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 75625c68fdd8..dff4da082d06 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -63,6 +63,9 @@ void btrfs_free_path(struct btrfs_path *p)
63void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) 63void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
64{ 64{
65 int i; 65 int i;
66 int skip = p->skip_locking;
67 int keep = p->keep_locks;
68
66 for (i = 0; i < BTRFS_MAX_LEVEL; i++) { 69 for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
67 if (!p->nodes[i]) 70 if (!p->nodes[i])
68 continue; 71 continue;
@@ -73,6 +76,8 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
73 free_extent_buffer(p->nodes[i]); 76 free_extent_buffer(p->nodes[i]);
74 } 77 }
75 memset(p, 0, sizeof(*p)); 78 memset(p, 0, sizeof(*p));
79 p->skip_locking = skip;
80 p->keep_locks = keep;
76} 81}
77 82
78struct extent_buffer *btrfs_root_node(struct btrfs_root *root) 83struct extent_buffer *btrfs_root_node(struct btrfs_root *root)
@@ -1202,13 +1207,19 @@ static void unlock_up(struct btrfs_path *path, int level, int lowest_unlock)
1202 u32 nritems; 1207 u32 nritems;
1203 t = path->nodes[i]; 1208 t = path->nodes[i];
1204 nritems = btrfs_header_nritems(t); 1209 nritems = btrfs_header_nritems(t);
1205 if (path->slots[i] >= nritems - 1) { 1210 if (nritems < 2 || path->slots[i] >= nritems - 2) {
1211if (path->keep_locks) {
1212//printk("path %p skip level now %d\n", path, skip_level);
1213}
1206 skip_level = i + 1; 1214 skip_level = i + 1;
1207 continue; 1215 continue;
1208 } 1216 }
1209 } 1217 }
1210 t = path->nodes[i]; 1218 t = path->nodes[i];
1211 if (i >= lowest_unlock && i > skip_level && path->locks[i]) { 1219 if (i >= lowest_unlock && i > skip_level && path->locks[i]) {
1220if (path->keep_locks) {
1221//printk("path %p unlocking level %d slot %d nritems %d skip_level %d\n", path, i, path->slots[i], btrfs_header_nritems(t), skip_level);
1222}
1212 btrfs_tree_unlock(t); 1223 btrfs_tree_unlock(t);
1213 path->locks[i] = 0; 1224 path->locks[i] = 0;
1214 } 1225 }
@@ -1243,7 +1254,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
1243 lowest_level = p->lowest_level; 1254 lowest_level = p->lowest_level;
1244 WARN_ON(lowest_level && ins_len); 1255 WARN_ON(lowest_level && ins_len);
1245 WARN_ON(p->nodes[0] != NULL); 1256 WARN_ON(p->nodes[0] != NULL);
1246 // WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
1247 WARN_ON(root == root->fs_info->extent_root && 1257 WARN_ON(root == root->fs_info->extent_root &&
1248 !mutex_is_locked(&root->fs_info->alloc_mutex)); 1258 !mutex_is_locked(&root->fs_info->alloc_mutex));
1249 WARN_ON(root == root->fs_info->chunk_root && 1259 WARN_ON(root == root->fs_info->chunk_root &&
@@ -1321,7 +1331,7 @@ again:
1321 b = read_node_slot(root, b, slot); 1331 b = read_node_slot(root, b, slot);
1322 if (!p->skip_locking) 1332 if (!p->skip_locking)
1323 btrfs_tree_lock(b); 1333 btrfs_tree_lock(b);
1324 unlock_up(p, level, lowest_unlock); 1334 unlock_up(p, level + 1, lowest_unlock);
1325 } else { 1335 } else {
1326 p->slots[level] = slot; 1336 p->slots[level] = slot;
1327 if (ins_len > 0 && btrfs_leaf_free_space(root, b) < 1337 if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
@@ -1804,6 +1814,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1804 if (slot >= btrfs_header_nritems(upper) - 1) 1814 if (slot >= btrfs_header_nritems(upper) - 1)
1805 return 1; 1815 return 1;
1806 1816
1817 WARN_ON(!btrfs_tree_locked(path->nodes[1]));
1818
1807 right = read_node_slot(root, upper, slot + 1); 1819 right = read_node_slot(root, upper, slot + 1);
1808 btrfs_tree_lock(right); 1820 btrfs_tree_lock(right);
1809 free_space = btrfs_leaf_free_space(root, right); 1821 free_space = btrfs_leaf_free_space(root, right);
@@ -1981,6 +1993,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1981 return 1; 1993 return 1;
1982 } 1994 }
1983 1995
1996 WARN_ON(!btrfs_tree_locked(path->nodes[1]));
1997
1984 left = read_node_slot(root, path->nodes[1], slot - 1); 1998 left = read_node_slot(root, path->nodes[1], slot - 1);
1985 btrfs_tree_lock(left); 1999 btrfs_tree_lock(left);
1986 free_space = btrfs_leaf_free_space(root, left); 2000 free_space = btrfs_leaf_free_space(root, left);
@@ -2957,15 +2971,16 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
2957 2971
2958 btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1); 2972 btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);
2959 2973
2960 path->keep_locks = 1;
2961 btrfs_release_path(root, path); 2974 btrfs_release_path(root, path);
2975 path->keep_locks = 1;
2962 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 2976 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
2963 path->keep_locks = 0; 2977 path->keep_locks = 0;
2964 2978
2965 if (ret < 0) 2979 if (ret < 0)
2966 return ret; 2980 return ret;
2967 2981
2968 if (path->slots[0] < nritems - 1) { 2982 nritems = btrfs_header_nritems(path->nodes[0]);
2983 if (nritems > 0 && path->slots[0] < nritems - 1) {
2969 goto done; 2984 goto done;
2970 } 2985 }
2971 2986
@@ -2992,8 +3007,17 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
2992 reada_for_search(root, path, level, slot, 0); 3007 reada_for_search(root, path, level, slot, 0);
2993 3008
2994 next = read_node_slot(root, c, slot); 3009 next = read_node_slot(root, c, slot);
2995 if (!path->skip_locking) 3010 if (!path->skip_locking) {
3011 if (!btrfs_tree_locked(c)) {
3012 int i;
3013 WARN_ON(1);
3014printk("path %p no lock on level %d\n", path, level);
3015for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
3016printk("path %p level %d slot %d nritems %d\n", path, i, path->slots[i], btrfs_header_nritems(path->nodes[i]));
3017}
3018 }
2996 btrfs_tree_lock(next); 3019 btrfs_tree_lock(next);
3020 }
2997 break; 3021 break;
2998 } 3022 }
2999 path->slots[level] = slot; 3023 path->slots[level] = slot;
@@ -3011,8 +3035,10 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
3011 if (level == 1 && path->locks[1] && path->reada) 3035 if (level == 1 && path->locks[1] && path->reada)
3012 reada_for_search(root, path, level, slot, 0); 3036 reada_for_search(root, path, level, slot, 0);
3013 next = read_node_slot(root, next, 0); 3037 next = read_node_slot(root, next, 0);
3014 if (!path->skip_locking) 3038 if (!path->skip_locking) {
3039 WARN_ON(!btrfs_tree_locked(path->nodes[level]));
3015 btrfs_tree_lock(next); 3040 btrfs_tree_lock(next);
3041 }
3016 } 3042 }
3017done: 3043done:
3018 unlock_up(path, 0, 1); 3044 unlock_up(path, 0, 1);