aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2012-03-19 15:54:38 -0400
committerChris Mason <chris.mason@oracle.com>2012-03-26 17:04:24 -0400
commitf7c79f30cb2d3883488e70cafc9e3a7edd4b9fdb (patch)
tree784c5c878e85a7b8fa283e22767b057d6cfcfa40 /fs/btrfs/ctree.c
parenta098d8e8eec5a46a47b1bb74390746973d913a9c (diff)
Btrfs: adjust the write_lock_level as we unlock
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>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 8af24da983b..270655da11d 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1395,7 +1395,8 @@ static noinline int reada_for_balance(struct btrfs_root *root,
1395 * if lowest_unlock is 1, level 0 won't be unlocked 1395 * if lowest_unlock is 1, level 0 won't be unlocked
1396 */ 1396 */
1397static noinline void unlock_up(struct btrfs_path *path, int level, 1397static noinline void unlock_up(struct btrfs_path *path, int level,
1398 int lowest_unlock) 1398 int lowest_unlock, int min_write_lock_level,
1399 int *write_lock_level)
1399{ 1400{
1400 int i; 1401 int i;
1401 int skip_level = level; 1402 int skip_level = level;
@@ -1427,6 +1428,11 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
1427 if (i >= lowest_unlock && i > skip_level && path->locks[i]) { 1428 if (i >= lowest_unlock && i > skip_level && path->locks[i]) {
1428 btrfs_tree_unlock_rw(t, path->locks[i]); 1429 btrfs_tree_unlock_rw(t, path->locks[i]);
1429 path->locks[i] = 0; 1430 path->locks[i] = 0;
1431 if (write_lock_level &&
1432 i > min_write_lock_level &&
1433 i <= *write_lock_level) {
1434 *write_lock_level = i - 1;
1435 }
1430 } 1436 }
1431 } 1437 }
1432} 1438}
@@ -1650,6 +1656,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
1650 /* everything at write_lock_level or lower must be write locked */ 1656 /* everything at write_lock_level or lower must be write locked */
1651 int write_lock_level = 0; 1657 int write_lock_level = 0;
1652 u8 lowest_level = 0; 1658 u8 lowest_level = 0;
1659 int min_write_lock_level;
1653 1660
1654 lowest_level = p->lowest_level; 1661 lowest_level = p->lowest_level;
1655 WARN_ON(lowest_level && ins_len > 0); 1662 WARN_ON(lowest_level && ins_len > 0);
@@ -1677,6 +1684,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
1677 if (cow && (p->keep_locks || p->lowest_level)) 1684 if (cow && (p->keep_locks || p->lowest_level))
1678 write_lock_level = BTRFS_MAX_LEVEL; 1685 write_lock_level = BTRFS_MAX_LEVEL;
1679 1686
1687 min_write_lock_level = write_lock_level;
1688
1680again: 1689again:
1681 /* 1690 /*
1682 * we try very hard to do read locks on the root 1691 * we try very hard to do read locks on the root
@@ -1808,7 +1817,8 @@ cow_done:
1808 goto again; 1817 goto again;
1809 } 1818 }
1810 1819
1811 unlock_up(p, level, lowest_unlock); 1820 unlock_up(p, level, lowest_unlock,
1821 min_write_lock_level, &write_lock_level);
1812 1822
1813 if (level == lowest_level) { 1823 if (level == lowest_level) {
1814 if (dec) 1824 if (dec)
@@ -1870,7 +1880,8 @@ cow_done:
1870 } 1880 }
1871 } 1881 }
1872 if (!p->search_for_split) 1882 if (!p->search_for_split)
1873 unlock_up(p, level, lowest_unlock); 1883 unlock_up(p, level, lowest_unlock,
1884 min_write_lock_level, &write_lock_level);
1874 goto done; 1885 goto done;
1875 } 1886 }
1876 } 1887 }
@@ -4108,7 +4119,7 @@ find_next_key:
4108 path->slots[level] = slot; 4119 path->slots[level] = slot;
4109 if (level == path->lowest_level) { 4120 if (level == path->lowest_level) {
4110 ret = 0; 4121 ret = 0;
4111 unlock_up(path, level, 1); 4122 unlock_up(path, level, 1, 0, NULL);
4112 goto out; 4123 goto out;
4113 } 4124 }
4114 btrfs_set_path_blocking(path); 4125 btrfs_set_path_blocking(path);
@@ -4119,7 +4130,7 @@ find_next_key:
4119 4130
4120 path->locks[level - 1] = BTRFS_READ_LOCK; 4131 path->locks[level - 1] = BTRFS_READ_LOCK;
4121 path->nodes[level - 1] = cur; 4132 path->nodes[level - 1] = cur;
4122 unlock_up(path, level, 1); 4133 unlock_up(path, level, 1, 0, NULL);
4123 btrfs_clear_path_blocking(path, NULL, 0); 4134 btrfs_clear_path_blocking(path, NULL, 0);
4124 } 4135 }
4125out: 4136out:
@@ -4355,7 +4366,7 @@ again:
4355 } 4366 }
4356 ret = 0; 4367 ret = 0;
4357done: 4368done:
4358 unlock_up(path, 0, 1); 4369 unlock_up(path, 0, 1, 0, NULL);
4359 path->leave_spinning = old_spinning; 4370 path->leave_spinning = old_spinning;
4360 if (!old_spinning) 4371 if (!old_spinning)
4361 btrfs_set_path_blocking(path); 4372 btrfs_set_path_blocking(path);