diff options
author | Filipe Manana <fdmanana@suse.com> | 2014-08-04 14:37:21 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-09-17 16:38:02 -0400 |
commit | f98de9b9c07485f7e21edfd5b2b20c89d662af3c (patch) | |
tree | cf83b225c48c5f3fa32be73c25ad4c20b087d580 /fs | |
parent | 79aec2b80db1089f983d60e4a22cb95d8b939844 (diff) |
Btrfs: make btrfs_search_forward return with nodes unlocked
None of the uses of btrfs_search_forward() need to have the path
nodes (level >= 1) read locked, only the leaf needs to be locked
while the caller processes it. Therefore make it return a path
with all nodes unlocked, except for the leaf.
This change is motivated by the observation that during a file
fsync we repeatdly call btrfs_search_forward() and process the
returned leaf while upper nodes of the returned path (level >= 1)
are read locked, which unnecessarily blocks other tasks that want
to write to the same fs/subvol btree.
Therefore instead of modifying the fsync code to unlock all nodes
with level >= 1 immediately after calling btrfs_search_forward(),
change btrfs_search_forward() to do it, so that it benefits all
callers.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.c | 11 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 5 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 3 | ||||
-rw-r--r-- | fs/btrfs/uuid-tree.c | 1 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 2 |
5 files changed, 7 insertions, 15 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 783ea3bac7dc..39021bf2df9a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -5144,8 +5144,9 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, | |||
5144 | u32 nritems; | 5144 | u32 nritems; |
5145 | int level; | 5145 | int level; |
5146 | int ret = 1; | 5146 | int ret = 1; |
5147 | int keep_locks = path->keep_locks; | ||
5147 | 5148 | ||
5148 | WARN_ON(!path->keep_locks); | 5149 | path->keep_locks = 1; |
5149 | again: | 5150 | again: |
5150 | cur = btrfs_read_lock_root_node(root); | 5151 | cur = btrfs_read_lock_root_node(root); |
5151 | level = btrfs_header_level(cur); | 5152 | level = btrfs_header_level(cur); |
@@ -5209,7 +5210,6 @@ find_next_key: | |||
5209 | path->slots[level] = slot; | 5210 | path->slots[level] = slot; |
5210 | if (level == path->lowest_level) { | 5211 | if (level == path->lowest_level) { |
5211 | ret = 0; | 5212 | ret = 0; |
5212 | unlock_up(path, level, 1, 0, NULL); | ||
5213 | goto out; | 5213 | goto out; |
5214 | } | 5214 | } |
5215 | btrfs_set_path_blocking(path); | 5215 | btrfs_set_path_blocking(path); |
@@ -5224,9 +5224,12 @@ find_next_key: | |||
5224 | btrfs_clear_path_blocking(path, NULL, 0); | 5224 | btrfs_clear_path_blocking(path, NULL, 0); |
5225 | } | 5225 | } |
5226 | out: | 5226 | out: |
5227 | if (ret == 0) | 5227 | path->keep_locks = keep_locks; |
5228 | if (ret == 0) { | ||
5229 | btrfs_unlock_up_safe(path, path->lowest_level + 1); | ||
5230 | btrfs_set_path_blocking(path); | ||
5228 | memcpy(min_key, &found_key, sizeof(found_key)); | 5231 | memcpy(min_key, &found_key, sizeof(found_key)); |
5229 | btrfs_set_path_blocking(path); | 5232 | } |
5230 | return ret; | 5233 | return ret; |
5231 | } | 5234 | } |
5232 | 5235 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4492e017bdb2..85ca3cce8554 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -936,12 +936,9 @@ static int find_new_extents(struct btrfs_root *root, | |||
936 | min_key.offset = *off; | 936 | min_key.offset = *off; |
937 | 937 | ||
938 | while (1) { | 938 | while (1) { |
939 | path->keep_locks = 1; | ||
940 | ret = btrfs_search_forward(root, &min_key, path, newer_than); | 939 | ret = btrfs_search_forward(root, &min_key, path, newer_than); |
941 | if (ret != 0) | 940 | if (ret != 0) |
942 | goto none; | 941 | goto none; |
943 | path->keep_locks = 0; | ||
944 | btrfs_unlock_up_safe(path, 1); | ||
945 | process_slot: | 942 | process_slot: |
946 | if (min_key.objectid != ino) | 943 | if (min_key.objectid != ino) |
947 | goto none; | 944 | goto none; |
@@ -2088,8 +2085,6 @@ static noinline int search_ioctl(struct inode *inode, | |||
2088 | key.type = sk->min_type; | 2085 | key.type = sk->min_type; |
2089 | key.offset = sk->min_offset; | 2086 | key.offset = sk->min_offset; |
2090 | 2087 | ||
2091 | path->keep_locks = 1; | ||
2092 | |||
2093 | while (1) { | 2088 | while (1) { |
2094 | ret = btrfs_search_forward(root, &key, path, sk->min_transid); | 2089 | ret = btrfs_search_forward(root, &key, path, sk->min_transid); |
2095 | if (ret != 0) { | 2090 | if (ret != 0) { |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 7b6d1428f033..82db14f5cf87 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2983,8 +2983,6 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
2983 | min_key.type = key_type; | 2983 | min_key.type = key_type; |
2984 | min_key.offset = min_offset; | 2984 | min_key.offset = min_offset; |
2985 | 2985 | ||
2986 | path->keep_locks = 1; | ||
2987 | |||
2988 | ret = btrfs_search_forward(root, &min_key, path, trans->transid); | 2986 | ret = btrfs_search_forward(root, &min_key, path, trans->transid); |
2989 | 2987 | ||
2990 | /* | 2988 | /* |
@@ -3964,7 +3962,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
3964 | err = ret; | 3962 | err = ret; |
3965 | goto out_unlock; | 3963 | goto out_unlock; |
3966 | } | 3964 | } |
3967 | path->keep_locks = 1; | ||
3968 | 3965 | ||
3969 | while (1) { | 3966 | while (1) { |
3970 | ins_nr = 0; | 3967 | ins_nr = 0; |
diff --git a/fs/btrfs/uuid-tree.c b/fs/btrfs/uuid-tree.c index f6a4c03ee7d8..778282944530 100644 --- a/fs/btrfs/uuid-tree.c +++ b/fs/btrfs/uuid-tree.c | |||
@@ -279,7 +279,6 @@ int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info, | |||
279 | key.offset = 0; | 279 | key.offset = 0; |
280 | 280 | ||
281 | again_search_slot: | 281 | again_search_slot: |
282 | path->keep_locks = 1; | ||
283 | ret = btrfs_search_forward(root, &key, path, 0); | 282 | ret = btrfs_search_forward(root, &key, path, 0); |
284 | if (ret) { | 283 | if (ret) { |
285 | if (ret > 0) | 284 | if (ret > 0) |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 46cd29ad3156..ff8386eb3367 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -3625,8 +3625,6 @@ static int btrfs_uuid_scan_kthread(void *data) | |||
3625 | max_key.type = BTRFS_ROOT_ITEM_KEY; | 3625 | max_key.type = BTRFS_ROOT_ITEM_KEY; |
3626 | max_key.offset = (u64)-1; | 3626 | max_key.offset = (u64)-1; |
3627 | 3627 | ||
3628 | path->keep_locks = 1; | ||
3629 | |||
3630 | while (1) { | 3628 | while (1) { |
3631 | ret = btrfs_search_forward(root, &key, path, 0); | 3629 | ret = btrfs_search_forward(root, &key, path, 0); |
3632 | if (ret) { | 3630 | if (ret) { |