Commit cb517eab authored by Miao Xie's avatar Miao Xie Committed by Josef Bacik

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: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
parent babbf170
...@@ -3376,9 +3376,9 @@ int __must_check btrfs_update_root(struct btrfs_trans_handle *trans, ...@@ -3376,9 +3376,9 @@ int __must_check btrfs_update_root(struct btrfs_trans_handle *trans,
struct btrfs_root_item *item); struct btrfs_root_item *item);
void btrfs_read_root_item(struct extent_buffer *eb, int slot, void btrfs_read_root_item(struct extent_buffer *eb, int slot,
struct btrfs_root_item *item); struct btrfs_root_item *item);
int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key,
btrfs_root_item *item, struct btrfs_key *key); struct btrfs_path *path, struct btrfs_root_item *root_item,
int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid); struct btrfs_key *root_key);
int btrfs_find_orphan_roots(struct btrfs_root *tree_root); int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
void btrfs_set_root_node(struct btrfs_root_item *item, void btrfs_set_root_node(struct btrfs_root_item *item,
struct extent_buffer *node); struct extent_buffer *node);
......
This diff is collapsed.
...@@ -63,14 +63,19 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev); ...@@ -63,14 +63,19 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev);
int btrfs_commit_super(struct btrfs_root *root); int btrfs_commit_super(struct btrfs_root *root);
struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
u64 bytenr, u32 blocksize); u64 bytenr, u32 blocksize);
struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root,
struct btrfs_key *location); struct btrfs_key *location);
int btrfs_init_fs_root(struct btrfs_root *root);
int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_root *root);
struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
struct btrfs_key *location); struct btrfs_key *location);
int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info); int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
void btrfs_btree_balance_dirty(struct btrfs_root *root); void btrfs_btree_balance_dirty(struct btrfs_root *root);
void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root); void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root);
void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_root *root);
void btrfs_free_fs_root(struct btrfs_root *root);
void btrfs_mark_buffer_dirty(struct extent_buffer *buf); void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
int atomic); int atomic);
......
...@@ -7447,7 +7447,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7447,7 +7447,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
} }
if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) {
ret = btrfs_find_last_root(tree_root, root->root_key.objectid, ret = btrfs_find_root(tree_root, &root->root_key, path,
NULL, NULL); NULL, NULL);
if (ret < 0) { if (ret < 0) {
btrfs_abort_transaction(trans, tree_root, ret); btrfs_abort_transaction(trans, tree_root, ret);
...@@ -7465,7 +7465,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7465,7 +7465,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
} }
if (root->in_radix) { if (root->in_radix) {
btrfs_free_fs_root(tree_root->fs_info, root); btrfs_drop_and_free_fs_root(tree_root->fs_info, root);
} else { } else {
free_extent_buffer(root->node); free_extent_buffer(root->node);
free_extent_buffer(root->commit_root); free_extent_buffer(root->commit_root);
......
...@@ -1355,8 +1355,7 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans, ...@@ -1355,8 +1355,7 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
BUG_ON(ret); BUG_ON(ret);
kfree(root_item); kfree(root_item);
reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root, reloc_root = btrfs_read_fs_root(root->fs_info->tree_root, &root_key);
&root_key);
BUG_ON(IS_ERR(reloc_root)); BUG_ON(IS_ERR(reloc_root));
reloc_root->last_trans = trans->transid; reloc_root->last_trans = trans->transid;
return reloc_root; return reloc_root;
...@@ -4277,7 +4276,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) ...@@ -4277,7 +4276,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
key.type != BTRFS_ROOT_ITEM_KEY) key.type != BTRFS_ROOT_ITEM_KEY)
break; break;
reloc_root = btrfs_read_fs_root_no_radix(root, &key); reloc_root = btrfs_read_fs_root(root, &key);
if (IS_ERR(reloc_root)) { if (IS_ERR(reloc_root)) {
err = PTR_ERR(reloc_root); err = PTR_ERR(reloc_root);
goto out; goto out;
......
...@@ -64,52 +64,59 @@ void btrfs_read_root_item(struct extent_buffer *eb, int slot, ...@@ -64,52 +64,59 @@ void btrfs_read_root_item(struct extent_buffer *eb, int slot,
} }
/* /*
* lookup the root with the highest offset for a given objectid. The key we do * btrfs_find_root - lookup the root by the key.
* find is copied into 'key'. If we find something return 0, otherwise 1, < 0 * root: the root of the root tree
* on error. * search_key: the key to search
* path: the path we search
* root_item: the root item of the tree we look for
* root_key: the reak key of the tree we look for
*
* If ->offset of 'seach_key' is -1ULL, it means we are not sure the offset
* of the search key, just lookup the root with the highest offset for a
* given objectid.
*
* If we find something return 0, otherwise > 0, < 0 on error.
*/ */
int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key,
struct btrfs_root_item *item, struct btrfs_key *key) struct btrfs_path *path, struct btrfs_root_item *root_item,
struct btrfs_key *root_key)
{ {
struct btrfs_path *path;
struct btrfs_key search_key;
struct btrfs_key found_key; struct btrfs_key found_key;
struct extent_buffer *l; struct extent_buffer *l;
int ret; int ret;
int slot; int slot;
search_key.objectid = objectid; ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0);
search_key.type = BTRFS_ROOT_ITEM_KEY;
search_key.offset = (u64)-1;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
if (ret < 0) if (ret < 0)
goto out; return ret;
BUG_ON(ret == 0); if (search_key->offset != -1ULL) { /* the search key is exact */
if (path->slots[0] == 0) { if (ret > 0)
ret = 1; goto out;
} else {
BUG_ON(ret == 0); /* Logical error */
if (path->slots[0] == 0)
goto out; goto out;
path->slots[0]--;
ret = 0;
} }
l = path->nodes[0]; l = path->nodes[0];
slot = path->slots[0] - 1; slot = path->slots[0];
btrfs_item_key_to_cpu(l, &found_key, slot); btrfs_item_key_to_cpu(l, &found_key, slot);
if (found_key.objectid != objectid || if (found_key.objectid != search_key->objectid ||
found_key.type != BTRFS_ROOT_ITEM_KEY) { found_key.type != BTRFS_ROOT_ITEM_KEY) {
ret = 1; ret = 1;
goto out; goto out;
} }
if (item)
btrfs_read_root_item(l, slot, item);
if (key)
memcpy(key, &found_key, sizeof(found_key));
ret = 0; if (root_item)
btrfs_read_root_item(l, slot, root_item);
if (root_key)
memcpy(root_key, &found_key, sizeof(found_key));
out: out:
btrfs_free_path(path); btrfs_release_path(path);
return ret; return ret;
} }
...@@ -212,86 +219,6 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, ...@@ -212,86 +219,6 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
return btrfs_insert_item(trans, root, key, item, sizeof(*item)); return btrfs_insert_item(trans, root, key, item, sizeof(*item));
} }
/*
* at mount time we want to find all the old transaction snapshots that were in
* the process of being deleted if we crashed. This is any root item with an
* offset lower than the latest root. They need to be queued for deletion to
* finish what was happening when we crashed.
*/
int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid)
{
struct btrfs_root *dead_root;
struct btrfs_root_item *ri;
struct btrfs_key key;
struct btrfs_key found_key;
struct btrfs_path *path;
int ret;
u32 nritems;
struct extent_buffer *leaf;
int slot;
key.objectid = objectid;
btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
key.offset = 0;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
again:
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0)
goto err;
while (1) {
leaf = path->nodes[0];
nritems = btrfs_header_nritems(leaf);
slot = path->slots[0];
if (slot >= nritems) {
ret = btrfs_next_leaf(root, path);
if (ret)
break;
leaf = path->nodes[0];
nritems = btrfs_header_nritems(leaf);
slot = path->slots[0];
}
btrfs_item_key_to_cpu(leaf, &key, slot);
if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
goto next;
if (key.objectid < objectid)
goto next;
if (key.objectid > objectid)
break;
ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
if (btrfs_disk_root_refs(leaf, ri) != 0)
goto next;
memcpy(&found_key, &key, sizeof(key));
key.offset++;
btrfs_release_path(path);
dead_root =
btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
&found_key);
if (IS_ERR(dead_root)) {
ret = PTR_ERR(dead_root);
goto err;
}
ret = btrfs_add_dead_root(dead_root);
if (ret)
goto err;
goto again;
next:
slot++;
path->slots[0]++;
}
ret = 0;
err:
btrfs_free_path(path);
return ret;
}
int btrfs_find_orphan_roots(struct btrfs_root *tree_root) int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
{ {
struct extent_buffer *leaf; struct extent_buffer *leaf;
...@@ -340,20 +267,29 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) ...@@ -340,20 +267,29 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
root_key.objectid = key.offset; root_key.objectid = key.offset;
key.offset++; key.offset++;
root = btrfs_read_fs_root_no_name(tree_root->fs_info, root = btrfs_read_fs_root(tree_root, &root_key);
&root_key); if (IS_ERR(root)) {
if (!IS_ERR(root)) err = PTR_ERR(root);
break;
}
if (btrfs_root_refs(&root->root_item) == 0) {
btrfs_add_dead_root(root);
continue; continue;
}
ret = PTR_ERR(root); err = btrfs_init_fs_root(root);
if (ret != -ENOENT) { if (err) {
err = ret; btrfs_free_fs_root(root);
break; break;
} }
ret = btrfs_find_dead_roots(tree_root, root_key.objectid); root->orphan_item_inserted = 1;
if (ret) {
err = ret; err = btrfs_insert_fs_root(root->fs_info, root);
if (err) {
BUG_ON(err == -EEXIST);
btrfs_free_fs_root(root);
break; break;
} }
} }
......
...@@ -4016,8 +4016,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) ...@@ -4016,8 +4016,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID) if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID)
break; break;
log = btrfs_read_fs_root_no_radix(log_root_tree, log = btrfs_read_fs_root(log_root_tree, &found_key);
&found_key);
if (IS_ERR(log)) { if (IS_ERR(log)) {
ret = PTR_ERR(log); ret = PTR_ERR(log);
btrfs_error(fs_info, ret, btrfs_error(fs_info, ret,
......
...@@ -5367,7 +5367,6 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root, ...@@ -5367,7 +5367,6 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
return NULL; return NULL;
list_add(&device->dev_list, list_add(&device->dev_list,
&fs_devices->devices); &fs_devices->devices);
device->dev_root = root->fs_info->dev_root;
device->devid = devid; device->devid = devid;
device->work.func = pending_bios_fn; device->work.func = pending_bios_fn;
device->fs_devices = fs_devices; device->fs_devices = fs_devices;
...@@ -5593,7 +5592,6 @@ static int read_one_dev(struct btrfs_root *root, ...@@ -5593,7 +5592,6 @@ static int read_one_dev(struct btrfs_root *root,
} }
fill_device_from_item(leaf, dev_item, device); fill_device_from_item(leaf, dev_item, device);
device->dev_root = root->fs_info->dev_root;
device->in_fs_metadata = 1; device->in_fs_metadata = 1;
if (device->writeable && !device->is_tgtdev_for_dev_replace) { if (device->writeable && !device->is_tgtdev_for_dev_replace) {
device->fs_devices->total_rw_bytes += device->total_bytes; device->fs_devices->total_rw_bytes += device->total_bytes;
...@@ -5751,6 +5749,17 @@ int btrfs_read_chunk_tree(struct btrfs_root *root) ...@@ -5751,6 +5749,17 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
return ret; return ret;
} }
void btrfs_init_devices_late(struct btrfs_fs_info *fs_info)
{
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
struct btrfs_device *device;
mutex_lock(&fs_devices->device_list_mutex);
list_for_each_entry(device, &fs_devices->devices, dev_list)
device->dev_root = fs_info->dev_root;
mutex_unlock(&fs_devices->device_list_mutex);
}
static void __btrfs_reset_dev_stats(struct btrfs_device *dev) static void __btrfs_reset_dev_stats(struct btrfs_device *dev)
{ {
int i; int i;
......
...@@ -321,6 +321,7 @@ int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, ...@@ -321,6 +321,7 @@ int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index); void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index);
int btrfs_get_dev_stats(struct btrfs_root *root, int btrfs_get_dev_stats(struct btrfs_root *root,
struct btrfs_ioctl_get_dev_stats *stats); struct btrfs_ioctl_get_dev_stats *stats);
void btrfs_init_devices_late(struct btrfs_fs_info *fs_info);
int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info); int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info);
int btrfs_run_dev_stats(struct btrfs_trans_handle *trans, int btrfs_run_dev_stats(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info); struct btrfs_fs_info *fs_info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment