mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-19 12:24:34 +08:00
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: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
3f157a2fd2
commit
f9efa9c784
@ -1313,16 +1313,13 @@ again:
|
|||||||
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 @@ again:
|
|||||||
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 @@ again:
|
|||||||
} 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 @@
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user