aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan <yanzheng@21cn.com>2008-01-03 14:14:39 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:58 -0400
commit73e48b277a3fcd647f1936c71aea2f8d450ecc74 (patch)
treea64bd6675dde709cf288d9236a4add1f18781799 /fs
parentd548ee5182bda42c87bdd4e28b539d5e436e206a (diff)
Btrfs: Properly handle overlapping extent in shrink_extent_tree
The patch fixes the overlapping extent issue in shrink_extent_tree. It checks whether there is an overlapping extent by using find_previous_extent. If there is an overlapping extent, it setups key.objectid and cur_byte properly. --- Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/extent-tree.c140
1 files changed, 56 insertions, 84 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index cc89df4493ab..426a0222e12f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2317,36 +2317,6 @@ out:
2317 return ret; 2317 return ret;
2318} 2318}
2319 2319
2320static int find_overlapping_extent(struct btrfs_root *root,
2321 struct btrfs_path *path, u64 new_size)
2322{
2323 struct btrfs_key found_key;
2324 struct extent_buffer *leaf;
2325 int ret;
2326
2327 while(1) {
2328 if (path->slots[0] == 0) {
2329 ret = btrfs_prev_leaf(root, path);
2330 if (ret == 1) {
2331 return 1;
2332 }
2333 if (ret < 0)
2334 return ret;
2335 } else {
2336 path->slots[0]--;
2337 }
2338 leaf = path->nodes[0];
2339 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2340 if (found_key.type == BTRFS_EXTENT_ITEM_KEY) {
2341 if (found_key.objectid + found_key.offset > new_size)
2342 return 0;
2343 else
2344 return 1;
2345 }
2346 }
2347 return 1;
2348}
2349
2350int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size) 2320int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size)
2351{ 2321{
2352 struct btrfs_trans_handle *trans; 2322 struct btrfs_trans_handle *trans;
@@ -2357,11 +2327,10 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size)
2357 struct btrfs_fs_info *info = root->fs_info; 2327 struct btrfs_fs_info *info = root->fs_info;
2358 struct extent_map_tree *block_group_cache; 2328 struct extent_map_tree *block_group_cache;
2359 struct btrfs_key key; 2329 struct btrfs_key key;
2360 struct btrfs_key found_key = { 0, 0, 0 }; 2330 struct btrfs_key found_key;
2361 struct extent_buffer *leaf; 2331 struct extent_buffer *leaf;
2362 u32 nritems; 2332 u32 nritems;
2363 int ret; 2333 int ret;
2364 int slot;
2365 2334
2366 btrfs_set_super_total_bytes(&info->super_copy, new_size); 2335 btrfs_set_super_total_bytes(&info->super_copy, new_size);
2367 block_group_cache = &info->block_group_cache; 2336 block_group_cache = &info->block_group_cache;
@@ -2372,48 +2341,54 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size)
2372again: 2341again:
2373 total_found = 0; 2342 total_found = 0;
2374 key.objectid = new_size; 2343 key.objectid = new_size;
2375 cur_byte = key.objectid;
2376 key.offset = 0; 2344 key.offset = 0;
2377 key.type = 0; 2345 key.type = 0;
2378 while(1) { 2346 cur_byte = key.objectid;
2379 2347
2348 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
2349 if (ret < 0)
2350 goto out;
2351
2352 ret = find_previous_extent(root, path);
2353 if (ret < 0)
2354 goto out;
2355 if (ret == 0) {
2356 leaf = path->nodes[0];
2357 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2358 if (found_key.objectid + found_key.offset > new_size) {
2359 cur_byte = found_key.objectid;
2360 key.objectid = cur_byte;
2361 }
2362 }
2363 btrfs_release_path(root, path);
2364
2365 while(1) {
2380 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 2366 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
2381 if (ret < 0) 2367 if (ret < 0)
2382 goto out; 2368 goto out;
2383next: 2369
2384 leaf = path->nodes[0]; 2370 leaf = path->nodes[0];
2385 if (key.objectid == new_size - 1) { 2371 nritems = btrfs_header_nritems(leaf);
2386 ret = find_overlapping_extent(root, path, new_size); 2372next:
2387 if (ret != 0) { 2373 if (path->slots[0] >= nritems) {
2388 btrfs_release_path(root, path); 2374 ret = btrfs_next_leaf(root, path);
2389 ret = btrfs_search_slot(NULL, root, &key, 2375 if (ret < 0)
2390 path, 0, 0); 2376 goto out;
2391 if (ret < 0) 2377 if (ret == 1) {
2392 goto out; 2378 ret = 0;
2379 break;
2393 } 2380 }
2381 leaf = path->nodes[0];
2382 nritems = btrfs_header_nritems(leaf);
2394 } 2383 }
2395 nritems = btrfs_header_nritems(leaf); 2384
2396 ret = 0; 2385 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2397 slot = path->slots[0]; 2386 if (btrfs_key_type(&found_key) != BTRFS_EXTENT_ITEM_KEY ||
2398 if (slot < nritems) 2387 found_key.objectid + found_key.offset <= cur_byte) {
2399 btrfs_item_key_to_cpu(leaf, &found_key, slot);
2400 if (slot == nritems ||
2401 btrfs_key_type(&found_key) != BTRFS_EXTENT_ITEM_KEY) {
2402 path->slots[0]++; 2388 path->slots[0]++;
2403 if (path->slots[0] >= nritems) {
2404 ret = btrfs_next_leaf(root, path);
2405 if (ret < 0)
2406 goto out;
2407 if (ret == 1) {
2408 ret = 0;
2409 break;
2410 }
2411 }
2412 goto next; 2389 goto next;
2413 } 2390 }
2414 btrfs_item_key_to_cpu(leaf, &found_key, slot); 2391
2415 if (found_key.objectid + found_key.offset <= cur_byte)
2416 continue;
2417 total_found++; 2392 total_found++;
2418 cur_byte = found_key.objectid + found_key.offset; 2393 cur_byte = found_key.objectid + found_key.offset;
2419 key.objectid = cur_byte; 2394 key.objectid = cur_byte;
@@ -2446,33 +2421,30 @@ next:
2446 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 2421 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
2447 if (ret < 0) 2422 if (ret < 0)
2448 goto out; 2423 goto out;
2449bg_next: 2424
2450 leaf = path->nodes[0]; 2425 leaf = path->nodes[0];
2451 nritems = btrfs_header_nritems(leaf); 2426 nritems = btrfs_header_nritems(leaf);
2452 ret = 0; 2427bg_next:
2453 slot = path->slots[0]; 2428 if (path->slots[0] >= nritems) {
2454 if (slot < nritems) 2429 ret = btrfs_next_leaf(root, path);
2455 btrfs_item_key_to_cpu(leaf, &found_key, slot); 2430 if (ret < 0)
2456 if (slot == nritems || 2431 break;
2457 btrfs_key_type(&found_key) != BTRFS_BLOCK_GROUP_ITEM_KEY) { 2432 if (ret == 1) {
2458 if (slot < nritems) { 2433 ret = 0;
2459 printk("shrinker found key %Lu %u %Lu\n", 2434 break;
2460 found_key.objectid, found_key.type,
2461 found_key.offset);
2462 path->slots[0]++;
2463 }
2464 if (path->slots[0] >= nritems) {
2465 ret = btrfs_next_leaf(root, path);
2466 if (ret < 0)
2467 break;
2468 if (ret == 1) {
2469 ret = 0;
2470 break;
2471 }
2472 } 2435 }
2436 leaf = path->nodes[0];
2437 nritems = btrfs_header_nritems(leaf);
2438 }
2439
2440 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2441 if (btrfs_key_type(&found_key) != BTRFS_BLOCK_GROUP_ITEM_KEY) {
2442 printk("shrinker found key %Lu %u %Lu\n",
2443 found_key.objectid, found_key.type,
2444 found_key.offset);
2445 path->slots[0]++;
2473 goto bg_next; 2446 goto bg_next;
2474 } 2447 }
2475 btrfs_item_key_to_cpu(leaf, &found_key, slot);
2476 ret = get_state_private(&info->block_group_cache, 2448 ret = get_state_private(&info->block_group_cache,
2477 found_key.objectid, &ptr); 2449 found_key.objectid, &ptr);
2478 if (!ret) 2450 if (!ret)