Commit 793955bc authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Limit btree writeback to prevent seeks

parent 015a739c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -210,6 +210,15 @@ 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) {
		u64 num_dirty;
		u64 start = 0;
		unsigned long thresh = 96 * 1024 * 1024;
		num_dirty = count_range_bits(tree, &start, thresh, EXTENT_DIRTY);
		if (num_dirty < thresh) {
			return 0;
		}
	}
	return extent_writepages(tree, mapping, btree_get_extent, wbc);
}

+39 −0
Original line number Diff line number Diff line
@@ -1106,6 +1106,45 @@ u64 find_lock_delalloc_range(struct extent_map_tree *tree,
	return found;
}

u64 count_range_bits(struct extent_map_tree *tree,
		     u64 *start, u64 max_bytes, unsigned long bits)
{
	struct rb_node *node;
	struct extent_state *state;
	u64 cur_start = *start;
	u64 total_bytes = 0;
	int found = 0;

	write_lock_irq(&tree->lock);
	/*
	 * this search will find all the extents that end after
	 * our range starts.
	 */
	node = tree_search(&tree->state, cur_start);
	if (!node || IS_ERR(node)) {
		goto out;
	}

	while(1) {
		state = rb_entry(node, struct extent_state, rb_node);
		if ((state->state & bits)) {
			total_bytes += state->end - state->start + 1;
			if (total_bytes >= max_bytes)
				break;
			if (!found) {
				*start = state->start;
				found = 1;
			}
		}
		node = rb_next(node);
		if (!node)
			break;
	}
out:
	write_unlock_irq(&tree->lock);
	return total_bytes;
}

/*
 * helper function to lock both pages and extents in the tree.
 * pages must be locked first.
+3 −0
Original line number Diff line number Diff line
@@ -113,6 +113,9 @@ int extent_read_full_page(struct extent_map_tree *tree, struct page *page,
int __init extent_map_init(void);
void __exit extent_map_exit(void);

u64 count_range_bits(struct extent_map_tree *tree,
		     u64 *start, u64 max_bytes, unsigned long bits);

int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end,
		   int bits, int filled);
int clear_extent_bits(struct extent_map_tree *tree, u64 start, u64 end,