diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
| -rw-r--r-- | fs/btrfs/ctree.c | 120 |
1 files changed, 44 insertions, 76 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 02fae7f7e42c..5bf4c39e2ad6 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 | ||
| @@ -1274,7 +1277,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
| 1274 | 1277 | ||
| 1275 | extent_buffer_get(eb_rewin); | 1278 | extent_buffer_get(eb_rewin); |
| 1276 | btrfs_tree_read_lock(eb_rewin); | 1279 | btrfs_tree_read_lock(eb_rewin); |
| 1277 | __tree_mod_log_rewind(eb_rewin, time_seq, tm); | 1280 | __tree_mod_log_rewind(fs_info, eb_rewin, time_seq, tm); |
| 1278 | WARN_ON(btrfs_header_nritems(eb_rewin) > | 1281 | WARN_ON(btrfs_header_nritems(eb_rewin) > |
| 1279 | BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root)); | 1282 | BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root)); |
| 1280 | 1283 | ||
| @@ -1350,7 +1353,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
| 1350 | btrfs_set_header_generation(eb, old_generation); | 1353 | btrfs_set_header_generation(eb, old_generation); |
| 1351 | } | 1354 | } |
| 1352 | if (tm) | 1355 | if (tm) |
| 1353 | __tree_mod_log_rewind(eb, time_seq, tm); | 1356 | __tree_mod_log_rewind(root->fs_info, eb, time_seq, tm); |
| 1354 | else | 1357 | else |
| 1355 | WARN_ON(btrfs_header_level(eb) != 0); | 1358 | WARN_ON(btrfs_header_level(eb) != 0); |
| 1356 | WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); | 1359 | WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); |
| @@ -2178,12 +2181,8 @@ static void reada_for_search(struct btrfs_root *root, | |||
| 2178 | } | 2181 | } |
| 2179 | } | 2182 | } |
| 2180 | 2183 | ||
| 2181 | /* | 2184 | 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 | 2185 | 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 | { | 2186 | { |
| 2188 | int slot; | 2187 | int slot; |
| 2189 | int nritems; | 2188 | int nritems; |
| @@ -2192,12 +2191,11 @@ static noinline int reada_for_balance(struct btrfs_root *root, | |||
| 2192 | u64 gen; | 2191 | u64 gen; |
| 2193 | u64 block1 = 0; | 2192 | u64 block1 = 0; |
| 2194 | u64 block2 = 0; | 2193 | u64 block2 = 0; |
| 2195 | int ret = 0; | ||
| 2196 | int blocksize; | 2194 | int blocksize; |
| 2197 | 2195 | ||
| 2198 | parent = path->nodes[level + 1]; | 2196 | parent = path->nodes[level + 1]; |
| 2199 | if (!parent) | 2197 | if (!parent) |
| 2200 | return 0; | 2198 | return; |
| 2201 | 2199 | ||
| 2202 | nritems = btrfs_header_nritems(parent); | 2200 | nritems = btrfs_header_nritems(parent); |
| 2203 | slot = path->slots[level + 1]; | 2201 | slot = path->slots[level + 1]; |
| @@ -2224,28 +2222,11 @@ static noinline int reada_for_balance(struct btrfs_root *root, | |||
| 2224 | block2 = 0; | 2222 | block2 = 0; |
| 2225 | free_extent_buffer(eb); | 2223 | free_extent_buffer(eb); |
| 2226 | } | 2224 | } |
| 2227 | if (block1 || block2) { | ||
| 2228 | ret = -EAGAIN; | ||
| 2229 | |||
| 2230 | /* release the whole path */ | ||
| 2231 | btrfs_release_path(path); | ||
| 2232 | |||
| 2233 | /* read the blocks */ | ||
| 2234 | if (block1) | ||
| 2235 | readahead_tree_block(root, block1, blocksize, 0); | ||
| 2236 | if (block2) | ||
| 2237 | readahead_tree_block(root, block2, blocksize, 0); | ||
| 2238 | 2225 | ||
| 2239 | if (block1) { | 2226 | if (block1) |
| 2240 | eb = read_tree_block(root, block1, blocksize, 0); | 2227 | readahead_tree_block(root, block1, blocksize, 0); |
| 2241 | free_extent_buffer(eb); | 2228 | if (block2) |
| 2242 | } | 2229 | readahead_tree_block(root, block2, blocksize, 0); |
| 2243 | if (block2) { | ||
| 2244 | eb = read_tree_block(root, block2, blocksize, 0); | ||
| 2245 | free_extent_buffer(eb); | ||
| 2246 | } | ||
| 2247 | } | ||
| 2248 | return ret; | ||
| 2249 | } | 2230 | } |
| 2250 | 2231 | ||
| 2251 | 2232 | ||
| @@ -2359,35 +2340,28 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
| 2359 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); | 2340 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); |
| 2360 | if (tmp) { | 2341 | if (tmp) { |
| 2361 | /* first we do an atomic uptodate check */ | 2342 | /* first we do an atomic uptodate check */ |
| 2362 | if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) { | 2343 | if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) { |
| 2363 | if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) { | 2344 | *eb_ret = tmp; |
| 2364 | /* | 2345 | return 0; |
| 2365 | * we found an up to date block without | 2346 | } |
| 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 | 2347 | ||
| 2381 | /* now we're allowed to do a blocking uptodate check */ | 2348 | /* the pages were up to date, but we failed |
| 2382 | tmp = read_tree_block(root, blocknr, blocksize, gen); | 2349 | * the generation number check. Do a full |
| 2383 | if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) { | 2350 | * read for the generation number that is correct. |
| 2384 | *eb_ret = tmp; | 2351 | * We must do this without dropping locks so |
| 2385 | return 0; | 2352 | * we can trust our generation number |
| 2386 | } | 2353 | */ |
| 2387 | free_extent_buffer(tmp); | 2354 | btrfs_set_path_blocking(p); |
| 2388 | btrfs_release_path(p); | 2355 | |
| 2389 | return -EIO; | 2356 | /* now we're allowed to do a blocking uptodate check */ |
| 2357 | ret = btrfs_read_buffer(tmp, gen); | ||
| 2358 | if (!ret) { | ||
| 2359 | *eb_ret = tmp; | ||
| 2360 | return 0; | ||
| 2390 | } | 2361 | } |
| 2362 | free_extent_buffer(tmp); | ||
| 2363 | btrfs_release_path(p); | ||
| 2364 | return -EIO; | ||
| 2391 | } | 2365 | } |
| 2392 | 2366 | ||
| 2393 | /* | 2367 | /* |
| @@ -2448,11 +2422,8 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, | |||
| 2448 | goto again; | 2422 | goto again; |
| 2449 | } | 2423 | } |
| 2450 | 2424 | ||
| 2451 | sret = reada_for_balance(root, p, level); | ||
| 2452 | if (sret) | ||
| 2453 | goto again; | ||
| 2454 | |||
| 2455 | btrfs_set_path_blocking(p); | 2425 | btrfs_set_path_blocking(p); |
| 2426 | reada_for_balance(root, p, level); | ||
| 2456 | sret = split_node(trans, root, p, level); | 2427 | sret = split_node(trans, root, p, level); |
| 2457 | btrfs_clear_path_blocking(p, NULL, 0); | 2428 | btrfs_clear_path_blocking(p, NULL, 0); |
| 2458 | 2429 | ||
| @@ -2472,11 +2443,8 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, | |||
| 2472 | goto again; | 2443 | goto again; |
| 2473 | } | 2444 | } |
| 2474 | 2445 | ||
| 2475 | sret = reada_for_balance(root, p, level); | ||
| 2476 | if (sret) | ||
| 2477 | goto again; | ||
| 2478 | |||
| 2479 | btrfs_set_path_blocking(p); | 2446 | btrfs_set_path_blocking(p); |
| 2447 | reada_for_balance(root, p, level); | ||
| 2480 | sret = balance_level(trans, root, p, level); | 2448 | sret = balance_level(trans, root, p, level); |
| 2481 | btrfs_clear_path_blocking(p, NULL, 0); | 2449 | btrfs_clear_path_blocking(p, NULL, 0); |
| 2482 | 2450 | ||
| @@ -3143,7 +3111,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans, | |||
| 3143 | */ | 3111 | */ |
| 3144 | static noinline int insert_new_root(struct btrfs_trans_handle *trans, | 3112 | static noinline int insert_new_root(struct btrfs_trans_handle *trans, |
| 3145 | struct btrfs_root *root, | 3113 | struct btrfs_root *root, |
| 3146 | struct btrfs_path *path, int level, int log_removal) | 3114 | struct btrfs_path *path, int level) |
| 3147 | { | 3115 | { |
| 3148 | u64 lower_gen; | 3116 | u64 lower_gen; |
| 3149 | struct extent_buffer *lower; | 3117 | struct extent_buffer *lower; |
| @@ -3194,7 +3162,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, | |||
| 3194 | btrfs_mark_buffer_dirty(c); | 3162 | btrfs_mark_buffer_dirty(c); |
| 3195 | 3163 | ||
| 3196 | old = root->node; | 3164 | old = root->node; |
| 3197 | tree_mod_log_set_root_pointer(root, c, log_removal); | 3165 | tree_mod_log_set_root_pointer(root, c, 0); |
| 3198 | rcu_assign_pointer(root->node, c); | 3166 | rcu_assign_pointer(root->node, c); |
| 3199 | 3167 | ||
| 3200 | /* the super has an extra ref to root->node */ | 3168 | /* the super has an extra ref to root->node */ |
| @@ -3278,14 +3246,14 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
| 3278 | /* | 3246 | /* |
| 3279 | * trying to split the root, lets make a new one | 3247 | * trying to split the root, lets make a new one |
| 3280 | * | 3248 | * |
| 3281 | * tree mod log: We pass 0 as log_removal parameter to | 3249 | * tree mod log: We don't log_removal old root in |
| 3282 | * insert_new_root, because that root buffer will be kept as a | 3250 | * 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 | 3251 | * 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 | 3252 | * 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 | 3253 | * tree lock on the buffer, which is why we cannot race with |
| 3286 | * other tree_mod_log users. | 3254 | * other tree_mod_log users. |
| 3287 | */ | 3255 | */ |
| 3288 | ret = insert_new_root(trans, root, path, level + 1, 0); | 3256 | ret = insert_new_root(trans, root, path, level + 1); |
| 3289 | if (ret) | 3257 | if (ret) |
| 3290 | return ret; | 3258 | return ret; |
| 3291 | } else { | 3259 | } else { |
| @@ -3986,7 +3954,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
| 3986 | return -EOVERFLOW; | 3954 | return -EOVERFLOW; |
| 3987 | 3955 | ||
| 3988 | /* first try to make some room by pushing left and right */ | 3956 | /* first try to make some room by pushing left and right */ |
| 3989 | if (data_size) { | 3957 | if (data_size && path->nodes[1]) { |
| 3990 | wret = push_leaf_right(trans, root, path, data_size, | 3958 | wret = push_leaf_right(trans, root, path, data_size, |
| 3991 | data_size, 0, 0); | 3959 | data_size, 0, 0); |
| 3992 | if (wret < 0) | 3960 | if (wret < 0) |
| @@ -4005,7 +3973,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
| 4005 | } | 3973 | } |
| 4006 | 3974 | ||
| 4007 | if (!path->nodes[1]) { | 3975 | if (!path->nodes[1]) { |
| 4008 | ret = insert_new_root(trans, root, path, 1, 1); | 3976 | ret = insert_new_root(trans, root, path, 1); |
| 4009 | if (ret) | 3977 | if (ret) |
| 4010 | return ret; | 3978 | return ret; |
| 4011 | } | 3979 | } |
| @@ -4430,7 +4398,7 @@ void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path, | |||
| 4430 | } | 4398 | } |
| 4431 | 4399 | ||
| 4432 | /* | 4400 | /* |
| 4433 | * make the item pointed to by the path bigger, data_size is the new size. | 4401 | * make the item pointed to by the path bigger, data_size is the added size. |
| 4434 | */ | 4402 | */ |
| 4435 | void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, | 4403 | void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, |
| 4436 | u32 data_size) | 4404 | u32 data_size) |
