Skip to content

Commit

Permalink
Btrfs: adjust the write_lock_level as we unlock
Browse files Browse the repository at this point in the history
btrfs_search_slot sometimes needs write locks on high levels of
the tree.  It remembers the highest level that needs a write lock
and will use that for all future searches through the tree in a given
call.

But, very often we'll just cow the top level or the level below and we
won't really need write locks on the root again after that.  This patch
changes things to adjust the write lock requirement as it unlocks
levels.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason committed Mar 26, 2012
1 parent a098d8e commit f7c79f3
Showing 1 changed file with 17 additions and 6 deletions.
23 changes: 17 additions & 6 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,8 @@ static noinline int reada_for_balance(struct btrfs_root *root,
* if lowest_unlock is 1, level 0 won't be unlocked
*/
static noinline void unlock_up(struct btrfs_path *path, int level,
int lowest_unlock)
int lowest_unlock, int min_write_lock_level,
int *write_lock_level)
{
int i;
int skip_level = level;
Expand Down Expand Up @@ -1427,6 +1428,11 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
if (i >= lowest_unlock && i > skip_level && path->locks[i]) {
btrfs_tree_unlock_rw(t, path->locks[i]);
path->locks[i] = 0;
if (write_lock_level &&
i > min_write_lock_level &&
i <= *write_lock_level) {
*write_lock_level = i - 1;
}
}
}
}
Expand Down Expand Up @@ -1650,6 +1656,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
/* everything at write_lock_level or lower must be write locked */
int write_lock_level = 0;
u8 lowest_level = 0;
int min_write_lock_level;

lowest_level = p->lowest_level;
WARN_ON(lowest_level && ins_len > 0);
Expand Down Expand Up @@ -1677,6 +1684,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if (cow && (p->keep_locks || p->lowest_level))
write_lock_level = BTRFS_MAX_LEVEL;

min_write_lock_level = write_lock_level;

again:
/*
* we try very hard to do read locks on the root
Expand Down Expand Up @@ -1808,7 +1817,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
goto again;
}

unlock_up(p, level, lowest_unlock);
unlock_up(p, level, lowest_unlock,
min_write_lock_level, &write_lock_level);

if (level == lowest_level) {
if (dec)
Expand Down Expand Up @@ -1870,7 +1880,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
}
}
if (!p->search_for_split)
unlock_up(p, level, lowest_unlock);
unlock_up(p, level, lowest_unlock,
min_write_lock_level, &write_lock_level);
goto done;
}
}
Expand Down Expand Up @@ -4108,7 +4119,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
path->slots[level] = slot;
if (level == path->lowest_level) {
ret = 0;
unlock_up(path, level, 1);
unlock_up(path, level, 1, 0, NULL);
goto out;
}
btrfs_set_path_blocking(path);
Expand All @@ -4119,7 +4130,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,

path->locks[level - 1] = BTRFS_READ_LOCK;
path->nodes[level - 1] = cur;
unlock_up(path, level, 1);
unlock_up(path, level, 1, 0, NULL);
btrfs_clear_path_blocking(path, NULL, 0);
}
out:
Expand Down Expand Up @@ -4355,7 +4366,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
}
ret = 0;
done:
unlock_up(path, 0, 1);
unlock_up(path, 0, 1, 0, NULL);
path->leave_spinning = old_spinning;
if (!old_spinning)
btrfs_set_path_blocking(path);
Expand Down

0 comments on commit f7c79f3

Please sign in to comment.