Commit f9efa9c7 authored by Chris Mason's avatar Chris Mason

Btrfs: Reduce contention on the root node

This calls unlock_up sooner in btrfs_search_slot in order to decrease the
amount of work done with the higher level tree locks held.

Also, it changes btrfs_tree_lock to spin for a big against the page lock
before scheduling.  This makes a big difference in context switch rate under
highly contended workloads.

Longer term, a better locking structure is needed than the page lock.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 3f157a2f
...@@ -1313,16 +1313,13 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1313,16 +1313,13 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
slot = p->slots[level]; slot = p->slots[level];
BUG_ON(btrfs_header_nritems(b) == 1); BUG_ON(btrfs_header_nritems(b) == 1);
} }
unlock_up(p, level, lowest_unlock);
/* this is only true while dropping a snapshot */ /* this is only true while dropping a snapshot */
if (level == lowest_level) { if (level == lowest_level) {
unlock_up(p, level, lowest_unlock);
break; break;
} }
if (should_reada)
reada_for_search(root, p, level, slot,
key->objectid);
blocknr = btrfs_node_blockptr(b, slot); blocknr = btrfs_node_blockptr(b, slot);
gen = btrfs_node_ptr_generation(b, slot); gen = btrfs_node_ptr_generation(b, slot);
blocksize = btrfs_level_size(root, level - 1); blocksize = btrfs_level_size(root, level - 1);
...@@ -1340,6 +1337,11 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1340,6 +1337,11 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_release_path(NULL, p); btrfs_release_path(NULL, p);
if (tmp) if (tmp)
free_extent_buffer(tmp); free_extent_buffer(tmp);
if (should_reada)
reada_for_search(root, p,
level, slot,
key->objectid);
tmp = read_tree_block(root, blocknr, tmp = read_tree_block(root, blocknr,
blocksize, gen); blocksize, gen);
if (tmp) if (tmp)
...@@ -1348,12 +1350,15 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1348,12 +1350,15 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
} else { } else {
if (tmp) if (tmp)
free_extent_buffer(tmp); free_extent_buffer(tmp);
if (should_reada)
reada_for_search(root, p,
level, slot,
key->objectid);
b = read_node_slot(root, b, slot); b = read_node_slot(root, b, slot);
} }
} }
if (!p->skip_locking) if (!p->skip_locking)
btrfs_tree_lock(b); btrfs_tree_lock(b);
unlock_up(p, level, lowest_unlock);
} else { } else {
p->slots[level] = slot; p->slots[level] = slot;
if (ins_len > 0 && btrfs_leaf_free_space(root, b) < if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
......
...@@ -27,6 +27,16 @@ ...@@ -27,6 +27,16 @@
int btrfs_tree_lock(struct extent_buffer *eb) int btrfs_tree_lock(struct extent_buffer *eb)
{ {
int i;
if (!TestSetPageLocked(eb->first_page))
return 0;
for (i = 0; i < 512; i++) {
cpu_relax();
if (!TestSetPageLocked(eb->first_page))
return 0;
}
cpu_relax();
lock_page(eb->first_page); lock_page(eb->first_page);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment