From 5b00b78262e24b0dc53c72b408db4c6472058095 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 19 Mar 2012 15:54:38 -0400 Subject: [PATCH] --- yaml --- r: 297851 b: refs/heads/master c: f7c79f30cb2d3883488e70cafc9e3a7edd4b9fdb h: refs/heads/master i: 297849: 9aa1390c4b3e397b0abe1bec7b4cb89143450993 297847: 7fb9b95033eec5a14a012325cdddc7b1e04201a3 v: v3 --- [refs] | 2 +- trunk/fs/btrfs/ctree.c | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index be1eb1ec45e3..1618c325e791 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a098d8e8eec5a46a47b1bb74390746973d913a9c +refs/heads/master: f7c79f30cb2d3883488e70cafc9e3a7edd4b9fdb diff --git a/trunk/fs/btrfs/ctree.c b/trunk/fs/btrfs/ctree.c index 8af24da983b1..270655da11d1 100644 --- a/trunk/fs/btrfs/ctree.c +++ b/trunk/fs/btrfs/ctree.c @@ -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; @@ -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; + } } } } @@ -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); @@ -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 @@ -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) @@ -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; } } @@ -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); @@ -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: @@ -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);