diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 40 |
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) | |||
63 | void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) | 63 | void 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 | ||
78 | struct extent_buffer *btrfs_root_node(struct btrfs_root *root) | 83 | struct 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) { |
1211 | if (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]) { |
1220 | if (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); | ||
3014 | printk("path %p no lock on level %d\n", path, level); | ||
3015 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { | ||
3016 | printk("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 | } |
3017 | done: | 3043 | done: |
3018 | unlock_up(path, 0, 1); | 3044 | unlock_up(path, 0, 1); |