aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-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 8af24da983b1..270655da11d1 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);