diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.c | 23 |
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 | */ |
1397 | static noinline void unlock_up(struct btrfs_path *path, int level, | 1397 | static 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 | |||
1680 | again: | 1689 | again: |
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 | } |
4125 | out: | 4136 | out: |
@@ -4355,7 +4366,7 @@ again: | |||
4355 | } | 4366 | } |
4356 | ret = 0; | 4367 | ret = 0; |
4357 | done: | 4368 | done: |
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); |