aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2014-08-04 14:37:21 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:38:02 -0400
commitf98de9b9c07485f7e21edfd5b2b20c89d662af3c (patch)
treecf83b225c48c5f3fa32be73c25ad4c20b087d580 /fs
parent79aec2b80db1089f983d60e4a22cb95d8b939844 (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.c11
-rw-r--r--fs/btrfs/ioctl.c5
-rw-r--r--fs/btrfs/tree-log.c3
-rw-r--r--fs/btrfs/uuid-tree.c1
-rw-r--r--fs/btrfs/volumes.c2
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;
5149again: 5150again:
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 }
5226out: 5226out:
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);
945process_slot: 942process_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
281again_search_slot: 281again_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) {