|
@@ -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 @@ cow_done:
|
|
|
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 @@ cow_done:
|
|
|
}
|
|
|
}
|
|
|
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 @@ find_next_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 @@ find_next_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 @@ again:
|
|
|
}
|
|
|
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);
|