On 2018年05月18日 11:00, Liu Bo wrote:
> It's good to have a helper instead of having all get-root details
> open-coded.
>
> The new helper locks (if necessary) and sets root node of the path.
>
> Also invert the checks to make the code flow easier to read.
>
> There is no functional change in this commit.
>
> Signed-off-by: Liu Bo
Less indents with better use of goto tag, indeed easier to read.
Reviewed-by: Qu Wenruo
Thanks,
Qu
> ---
> fs/btrfs/ctree.c | 115
> +--
> 1 file changed, 70 insertions(+), 45 deletions(-)
>
> diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
> index a96d308c51b8..d12fc0474e21 100644
> --- a/fs/btrfs/ctree.c
> +++ b/fs/btrfs/ctree.c
> @@ -2598,6 +2598,75 @@ int btrfs_find_item(struct btrfs_root *fs_root, struct
> btrfs_path *path,
> return 0;
> }
>
> +static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root
> *root,
> + struct btrfs_path *p,
> + int write_lock_level)
> +{
> + struct btrfs_fs_info *fs_info = root->fs_info;
> + struct extent_buffer *b;
> + int root_lock;
> + int level = 0;
> +
> + /*
> + * we try very hard to do read locks on the root
> + */
> + root_lock = BTRFS_READ_LOCK;
> +
> + if (p->search_commit_root) {
> + /*
> + * the commit roots are read only so we always do read locks
> + */
> + if (p->need_commit_sem)
> + down_read(&fs_info->commit_root_sem);
> + b = root->commit_root;
> + extent_buffer_get(b);
> + level = btrfs_header_level(b);
> + if (p->need_commit_sem)
> + up_read(&fs_info->commit_root_sem);
> + if (!p->skip_locking)
> + btrfs_tree_read_lock(b);
> +
> + goto out;
> + }
> +
> + if (p->skip_locking) {
> + b = btrfs_root_node(root);
> + level = btrfs_header_level(b);
> + goto out;
> + }
> +
> + /*
> + * we don't know the level of the root node until we actually
> + * have it read locked
> + */
> + b = btrfs_read_lock_root_node(root);
> + level = btrfs_header_level(b);
> + if (level > write_lock_level)
> + goto out;
> +
> + /*
> + * whoops, must trade for write lock
> + */
> + btrfs_tree_read_unlock(b);
> + free_extent_buffer(b);
> + b = btrfs_lock_root_node(root);
> + root_lock = BTRFS_WRITE_LOCK;
> + /*
> + * the level might have changed, check again
> + */
> + level = btrfs_header_level(b);
> +
> +out:
> + p->nodes[level] = b;
> + if (!p->skip_locking)
> + p->locks[level] = root_lock;
> + /*
> + * Callers are responsible for drop b's refs.
> + */
> + return b;
> +}
> +
> +
> /*
> * btrfs_search_slot - look for a key in a tree and perform necessary
> * modifications to preserve tree invariants.
> @@ -2634,7 +2703,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans,
> struct btrfs_root *root,
> int err;
> int level;
> int lowest_unlock = 1;
> - int root_lock;
> /* everything at write_lock_level or lower must be write locked */
> int write_lock_level = 0;
> u8 lowest_level = 0;
> @@ -2672,50 +2740,7 @@ int btrfs_search_slot(struct btrfs_trans_handle
> *trans, struct btrfs_root *root,
>
> again:
> prev_cmp = -1;
> - /*
> - * we try very hard to do read locks on the root
> - */
> - root_lock = BTRFS_READ_LOCK;
> - level = 0;
> - if (p->search_commit_root) {
> - /*
> - * the commit roots are read only
> - * so we always do read locks
> - */
> - if (p->need_commit_sem)
> - down_read(&fs_info->commit_root_sem);
> - b = root->commit_root;
> - extent_buffer_get(b);
> - level = btrfs_header_level(b);
> - if (p->need_commit_sem)
> - up_read(&fs_info->commit_root_sem);
> - if (!p->skip_locking)
> - btrfs_tree_read_lock(b);
> - } else {
> - if (p->skip_locking) {
> - b = btrfs_root_node(root);
> - level = btrfs_header_level(b);
> - } else {
> - /* we don't know the level of the root node
> - * until we actually have it read locked
> - */
> - b = btrfs_read_lock_root_node(root);
> - level = btrfs_header_level(b);
> - if (level <= write_lock_level) {
> - /* whoops, must trade for write lock */
> - btrfs_tree_read_unlock(b);
> - free_extent_buffer(