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

Btrfs: Add efficient dirty accounting to the extent_map tree

parent 448d640b
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -210,7 +210,7 @@ static int btree_writepages(struct address_space *mapping,
{
	struct extent_map_tree *tree;
	tree = &BTRFS_I(mapping->host)->extent_tree;
	if (wbc->sync_mode == WB_SYNC_NONE && current_is_pdflush()) {
	if (wbc->sync_mode == WB_SYNC_NONE) {
		u64 num_dirty;
		u64 start = 0;
		unsigned long thresh = 96 * 1024 * 1024;
@@ -218,6 +218,11 @@ static int btree_writepages(struct address_space *mapping,
		if (wbc->for_kupdate)
			return 0;

		if (current_is_pdflush()) {
			thresh = 96 * 1024 * 1024;
		} else {
			thresh = 8 * 1024 * 1024;
		}
		num_dirty = count_range_bits(tree, &start, thresh, EXTENT_DIRTY);
		if (num_dirty < thresh) {
			return 0;
+29 −3
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ struct extent_page_data {
	struct extent_map_tree *tree;
	get_extent_t *get_extent;
};

int __init extent_map_init(void)
{
	extent_map_cache = btrfs_cache_create("extent_map",
@@ -94,6 +95,7 @@ void extent_map_tree_init(struct extent_map_tree *tree,
	tree->map.rb_node = NULL;
	tree->state.rb_node = NULL;
	tree->ops = NULL;
	tree->dirty_bytes = 0;
	rwlock_init(&tree->lock);
	spin_lock_init(&tree->lru_lock);
	tree->mapping = mapping;
@@ -414,6 +416,8 @@ static int insert_state(struct extent_map_tree *tree,
		printk("end < start %Lu %Lu\n", end, start);
		WARN_ON(1);
	}
	if (bits & EXTENT_DIRTY)
		tree->dirty_bytes += end - start + 1;
	state->state |= bits;
	state->start = start;
	state->end = end;
@@ -476,6 +480,12 @@ static int clear_state_bit(struct extent_map_tree *tree,
			    int delete)
{
	int ret = state->state & bits;

	if ((bits & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {
		u64 range = state->end - state->start + 1;
		WARN_ON(range > tree->dirty_bytes);
		tree->dirty_bytes -= range;
	}
	state->state &= ~bits;
	if (wake)
		wake_up(&state->wq);
@@ -668,6 +678,17 @@ int wait_extent_bit(struct extent_map_tree *tree, u64 start, u64 end, int bits)
}
EXPORT_SYMBOL(wait_extent_bit);

static void set_state_bits(struct extent_map_tree *tree,
			   struct extent_state *state,
			   int bits)
{
	if ((bits & EXTENT_DIRTY) && !(state->state & EXTENT_DIRTY)) {
		u64 range = state->end - state->start + 1;
		tree->dirty_bytes += range;
	}
	state->state |= bits;
}

/*
 * set some bits on a range in the tree.  This may require allocations
 * or sleeping, so the gfp mask is used to indicate what is allowed.
@@ -727,7 +748,7 @@ int set_extent_bit(struct extent_map_tree *tree, u64 start, u64 end, int bits,
			err = -EEXIST;
			goto out;
		}
		state->state |= bits;
		set_state_bits(tree, state, bits);
		start = state->end + 1;
		merge_state(tree, state);
		goto search_again;
@@ -762,7 +783,7 @@ int set_extent_bit(struct extent_map_tree *tree, u64 start, u64 end, int bits,
		if (err)
			goto out;
		if (state->end <= end) {
			state->state |= bits;
			set_state_bits(tree, state, bits);
			start = state->end + 1;
			merge_state(tree, state);
		} else {
@@ -808,7 +829,7 @@ int set_extent_bit(struct extent_map_tree *tree, u64 start, u64 end, int bits,
		err = split_state(tree, state, prealloc, end + 1);
		BUG_ON(err == -EEXIST);

		prealloc->state |= bits;
		set_state_bits(tree, prealloc, bits);
		merge_state(tree, prealloc);
		prealloc = NULL;
		goto out;
@@ -1116,6 +1137,11 @@ u64 count_range_bits(struct extent_map_tree *tree,
	int found = 0;

	write_lock_irq(&tree->lock);
	if (bits == EXTENT_DIRTY) {
		*start = 0;
		total_bytes = tree->dirty_bytes;
		goto out;
	}
	/*
	 * this search will find all the extents that end after
	 * our range starts.
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ struct extent_map_tree {
	struct rb_root map;
	struct rb_root state;
	struct address_space *mapping;
	u64 dirty_bytes;
	rwlock_t lock;
	struct extent_map_ops *ops;
	spinlock_t lru_lock;