Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9efa9c7 authored by Chris Mason's avatar Chris Mason
Browse files

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
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -1313,16 +1313,13 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
				slot = p->slots[level];
				BUG_ON(btrfs_header_nritems(b) == 1);
			}
			unlock_up(p, level, lowest_unlock);

			/* this is only true while dropping a snapshot */
			if (level == lowest_level) {
				unlock_up(p, level, lowest_unlock);
				break;
			}

			if (should_reada)
				reada_for_search(root, p, level, slot,
						 key->objectid);

			blocknr = btrfs_node_blockptr(b, slot);
			gen = btrfs_node_ptr_generation(b, slot);
			blocksize = btrfs_level_size(root, level - 1);
@@ -1340,6 +1337,11 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
					btrfs_release_path(NULL, p);
					if (tmp)
						free_extent_buffer(tmp);
					if (should_reada)
						reada_for_search(root, p,
								 level, slot,
								 key->objectid);

					tmp = read_tree_block(root, blocknr,
							 blocksize, gen);
					if (tmp)
@@ -1348,12 +1350,15 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
				} else {
					if (tmp)
						free_extent_buffer(tmp);
					if (should_reada)
						reada_for_search(root, p,
								 level, slot,
								 key->objectid);
					b = read_node_slot(root, b, slot);
				}
			}
			if (!p->skip_locking)
				btrfs_tree_lock(b);
			unlock_up(p, level, lowest_unlock);
		} else {
			p->slots[level] = slot;
			if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
+10 −0
Original line number Diff line number Diff line
@@ -27,6 +27,16 @@

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);
	return 0;
}