diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 121 |
1 files changed, 44 insertions, 77 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 02fae7f7e42c..ed504607d8ec 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1089,7 +1089,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
1089 | btrfs_set_node_ptr_generation(parent, parent_slot, | 1089 | btrfs_set_node_ptr_generation(parent, parent_slot, |
1090 | trans->transid); | 1090 | trans->transid); |
1091 | btrfs_mark_buffer_dirty(parent); | 1091 | btrfs_mark_buffer_dirty(parent); |
1092 | tree_mod_log_free_eb(root->fs_info, buf); | 1092 | if (last_ref) |
1093 | tree_mod_log_free_eb(root->fs_info, buf); | ||
1093 | btrfs_free_tree_block(trans, root, buf, parent_start, | 1094 | btrfs_free_tree_block(trans, root, buf, parent_start, |
1094 | last_ref); | 1095 | last_ref); |
1095 | } | 1096 | } |
@@ -1161,8 +1162,8 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, | |||
1161 | * time_seq). | 1162 | * time_seq). |
1162 | */ | 1163 | */ |
1163 | static void | 1164 | static void |
1164 | __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq, | 1165 | __tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, |
1165 | struct tree_mod_elem *first_tm) | 1166 | u64 time_seq, struct tree_mod_elem *first_tm) |
1166 | { | 1167 | { |
1167 | u32 n; | 1168 | u32 n; |
1168 | struct rb_node *next; | 1169 | struct rb_node *next; |
@@ -1172,6 +1173,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq, | |||
1172 | unsigned long p_size = sizeof(struct btrfs_key_ptr); | 1173 | unsigned long p_size = sizeof(struct btrfs_key_ptr); |
1173 | 1174 | ||
1174 | n = btrfs_header_nritems(eb); | 1175 | n = btrfs_header_nritems(eb); |
1176 | tree_mod_log_read_lock(fs_info); | ||
1175 | while (tm && tm->seq >= time_seq) { | 1177 | while (tm && tm->seq >= time_seq) { |
1176 | /* | 1178 | /* |
1177 | * all the operations are recorded with the operator used for | 1179 | * all the operations are recorded with the operator used for |
@@ -1226,6 +1228,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq, | |||
1226 | if (tm->index != first_tm->index) | 1228 | if (tm->index != first_tm->index) |
1227 | break; | 1229 | break; |
1228 | } | 1230 | } |
1231 | tree_mod_log_read_unlock(fs_info); | ||
1229 | btrfs_set_header_nritems(eb, n); | 1232 | btrfs_set_header_nritems(eb, n); |
1230 | } | 1233 | } |
1231 | 1234 | ||
@@ -1268,13 +1271,12 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
1268 | BUG_ON(!eb_rewin); | 1271 | BUG_ON(!eb_rewin); |
1269 | } | 1272 | } |
1270 | 1273 | ||
1271 | extent_buffer_get(eb_rewin); | ||
1272 | btrfs_tree_read_unlock(eb); | 1274 | btrfs_tree_read_unlock(eb); |
1273 | free_extent_buffer(eb); | 1275 | free_extent_buffer(eb); |
1274 | 1276 | ||
1275 | extent_buffer_get(eb_rewin); | 1277 | extent_buffer_get(eb_rewin); |
1276 | btrfs_tree_read_lock(eb_rewin); | 1278 | btrfs_tree_read_lock(eb_rewin); |
1277 | __tree_mod_log_rewind(eb_rewin, time_seq, tm); | 1279 | __tree_mod_log_rewind(fs_info, eb_rewin, time_seq, tm); |
1278 | WARN_ON(btrfs_header_nritems(eb_rewin) > | 1280 | WARN_ON(btrfs_header_nritems(eb_rewin) > |
1279 | BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root)); | 1281 | BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root)); |
1280 | 1282 | ||
@@ -1350,7 +1352,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
1350 | btrfs_set_header_generation(eb, old_generation); | 1352 | btrfs_set_header_generation(eb, old_generation); |
1351 | } | 1353 | } |
1352 | if (tm) | 1354 | if (tm) |
1353 | __tree_mod_log_rewind(eb, time_seq, tm); | 1355 | __tree_mod_log_rewind(root->fs_info, eb, time_seq, tm); |
1354 | else | 1356 | else |
1355 | WARN_ON(btrfs_header_level(eb) != 0); | 1357 | WARN_ON(btrfs_header_level(eb) != 0); |
1356 | WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); | 1358 | WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); |
@@ -2178,12 +2180,8 @@ static void reada_for_search(struct btrfs_root *root, | |||
2178 | } | 2180 | } |
2179 | } | 2181 | } |
2180 | 2182 | ||
2181 | /* | 2183 | static noinline void reada_for_balance(struct btrfs_root *root, |
2182 | * returns -EAGAIN if it had to drop the path, or zero if everything was in | 2184 | struct btrfs_path *path, int level) |
2183 | * cache | ||
2184 | */ | ||
2185 | static noinline int reada_for_balance(struct btrfs_root *root, | ||
2186 | struct btrfs_path *path, int level) | ||
2187 | { | 2185 | { |
2188 | int slot; | 2186 | int slot; |
2189 | int nritems; | 2187 | int nritems; |
@@ -2192,12 +2190,11 @@ static noinline int reada_for_balance(struct btrfs_root *root, | |||
2192 | u64 gen; | 2190 | u64 gen; |
2193 | u64 block1 = 0; | 2191 | u64 block1 = 0; |
2194 | u64 block2 = 0; | 2192 | u64 block2 = 0; |
2195 | int ret = 0; | ||
2196 | int blocksize; | 2193 | int blocksize; |
2197 | 2194 | ||
2198 | parent = path->nodes[level + 1]; | 2195 | parent = path->nodes[level + 1]; |
2199 | if (!parent) | 2196 | if (!parent) |
2200 | return 0; | 2197 | return; |
2201 | 2198 | ||
2202 | nritems = btrfs_header_nritems(parent); | 2199 | nritems = btrfs_header_nritems(parent); |
2203 | slot = path->slots[level + 1]; | 2200 | slot = path->slots[level + 1]; |
@@ -2224,28 +2221,11 @@ static noinline int reada_for_balance(struct btrfs_root *root, | |||
2224 | block2 = 0; | 2221 | block2 = 0; |
2225 | free_extent_buffer(eb); | 2222 | free_extent_buffer(eb); |
2226 | } | 2223 | } |
2227 | if (block1 || block2) { | ||
2228 | ret = -EAGAIN; | ||
2229 | |||
2230 | /* release the whole path */ | ||
2231 | btrfs_release_path(path); | ||
2232 | 2224 | ||
2233 | /* read the blocks */ | 2225 | if (block1) |
2234 | if (block1) | 2226 | readahead_tree_block(root, block1, blocksize, 0); |
2235 | readahead_tree_block(root, block1, blocksize, 0); | 2227 | if (block2) |
2236 | if (block2) | 2228 | readahead_tree_block(root, block2, blocksize, 0); |
2237 | readahead_tree_block(root, block2, blocksize, 0); | ||
2238 | |||
2239 | if (block1) { | ||
2240 | eb = read_tree_block(root, block1, blocksize, 0); | ||
2241 | free_extent_buffer(eb); | ||
2242 | } | ||
2243 | if (block2) { | ||
2244 | eb = read_tree_block(root, block2, blocksize, 0); | ||
2245 | free_extent_buffer(eb); | ||
2246 | } | ||
2247 | } | ||
2248 | return ret; | ||
2249 | } | 2229 | } |
2250 | 2230 | ||
2251 | 2231 | ||
@@ -2359,35 +2339,28 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
2359 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); | 2339 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); |
2360 | if (tmp) { | 2340 | if (tmp) { |
2361 | /* first we do an atomic uptodate check */ | 2341 | /* first we do an atomic uptodate check */ |
2362 | if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) { | 2342 | if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) { |
2363 | if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) { | 2343 | *eb_ret = tmp; |
2364 | /* | 2344 | return 0; |
2365 | * we found an up to date block without | 2345 | } |
2366 | * sleeping, return | ||
2367 | * right away | ||
2368 | */ | ||
2369 | *eb_ret = tmp; | ||
2370 | return 0; | ||
2371 | } | ||
2372 | /* the pages were up to date, but we failed | ||
2373 | * the generation number check. Do a full | ||
2374 | * read for the generation number that is correct. | ||
2375 | * We must do this without dropping locks so | ||
2376 | * we can trust our generation number | ||
2377 | */ | ||
2378 | free_extent_buffer(tmp); | ||
2379 | btrfs_set_path_blocking(p); | ||
2380 | 2346 | ||
2381 | /* now we're allowed to do a blocking uptodate check */ | 2347 | /* the pages were up to date, but we failed |
2382 | tmp = read_tree_block(root, blocknr, blocksize, gen); | 2348 | * the generation number check. Do a full |
2383 | if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) { | 2349 | * read for the generation number that is correct. |
2384 | *eb_ret = tmp; | 2350 | * We must do this without dropping locks so |
2385 | return 0; | 2351 | * we can trust our generation number |
2386 | } | 2352 | */ |
2387 | free_extent_buffer(tmp); | 2353 | btrfs_set_path_blocking(p); |
2388 | btrfs_release_path(p); | 2354 | |
2389 | return -EIO; | 2355 | /* now we're allowed to do a blocking uptodate check */ |
2356 | ret = btrfs_read_buffer(tmp, gen); | ||
2357 | if (!ret) { | ||
2358 | *eb_ret = tmp; | ||
2359 | return 0; | ||
2390 | } | 2360 | } |
2361 | free_extent_buffer(tmp); | ||
2362 | btrfs_release_path(p); | ||
2363 | return -EIO; | ||
2391 | } | 2364 | } |
2392 | 2365 | ||
2393 | /* | 2366 | /* |
@@ -2448,11 +2421,8 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, | |||
2448 | goto again; | 2421 | goto again; |
2449 | } | 2422 | } |
2450 | 2423 | ||
2451 | sret = reada_for_balance(root, p, level); | ||
2452 | if (sret) | ||
2453 | goto again; | ||
2454 | |||
2455 | btrfs_set_path_blocking(p); | 2424 | btrfs_set_path_blocking(p); |
2425 | reada_for_balance(root, p, level); | ||
2456 | sret = split_node(trans, root, p, level); | 2426 | sret = split_node(trans, root, p, level); |
2457 | btrfs_clear_path_blocking(p, NULL, 0); | 2427 | btrfs_clear_path_blocking(p, NULL, 0); |
2458 | 2428 | ||
@@ -2472,11 +2442,8 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, | |||
2472 | goto again; | 2442 | goto again; |
2473 | } | 2443 | } |
2474 | 2444 | ||
2475 | sret = reada_for_balance(root, p, level); | ||
2476 | if (sret) | ||
2477 | goto again; | ||
2478 | |||
2479 | btrfs_set_path_blocking(p); | 2445 | btrfs_set_path_blocking(p); |
2446 | reada_for_balance(root, p, level); | ||
2480 | sret = balance_level(trans, root, p, level); | 2447 | sret = balance_level(trans, root, p, level); |
2481 | btrfs_clear_path_blocking(p, NULL, 0); | 2448 | btrfs_clear_path_blocking(p, NULL, 0); |
2482 | 2449 | ||
@@ -3143,7 +3110,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans, | |||
3143 | */ | 3110 | */ |
3144 | static noinline int insert_new_root(struct btrfs_trans_handle *trans, | 3111 | static noinline int insert_new_root(struct btrfs_trans_handle *trans, |
3145 | struct btrfs_root *root, | 3112 | struct btrfs_root *root, |
3146 | struct btrfs_path *path, int level, int log_removal) | 3113 | struct btrfs_path *path, int level) |
3147 | { | 3114 | { |
3148 | u64 lower_gen; | 3115 | u64 lower_gen; |
3149 | struct extent_buffer *lower; | 3116 | struct extent_buffer *lower; |
@@ -3194,7 +3161,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, | |||
3194 | btrfs_mark_buffer_dirty(c); | 3161 | btrfs_mark_buffer_dirty(c); |
3195 | 3162 | ||
3196 | old = root->node; | 3163 | old = root->node; |
3197 | tree_mod_log_set_root_pointer(root, c, log_removal); | 3164 | tree_mod_log_set_root_pointer(root, c, 0); |
3198 | rcu_assign_pointer(root->node, c); | 3165 | rcu_assign_pointer(root->node, c); |
3199 | 3166 | ||
3200 | /* the super has an extra ref to root->node */ | 3167 | /* the super has an extra ref to root->node */ |
@@ -3278,14 +3245,14 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
3278 | /* | 3245 | /* |
3279 | * trying to split the root, lets make a new one | 3246 | * trying to split the root, lets make a new one |
3280 | * | 3247 | * |
3281 | * tree mod log: We pass 0 as log_removal parameter to | 3248 | * tree mod log: We don't log_removal old root in |
3282 | * insert_new_root, because that root buffer will be kept as a | 3249 | * insert_new_root, because that root buffer will be kept as a |
3283 | * normal node. We are going to log removal of half of the | 3250 | * normal node. We are going to log removal of half of the |
3284 | * elements below with tree_mod_log_eb_copy. We're holding a | 3251 | * elements below with tree_mod_log_eb_copy. We're holding a |
3285 | * tree lock on the buffer, which is why we cannot race with | 3252 | * tree lock on the buffer, which is why we cannot race with |
3286 | * other tree_mod_log users. | 3253 | * other tree_mod_log users. |
3287 | */ | 3254 | */ |
3288 | ret = insert_new_root(trans, root, path, level + 1, 0); | 3255 | ret = insert_new_root(trans, root, path, level + 1); |
3289 | if (ret) | 3256 | if (ret) |
3290 | return ret; | 3257 | return ret; |
3291 | } else { | 3258 | } else { |
@@ -3986,7 +3953,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
3986 | return -EOVERFLOW; | 3953 | return -EOVERFLOW; |
3987 | 3954 | ||
3988 | /* first try to make some room by pushing left and right */ | 3955 | /* first try to make some room by pushing left and right */ |
3989 | if (data_size) { | 3956 | if (data_size && path->nodes[1]) { |
3990 | wret = push_leaf_right(trans, root, path, data_size, | 3957 | wret = push_leaf_right(trans, root, path, data_size, |
3991 | data_size, 0, 0); | 3958 | data_size, 0, 0); |
3992 | if (wret < 0) | 3959 | if (wret < 0) |
@@ -4005,7 +3972,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
4005 | } | 3972 | } |
4006 | 3973 | ||
4007 | if (!path->nodes[1]) { | 3974 | if (!path->nodes[1]) { |
4008 | ret = insert_new_root(trans, root, path, 1, 1); | 3975 | ret = insert_new_root(trans, root, path, 1); |
4009 | if (ret) | 3976 | if (ret) |
4010 | return ret; | 3977 | return ret; |
4011 | } | 3978 | } |
@@ -4430,7 +4397,7 @@ void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path, | |||
4430 | } | 4397 | } |
4431 | 4398 | ||
4432 | /* | 4399 | /* |
4433 | * make the item pointed to by the path bigger, data_size is the new size. | 4400 | * make the item pointed to by the path bigger, data_size is the added size. |
4434 | */ | 4401 | */ |
4435 | void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, | 4402 | void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, |
4436 | u32 data_size) | 4403 | u32 data_size) |