Commit cb517eabba4f109810dba2e5f37b0dcf22103065
Committed by
Josef Bacik
1 parent
babbf170c7
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
Btrfs: cleanup the similar code of the fs root read
There are several functions whose code is similar, such as btrfs_find_last_root() btrfs_read_fs_root_no_radix() Besides that, some functions are invoked twice, it is unnecessary, for example, we are sure that all roots which is found in btrfs_find_orphan_roots() have their orphan items, so it is unnecessary to check the orphan item again. So cleanup it. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Showing 9 changed files with 228 additions and 269 deletions Side-by-side Diff
fs/btrfs/ctree.h
... | ... | @@ -3376,9 +3376,9 @@ |
3376 | 3376 | struct btrfs_root_item *item); |
3377 | 3377 | void btrfs_read_root_item(struct extent_buffer *eb, int slot, |
3378 | 3378 | struct btrfs_root_item *item); |
3379 | -int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct | |
3380 | - btrfs_root_item *item, struct btrfs_key *key); | |
3381 | -int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid); | |
3379 | +int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key, | |
3380 | + struct btrfs_path *path, struct btrfs_root_item *root_item, | |
3381 | + struct btrfs_key *root_key); | |
3382 | 3382 | int btrfs_find_orphan_roots(struct btrfs_root *tree_root); |
3383 | 3383 | void btrfs_set_root_node(struct btrfs_root_item *item, |
3384 | 3384 | struct extent_buffer *node); |
fs/btrfs/disk-io.c
... | ... | @@ -1234,39 +1234,6 @@ |
1234 | 1234 | spin_lock_init(&root->root_item_lock); |
1235 | 1235 | } |
1236 | 1236 | |
1237 | -static int __must_check find_and_setup_root(struct btrfs_root *tree_root, | |
1238 | - struct btrfs_fs_info *fs_info, | |
1239 | - u64 objectid, | |
1240 | - struct btrfs_root *root) | |
1241 | -{ | |
1242 | - int ret; | |
1243 | - u32 blocksize; | |
1244 | - u64 generation; | |
1245 | - | |
1246 | - __setup_root(tree_root->nodesize, tree_root->leafsize, | |
1247 | - tree_root->sectorsize, tree_root->stripesize, | |
1248 | - root, fs_info, objectid); | |
1249 | - ret = btrfs_find_last_root(tree_root, objectid, | |
1250 | - &root->root_item, &root->root_key); | |
1251 | - if (ret > 0) | |
1252 | - return -ENOENT; | |
1253 | - else if (ret < 0) | |
1254 | - return ret; | |
1255 | - | |
1256 | - generation = btrfs_root_generation(&root->root_item); | |
1257 | - blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); | |
1258 | - root->commit_root = NULL; | |
1259 | - root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | |
1260 | - blocksize, generation); | |
1261 | - if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) { | |
1262 | - free_extent_buffer(root->node); | |
1263 | - root->node = NULL; | |
1264 | - return -EIO; | |
1265 | - } | |
1266 | - root->commit_root = btrfs_root_node(root); | |
1267 | - return 0; | |
1268 | -} | |
1269 | - | |
1270 | 1237 | static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info) |
1271 | 1238 | { |
1272 | 1239 | struct btrfs_root *root = kzalloc(sizeof(*root), GFP_NOFS); |
1273 | 1240 | |
1274 | 1241 | |
1275 | 1242 | |
1276 | 1243 | |
1277 | 1244 | |
1278 | 1245 | |
1279 | 1246 | |
1280 | 1247 | |
1281 | 1248 | |
1282 | 1249 | |
1283 | 1250 | |
... | ... | @@ -1451,70 +1418,73 @@ |
1451 | 1418 | return 0; |
1452 | 1419 | } |
1453 | 1420 | |
1454 | -struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, | |
1455 | - struct btrfs_key *location) | |
1421 | +struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root, | |
1422 | + struct btrfs_key *key) | |
1456 | 1423 | { |
1457 | 1424 | struct btrfs_root *root; |
1458 | 1425 | struct btrfs_fs_info *fs_info = tree_root->fs_info; |
1459 | 1426 | struct btrfs_path *path; |
1460 | - struct extent_buffer *l; | |
1461 | 1427 | u64 generation; |
1462 | 1428 | u32 blocksize; |
1463 | - int ret = 0; | |
1464 | - int slot; | |
1429 | + int ret; | |
1465 | 1430 | |
1466 | - root = btrfs_alloc_root(fs_info); | |
1467 | - if (!root) | |
1431 | + path = btrfs_alloc_path(); | |
1432 | + if (!path) | |
1468 | 1433 | return ERR_PTR(-ENOMEM); |
1469 | - if (location->offset == (u64)-1) { | |
1470 | - ret = find_and_setup_root(tree_root, fs_info, | |
1471 | - location->objectid, root); | |
1472 | - if (ret) { | |
1473 | - kfree(root); | |
1474 | - return ERR_PTR(ret); | |
1475 | - } | |
1476 | - goto out; | |
1434 | + | |
1435 | + root = btrfs_alloc_root(fs_info); | |
1436 | + if (!root) { | |
1437 | + ret = -ENOMEM; | |
1438 | + goto alloc_fail; | |
1477 | 1439 | } |
1478 | 1440 | |
1479 | 1441 | __setup_root(tree_root->nodesize, tree_root->leafsize, |
1480 | 1442 | tree_root->sectorsize, tree_root->stripesize, |
1481 | - root, fs_info, location->objectid); | |
1443 | + root, fs_info, key->objectid); | |
1482 | 1444 | |
1483 | - path = btrfs_alloc_path(); | |
1484 | - if (!path) { | |
1485 | - kfree(root); | |
1486 | - return ERR_PTR(-ENOMEM); | |
1487 | - } | |
1488 | - ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); | |
1489 | - if (ret == 0) { | |
1490 | - l = path->nodes[0]; | |
1491 | - slot = path->slots[0]; | |
1492 | - btrfs_read_root_item(l, slot, &root->root_item); | |
1493 | - memcpy(&root->root_key, location, sizeof(*location)); | |
1494 | - } | |
1495 | - btrfs_free_path(path); | |
1445 | + ret = btrfs_find_root(tree_root, key, path, | |
1446 | + &root->root_item, &root->root_key); | |
1496 | 1447 | if (ret) { |
1497 | - kfree(root); | |
1498 | 1448 | if (ret > 0) |
1499 | 1449 | ret = -ENOENT; |
1500 | - return ERR_PTR(ret); | |
1450 | + goto find_fail; | |
1501 | 1451 | } |
1502 | 1452 | |
1503 | 1453 | generation = btrfs_root_generation(&root->root_item); |
1504 | 1454 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); |
1505 | 1455 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
1506 | 1456 | blocksize, generation); |
1507 | - if (!root->node || !extent_buffer_uptodate(root->node)) { | |
1508 | - ret = (!root->node) ? -ENOMEM : -EIO; | |
1509 | - | |
1510 | - free_extent_buffer(root->node); | |
1511 | - kfree(root); | |
1512 | - return ERR_PTR(ret); | |
1457 | + if (!root->node) { | |
1458 | + ret = -ENOMEM; | |
1459 | + goto find_fail; | |
1460 | + } else if (!btrfs_buffer_uptodate(root->node, generation, 0)) { | |
1461 | + ret = -EIO; | |
1462 | + goto read_fail; | |
1513 | 1463 | } |
1514 | - | |
1515 | 1464 | root->commit_root = btrfs_root_node(root); |
1516 | 1465 | out: |
1517 | - if (location->objectid != BTRFS_TREE_LOG_OBJECTID) { | |
1466 | + btrfs_free_path(path); | |
1467 | + return root; | |
1468 | + | |
1469 | +read_fail: | |
1470 | + free_extent_buffer(root->node); | |
1471 | +find_fail: | |
1472 | + kfree(root); | |
1473 | +alloc_fail: | |
1474 | + root = ERR_PTR(ret); | |
1475 | + goto out; | |
1476 | +} | |
1477 | + | |
1478 | +struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root, | |
1479 | + struct btrfs_key *location) | |
1480 | +{ | |
1481 | + struct btrfs_root *root; | |
1482 | + | |
1483 | + root = btrfs_read_tree_root(tree_root, location); | |
1484 | + if (IS_ERR(root)) | |
1485 | + return root; | |
1486 | + | |
1487 | + if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { | |
1518 | 1488 | root->ref_cows = 1; |
1519 | 1489 | btrfs_check_and_init_root_item(&root->root_item); |
1520 | 1490 | } |
... | ... | @@ -1522,6 +1492,66 @@ |
1522 | 1492 | return root; |
1523 | 1493 | } |
1524 | 1494 | |
1495 | +int btrfs_init_fs_root(struct btrfs_root *root) | |
1496 | +{ | |
1497 | + int ret; | |
1498 | + | |
1499 | + root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS); | |
1500 | + root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned), | |
1501 | + GFP_NOFS); | |
1502 | + if (!root->free_ino_pinned || !root->free_ino_ctl) { | |
1503 | + ret = -ENOMEM; | |
1504 | + goto fail; | |
1505 | + } | |
1506 | + | |
1507 | + btrfs_init_free_ino_ctl(root); | |
1508 | + mutex_init(&root->fs_commit_mutex); | |
1509 | + spin_lock_init(&root->cache_lock); | |
1510 | + init_waitqueue_head(&root->cache_wait); | |
1511 | + | |
1512 | + ret = get_anon_bdev(&root->anon_dev); | |
1513 | + if (ret) | |
1514 | + goto fail; | |
1515 | + return 0; | |
1516 | +fail: | |
1517 | + kfree(root->free_ino_ctl); | |
1518 | + kfree(root->free_ino_pinned); | |
1519 | + return ret; | |
1520 | +} | |
1521 | + | |
1522 | +struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, | |
1523 | + u64 root_id) | |
1524 | +{ | |
1525 | + struct btrfs_root *root; | |
1526 | + | |
1527 | + spin_lock(&fs_info->fs_roots_radix_lock); | |
1528 | + root = radix_tree_lookup(&fs_info->fs_roots_radix, | |
1529 | + (unsigned long)root_id); | |
1530 | + spin_unlock(&fs_info->fs_roots_radix_lock); | |
1531 | + return root; | |
1532 | +} | |
1533 | + | |
1534 | +int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info, | |
1535 | + struct btrfs_root *root) | |
1536 | +{ | |
1537 | + int ret; | |
1538 | + | |
1539 | + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); | |
1540 | + if (ret) | |
1541 | + return ret; | |
1542 | + | |
1543 | + spin_lock(&fs_info->fs_roots_radix_lock); | |
1544 | + ret = radix_tree_insert(&fs_info->fs_roots_radix, | |
1545 | + (unsigned long)root->root_key.objectid, | |
1546 | + root); | |
1547 | + if (ret == 0) | |
1548 | + root->in_radix = 1; | |
1549 | + spin_unlock(&fs_info->fs_roots_radix_lock); | |
1550 | + radix_tree_preload_end(); | |
1551 | + | |
1552 | + return ret; | |
1553 | +} | |
1554 | + | |
1525 | 1555 | struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, |
1526 | 1556 | struct btrfs_key *location) |
1527 | 1557 | { |
1528 | 1558 | |
1529 | 1559 | |
1530 | 1560 | |
1531 | 1561 | |
1532 | 1562 | |
... | ... | @@ -1542,58 +1572,30 @@ |
1542 | 1572 | return fs_info->quota_root ? fs_info->quota_root : |
1543 | 1573 | ERR_PTR(-ENOENT); |
1544 | 1574 | again: |
1545 | - spin_lock(&fs_info->fs_roots_radix_lock); | |
1546 | - root = radix_tree_lookup(&fs_info->fs_roots_radix, | |
1547 | - (unsigned long)location->objectid); | |
1548 | - spin_unlock(&fs_info->fs_roots_radix_lock); | |
1575 | + root = btrfs_lookup_fs_root(fs_info, location->objectid); | |
1549 | 1576 | if (root) |
1550 | 1577 | return root; |
1551 | 1578 | |
1552 | - root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location); | |
1579 | + root = btrfs_read_fs_root(fs_info->tree_root, location); | |
1553 | 1580 | if (IS_ERR(root)) |
1554 | 1581 | return root; |
1555 | 1582 | |
1556 | - root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS); | |
1557 | - root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned), | |
1558 | - GFP_NOFS); | |
1559 | - if (!root->free_ino_pinned || !root->free_ino_ctl) { | |
1560 | - ret = -ENOMEM; | |
1583 | + if (btrfs_root_refs(&root->root_item) == 0) { | |
1584 | + ret = -ENOENT; | |
1561 | 1585 | goto fail; |
1562 | 1586 | } |
1563 | 1587 | |
1564 | - btrfs_init_free_ino_ctl(root); | |
1565 | - mutex_init(&root->fs_commit_mutex); | |
1566 | - spin_lock_init(&root->cache_lock); | |
1567 | - init_waitqueue_head(&root->cache_wait); | |
1568 | - | |
1569 | - ret = get_anon_bdev(&root->anon_dev); | |
1588 | + ret = btrfs_init_fs_root(root); | |
1570 | 1589 | if (ret) |
1571 | 1590 | goto fail; |
1572 | 1591 | |
1573 | - if (btrfs_root_refs(&root->root_item) == 0) { | |
1574 | - ret = -ENOENT; | |
1575 | - goto fail; | |
1576 | - } | |
1577 | - | |
1578 | 1592 | ret = btrfs_find_orphan_item(fs_info->tree_root, location->objectid); |
1579 | 1593 | if (ret < 0) |
1580 | 1594 | goto fail; |
1581 | 1595 | if (ret == 0) |
1582 | 1596 | root->orphan_item_inserted = 1; |
1583 | 1597 | |
1584 | - ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); | |
1585 | - if (ret) | |
1586 | - goto fail; | |
1587 | - | |
1588 | - spin_lock(&fs_info->fs_roots_radix_lock); | |
1589 | - ret = radix_tree_insert(&fs_info->fs_roots_radix, | |
1590 | - (unsigned long)root->root_key.objectid, | |
1591 | - root); | |
1592 | - if (ret == 0) | |
1593 | - root->in_radix = 1; | |
1594 | - | |
1595 | - spin_unlock(&fs_info->fs_roots_radix_lock); | |
1596 | - radix_tree_preload_end(); | |
1598 | + ret = btrfs_insert_fs_root(fs_info, root); | |
1597 | 1599 | if (ret) { |
1598 | 1600 | if (ret == -EEXIST) { |
1599 | 1601 | free_fs_root(root); |
... | ... | @@ -1601,10 +1603,6 @@ |
1601 | 1603 | } |
1602 | 1604 | goto fail; |
1603 | 1605 | } |
1604 | - | |
1605 | - ret = btrfs_find_dead_roots(fs_info->tree_root, | |
1606 | - root->root_key.objectid); | |
1607 | - WARN_ON(ret); | |
1608 | 1606 | return root; |
1609 | 1607 | fail: |
1610 | 1608 | free_fs_root(root); |
... | ... | @@ -2050,7 +2048,7 @@ |
2050 | 2048 | list_del(&gang[0]->root_list); |
2051 | 2049 | |
2052 | 2050 | if (gang[0]->in_radix) { |
2053 | - btrfs_free_fs_root(fs_info, gang[0]); | |
2051 | + btrfs_drop_and_free_fs_root(fs_info, gang[0]); | |
2054 | 2052 | } else { |
2055 | 2053 | free_extent_buffer(gang[0]->node); |
2056 | 2054 | free_extent_buffer(gang[0]->commit_root); |
... | ... | @@ -2065,7 +2063,7 @@ |
2065 | 2063 | if (!ret) |
2066 | 2064 | break; |
2067 | 2065 | for (i = 0; i < ret; i++) |
2068 | - btrfs_free_fs_root(fs_info, gang[i]); | |
2066 | + btrfs_drop_and_free_fs_root(fs_info, gang[i]); | |
2069 | 2067 | } |
2070 | 2068 | } |
2071 | 2069 | |
2072 | 2070 | |
... | ... | @@ -2097,14 +2095,8 @@ |
2097 | 2095 | int backup_index = 0; |
2098 | 2096 | |
2099 | 2097 | tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info); |
2100 | - extent_root = fs_info->extent_root = btrfs_alloc_root(fs_info); | |
2101 | - csum_root = fs_info->csum_root = btrfs_alloc_root(fs_info); | |
2102 | 2098 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info); |
2103 | - dev_root = fs_info->dev_root = btrfs_alloc_root(fs_info); | |
2104 | - quota_root = fs_info->quota_root = btrfs_alloc_root(fs_info); | |
2105 | - | |
2106 | - if (!tree_root || !extent_root || !csum_root || | |
2107 | - !chunk_root || !dev_root || !quota_root) { | |
2099 | + if (!tree_root || !chunk_root) { | |
2108 | 2100 | err = -ENOMEM; |
2109 | 2101 | goto fail; |
2110 | 2102 | } |
2111 | 2103 | |
2112 | 2104 | |
2113 | 2105 | |
2114 | 2106 | |
2115 | 2107 | |
2116 | 2108 | |
2117 | 2109 | |
2118 | 2110 | |
2119 | 2111 | |
2120 | 2112 | |
... | ... | @@ -2655,33 +2647,44 @@ |
2655 | 2647 | btrfs_set_root_node(&tree_root->root_item, tree_root->node); |
2656 | 2648 | tree_root->commit_root = btrfs_root_node(tree_root); |
2657 | 2649 | |
2658 | - ret = find_and_setup_root(tree_root, fs_info, | |
2659 | - BTRFS_EXTENT_TREE_OBJECTID, extent_root); | |
2660 | - if (ret) | |
2650 | + location.objectid = BTRFS_EXTENT_TREE_OBJECTID; | |
2651 | + location.type = BTRFS_ROOT_ITEM_KEY; | |
2652 | + location.offset = 0; | |
2653 | + | |
2654 | + extent_root = btrfs_read_tree_root(tree_root, &location); | |
2655 | + if (IS_ERR(extent_root)) { | |
2656 | + ret = PTR_ERR(extent_root); | |
2661 | 2657 | goto recovery_tree_root; |
2658 | + } | |
2662 | 2659 | extent_root->track_dirty = 1; |
2660 | + fs_info->extent_root = extent_root; | |
2663 | 2661 | |
2664 | - ret = find_and_setup_root(tree_root, fs_info, | |
2665 | - BTRFS_DEV_TREE_OBJECTID, dev_root); | |
2666 | - if (ret) | |
2662 | + location.objectid = BTRFS_DEV_TREE_OBJECTID; | |
2663 | + dev_root = btrfs_read_tree_root(tree_root, &location); | |
2664 | + if (IS_ERR(dev_root)) { | |
2665 | + ret = PTR_ERR(dev_root); | |
2667 | 2666 | goto recovery_tree_root; |
2667 | + } | |
2668 | 2668 | dev_root->track_dirty = 1; |
2669 | + fs_info->dev_root = dev_root; | |
2670 | + btrfs_init_devices_late(fs_info); | |
2669 | 2671 | |
2670 | - ret = find_and_setup_root(tree_root, fs_info, | |
2671 | - BTRFS_CSUM_TREE_OBJECTID, csum_root); | |
2672 | - if (ret) | |
2672 | + location.objectid = BTRFS_CSUM_TREE_OBJECTID; | |
2673 | + csum_root = btrfs_read_tree_root(tree_root, &location); | |
2674 | + if (IS_ERR(csum_root)) { | |
2675 | + ret = PTR_ERR(csum_root); | |
2673 | 2676 | goto recovery_tree_root; |
2677 | + } | |
2674 | 2678 | csum_root->track_dirty = 1; |
2679 | + fs_info->csum_root = csum_root; | |
2675 | 2680 | |
2676 | - ret = find_and_setup_root(tree_root, fs_info, | |
2677 | - BTRFS_QUOTA_TREE_OBJECTID, quota_root); | |
2678 | - if (ret) { | |
2679 | - kfree(quota_root); | |
2680 | - quota_root = fs_info->quota_root = NULL; | |
2681 | - } else { | |
2681 | + location.objectid = BTRFS_QUOTA_TREE_OBJECTID; | |
2682 | + quota_root = btrfs_read_tree_root(tree_root, &location); | |
2683 | + if (!IS_ERR(quota_root)) { | |
2682 | 2684 | quota_root->track_dirty = 1; |
2683 | 2685 | fs_info->quota_enabled = 1; |
2684 | 2686 | fs_info->pending_quota_state = 1; |
2687 | + fs_info->quota_root = quota_root; | |
2685 | 2688 | } |
2686 | 2689 | |
2687 | 2690 | fs_info->generation = generation; |
... | ... | @@ -2834,7 +2837,7 @@ |
2834 | 2837 | |
2835 | 2838 | location.objectid = BTRFS_FS_TREE_OBJECTID; |
2836 | 2839 | location.type = BTRFS_ROOT_ITEM_KEY; |
2837 | - location.offset = (u64)-1; | |
2840 | + location.offset = 0; | |
2838 | 2841 | |
2839 | 2842 | fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location); |
2840 | 2843 | if (IS_ERR(fs_info->fs_root)) { |
... | ... | @@ -3381,7 +3384,9 @@ |
3381 | 3384 | return ret; |
3382 | 3385 | } |
3383 | 3386 | |
3384 | -void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | |
3387 | +/* Drop a fs root from the radix tree and free it. */ | |
3388 | +void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, | |
3389 | + struct btrfs_root *root) | |
3385 | 3390 | { |
3386 | 3391 | spin_lock(&fs_info->fs_roots_radix_lock); |
3387 | 3392 | radix_tree_delete(&fs_info->fs_roots_radix, |
... | ... | @@ -3413,6 +3418,11 @@ |
3413 | 3418 | kfree(root->free_ino_pinned); |
3414 | 3419 | kfree(root->name); |
3415 | 3420 | kfree(root); |
3421 | +} | |
3422 | + | |
3423 | +void btrfs_free_fs_root(struct btrfs_root *root) | |
3424 | +{ | |
3425 | + free_fs_root(root); | |
3416 | 3426 | } |
3417 | 3427 | |
3418 | 3428 | int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info) |
fs/btrfs/disk-io.h
... | ... | @@ -63,14 +63,19 @@ |
63 | 63 | int btrfs_commit_super(struct btrfs_root *root); |
64 | 64 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
65 | 65 | u64 bytenr, u32 blocksize); |
66 | -struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, | |
67 | - struct btrfs_key *location); | |
66 | +struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root, | |
67 | + struct btrfs_key *location); | |
68 | +int btrfs_init_fs_root(struct btrfs_root *root); | |
69 | +int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info, | |
70 | + struct btrfs_root *root); | |
68 | 71 | struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, |
69 | 72 | struct btrfs_key *location); |
70 | 73 | int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info); |
71 | 74 | void btrfs_btree_balance_dirty(struct btrfs_root *root); |
72 | 75 | void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root); |
73 | -void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); | |
76 | +void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, | |
77 | + struct btrfs_root *root); | |
78 | +void btrfs_free_fs_root(struct btrfs_root *root); | |
74 | 79 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf); |
75 | 80 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, |
76 | 81 | int atomic); |
fs/btrfs/extent-tree.c
... | ... | @@ -7447,8 +7447,8 @@ |
7447 | 7447 | } |
7448 | 7448 | |
7449 | 7449 | if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { |
7450 | - ret = btrfs_find_last_root(tree_root, root->root_key.objectid, | |
7451 | - NULL, NULL); | |
7450 | + ret = btrfs_find_root(tree_root, &root->root_key, path, | |
7451 | + NULL, NULL); | |
7452 | 7452 | if (ret < 0) { |
7453 | 7453 | btrfs_abort_transaction(trans, tree_root, ret); |
7454 | 7454 | err = ret; |
... | ... | @@ -7465,7 +7465,7 @@ |
7465 | 7465 | } |
7466 | 7466 | |
7467 | 7467 | if (root->in_radix) { |
7468 | - btrfs_free_fs_root(tree_root->fs_info, root); | |
7468 | + btrfs_drop_and_free_fs_root(tree_root->fs_info, root); | |
7469 | 7469 | } else { |
7470 | 7470 | free_extent_buffer(root->node); |
7471 | 7471 | free_extent_buffer(root->commit_root); |
fs/btrfs/relocation.c
... | ... | @@ -1355,8 +1355,7 @@ |
1355 | 1355 | BUG_ON(ret); |
1356 | 1356 | kfree(root_item); |
1357 | 1357 | |
1358 | - reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root, | |
1359 | - &root_key); | |
1358 | + reloc_root = btrfs_read_fs_root(root->fs_info->tree_root, &root_key); | |
1360 | 1359 | BUG_ON(IS_ERR(reloc_root)); |
1361 | 1360 | reloc_root->last_trans = trans->transid; |
1362 | 1361 | return reloc_root; |
... | ... | @@ -4277,7 +4276,7 @@ |
4277 | 4276 | key.type != BTRFS_ROOT_ITEM_KEY) |
4278 | 4277 | break; |
4279 | 4278 | |
4280 | - reloc_root = btrfs_read_fs_root_no_radix(root, &key); | |
4279 | + reloc_root = btrfs_read_fs_root(root, &key); | |
4281 | 4280 | if (IS_ERR(reloc_root)) { |
4282 | 4281 | err = PTR_ERR(reloc_root); |
4283 | 4282 | goto out; |
fs/btrfs/root-tree.c
... | ... | @@ -64,52 +64,59 @@ |
64 | 64 | } |
65 | 65 | |
66 | 66 | /* |
67 | - * lookup the root with the highest offset for a given objectid. The key we do | |
68 | - * find is copied into 'key'. If we find something return 0, otherwise 1, < 0 | |
69 | - * on error. | |
67 | + * btrfs_find_root - lookup the root by the key. | |
68 | + * root: the root of the root tree | |
69 | + * search_key: the key to search | |
70 | + * path: the path we search | |
71 | + * root_item: the root item of the tree we look for | |
72 | + * root_key: the reak key of the tree we look for | |
73 | + * | |
74 | + * If ->offset of 'seach_key' is -1ULL, it means we are not sure the offset | |
75 | + * of the search key, just lookup the root with the highest offset for a | |
76 | + * given objectid. | |
77 | + * | |
78 | + * If we find something return 0, otherwise > 0, < 0 on error. | |
70 | 79 | */ |
71 | -int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | |
72 | - struct btrfs_root_item *item, struct btrfs_key *key) | |
80 | +int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key, | |
81 | + struct btrfs_path *path, struct btrfs_root_item *root_item, | |
82 | + struct btrfs_key *root_key) | |
73 | 83 | { |
74 | - struct btrfs_path *path; | |
75 | - struct btrfs_key search_key; | |
76 | 84 | struct btrfs_key found_key; |
77 | 85 | struct extent_buffer *l; |
78 | 86 | int ret; |
79 | 87 | int slot; |
80 | 88 | |
81 | - search_key.objectid = objectid; | |
82 | - search_key.type = BTRFS_ROOT_ITEM_KEY; | |
83 | - search_key.offset = (u64)-1; | |
84 | - | |
85 | - path = btrfs_alloc_path(); | |
86 | - if (!path) | |
87 | - return -ENOMEM; | |
88 | - ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); | |
89 | + ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0); | |
89 | 90 | if (ret < 0) |
90 | - goto out; | |
91 | + return ret; | |
91 | 92 | |
92 | - BUG_ON(ret == 0); | |
93 | - if (path->slots[0] == 0) { | |
94 | - ret = 1; | |
95 | - goto out; | |
93 | + if (search_key->offset != -1ULL) { /* the search key is exact */ | |
94 | + if (ret > 0) | |
95 | + goto out; | |
96 | + } else { | |
97 | + BUG_ON(ret == 0); /* Logical error */ | |
98 | + if (path->slots[0] == 0) | |
99 | + goto out; | |
100 | + path->slots[0]--; | |
101 | + ret = 0; | |
96 | 102 | } |
103 | + | |
97 | 104 | l = path->nodes[0]; |
98 | - slot = path->slots[0] - 1; | |
105 | + slot = path->slots[0]; | |
106 | + | |
99 | 107 | btrfs_item_key_to_cpu(l, &found_key, slot); |
100 | - if (found_key.objectid != objectid || | |
108 | + if (found_key.objectid != search_key->objectid || | |
101 | 109 | found_key.type != BTRFS_ROOT_ITEM_KEY) { |
102 | 110 | ret = 1; |
103 | 111 | goto out; |
104 | 112 | } |
105 | - if (item) | |
106 | - btrfs_read_root_item(l, slot, item); | |
107 | - if (key) | |
108 | - memcpy(key, &found_key, sizeof(found_key)); | |
109 | 113 | |
110 | - ret = 0; | |
114 | + if (root_item) | |
115 | + btrfs_read_root_item(l, slot, root_item); | |
116 | + if (root_key) | |
117 | + memcpy(root_key, &found_key, sizeof(found_key)); | |
111 | 118 | out: |
112 | - btrfs_free_path(path); | |
119 | + btrfs_release_path(path); | |
113 | 120 | return ret; |
114 | 121 | } |
115 | 122 | |
... | ... | @@ -212,86 +219,6 @@ |
212 | 219 | return btrfs_insert_item(trans, root, key, item, sizeof(*item)); |
213 | 220 | } |
214 | 221 | |
215 | -/* | |
216 | - * at mount time we want to find all the old transaction snapshots that were in | |
217 | - * the process of being deleted if we crashed. This is any root item with an | |
218 | - * offset lower than the latest root. They need to be queued for deletion to | |
219 | - * finish what was happening when we crashed. | |
220 | - */ | |
221 | -int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid) | |
222 | -{ | |
223 | - struct btrfs_root *dead_root; | |
224 | - struct btrfs_root_item *ri; | |
225 | - struct btrfs_key key; | |
226 | - struct btrfs_key found_key; | |
227 | - struct btrfs_path *path; | |
228 | - int ret; | |
229 | - u32 nritems; | |
230 | - struct extent_buffer *leaf; | |
231 | - int slot; | |
232 | - | |
233 | - key.objectid = objectid; | |
234 | - btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | |
235 | - key.offset = 0; | |
236 | - path = btrfs_alloc_path(); | |
237 | - if (!path) | |
238 | - return -ENOMEM; | |
239 | - | |
240 | -again: | |
241 | - ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | |
242 | - if (ret < 0) | |
243 | - goto err; | |
244 | - while (1) { | |
245 | - leaf = path->nodes[0]; | |
246 | - nritems = btrfs_header_nritems(leaf); | |
247 | - slot = path->slots[0]; | |
248 | - if (slot >= nritems) { | |
249 | - ret = btrfs_next_leaf(root, path); | |
250 | - if (ret) | |
251 | - break; | |
252 | - leaf = path->nodes[0]; | |
253 | - nritems = btrfs_header_nritems(leaf); | |
254 | - slot = path->slots[0]; | |
255 | - } | |
256 | - btrfs_item_key_to_cpu(leaf, &key, slot); | |
257 | - if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) | |
258 | - goto next; | |
259 | - | |
260 | - if (key.objectid < objectid) | |
261 | - goto next; | |
262 | - | |
263 | - if (key.objectid > objectid) | |
264 | - break; | |
265 | - | |
266 | - ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item); | |
267 | - if (btrfs_disk_root_refs(leaf, ri) != 0) | |
268 | - goto next; | |
269 | - | |
270 | - memcpy(&found_key, &key, sizeof(key)); | |
271 | - key.offset++; | |
272 | - btrfs_release_path(path); | |
273 | - dead_root = | |
274 | - btrfs_read_fs_root_no_radix(root->fs_info->tree_root, | |
275 | - &found_key); | |
276 | - if (IS_ERR(dead_root)) { | |
277 | - ret = PTR_ERR(dead_root); | |
278 | - goto err; | |
279 | - } | |
280 | - | |
281 | - ret = btrfs_add_dead_root(dead_root); | |
282 | - if (ret) | |
283 | - goto err; | |
284 | - goto again; | |
285 | -next: | |
286 | - slot++; | |
287 | - path->slots[0]++; | |
288 | - } | |
289 | - ret = 0; | |
290 | -err: | |
291 | - btrfs_free_path(path); | |
292 | - return ret; | |
293 | -} | |
294 | - | |
295 | 222 | int btrfs_find_orphan_roots(struct btrfs_root *tree_root) |
296 | 223 | { |
297 | 224 | struct extent_buffer *leaf; |
298 | 225 | |
299 | 226 | |
300 | 227 | |
... | ... | @@ -340,20 +267,29 @@ |
340 | 267 | root_key.objectid = key.offset; |
341 | 268 | key.offset++; |
342 | 269 | |
343 | - root = btrfs_read_fs_root_no_name(tree_root->fs_info, | |
344 | - &root_key); | |
345 | - if (!IS_ERR(root)) | |
270 | + root = btrfs_read_fs_root(tree_root, &root_key); | |
271 | + if (IS_ERR(root)) { | |
272 | + err = PTR_ERR(root); | |
273 | + break; | |
274 | + } | |
275 | + | |
276 | + if (btrfs_root_refs(&root->root_item) == 0) { | |
277 | + btrfs_add_dead_root(root); | |
346 | 278 | continue; |
279 | + } | |
347 | 280 | |
348 | - ret = PTR_ERR(root); | |
349 | - if (ret != -ENOENT) { | |
350 | - err = ret; | |
281 | + err = btrfs_init_fs_root(root); | |
282 | + if (err) { | |
283 | + btrfs_free_fs_root(root); | |
351 | 284 | break; |
352 | 285 | } |
353 | 286 | |
354 | - ret = btrfs_find_dead_roots(tree_root, root_key.objectid); | |
355 | - if (ret) { | |
356 | - err = ret; | |
287 | + root->orphan_item_inserted = 1; | |
288 | + | |
289 | + err = btrfs_insert_fs_root(root->fs_info, root); | |
290 | + if (err) { | |
291 | + BUG_ON(err == -EEXIST); | |
292 | + btrfs_free_fs_root(root); | |
357 | 293 | break; |
358 | 294 | } |
359 | 295 | } |
fs/btrfs/tree-log.c
... | ... | @@ -4016,8 +4016,7 @@ |
4016 | 4016 | if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID) |
4017 | 4017 | break; |
4018 | 4018 | |
4019 | - log = btrfs_read_fs_root_no_radix(log_root_tree, | |
4020 | - &found_key); | |
4019 | + log = btrfs_read_fs_root(log_root_tree, &found_key); | |
4021 | 4020 | if (IS_ERR(log)) { |
4022 | 4021 | ret = PTR_ERR(log); |
4023 | 4022 | btrfs_error(fs_info, ret, |
fs/btrfs/volumes.c
... | ... | @@ -5367,7 +5367,6 @@ |
5367 | 5367 | return NULL; |
5368 | 5368 | list_add(&device->dev_list, |
5369 | 5369 | &fs_devices->devices); |
5370 | - device->dev_root = root->fs_info->dev_root; | |
5371 | 5370 | device->devid = devid; |
5372 | 5371 | device->work.func = pending_bios_fn; |
5373 | 5372 | device->fs_devices = fs_devices; |
... | ... | @@ -5593,7 +5592,6 @@ |
5593 | 5592 | } |
5594 | 5593 | |
5595 | 5594 | fill_device_from_item(leaf, dev_item, device); |
5596 | - device->dev_root = root->fs_info->dev_root; | |
5597 | 5595 | device->in_fs_metadata = 1; |
5598 | 5596 | if (device->writeable && !device->is_tgtdev_for_dev_replace) { |
5599 | 5597 | device->fs_devices->total_rw_bytes += device->total_bytes; |
... | ... | @@ -5749,6 +5747,17 @@ |
5749 | 5747 | |
5750 | 5748 | btrfs_free_path(path); |
5751 | 5749 | return ret; |
5750 | +} | |
5751 | + | |
5752 | +void btrfs_init_devices_late(struct btrfs_fs_info *fs_info) | |
5753 | +{ | |
5754 | + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; | |
5755 | + struct btrfs_device *device; | |
5756 | + | |
5757 | + mutex_lock(&fs_devices->device_list_mutex); | |
5758 | + list_for_each_entry(device, &fs_devices->devices, dev_list) | |
5759 | + device->dev_root = fs_info->dev_root; | |
5760 | + mutex_unlock(&fs_devices->device_list_mutex); | |
5752 | 5761 | } |
5753 | 5762 | |
5754 | 5763 | static void __btrfs_reset_dev_stats(struct btrfs_device *dev) |
fs/btrfs/volumes.h
... | ... | @@ -321,6 +321,7 @@ |
321 | 321 | void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index); |
322 | 322 | int btrfs_get_dev_stats(struct btrfs_root *root, |
323 | 323 | struct btrfs_ioctl_get_dev_stats *stats); |
324 | +void btrfs_init_devices_late(struct btrfs_fs_info *fs_info); | |
324 | 325 | int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info); |
325 | 326 | int btrfs_run_dev_stats(struct btrfs_trans_handle *trans, |
326 | 327 | struct btrfs_fs_info *fs_info); |