Commit 33a18062 authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Mike Snitzer
Browse files

dm bufio: introduce forget_buffer_locked



Introduce a function forget_buffer_locked that forgets a range of
buffers. It is more efficient than calling forget_buffer in a loop.

Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 88f878e5
Loading
Loading
Loading
Loading
+56 −4
Original line number Diff line number Diff line
@@ -262,6 +262,29 @@ static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
	return NULL;
}

static struct dm_buffer *__find_next(struct dm_bufio_client *c, sector_t block)
{
	struct rb_node *n = c->buffer_tree.rb_node;
	struct dm_buffer *b;
	struct dm_buffer *best = NULL;

	while (n) {
		b = container_of(n, struct dm_buffer, node);

		if (b->block == block)
			return b;

		if (block <= b->block) {
			n = n->rb_left;
			best = b;
		} else {
			n = n->rb_right;
		}
	}

	return best;
}

static void __insert(struct dm_bufio_client *c, struct dm_buffer *b)
{
	struct rb_node **new = &c->buffer_tree.rb_node, *parent = NULL;
@@ -1434,6 +1457,14 @@ retry:
}
EXPORT_SYMBOL_GPL(dm_bufio_release_move);

static void forget_buffer_locked(struct dm_buffer *b)
{
	if (likely(!b->hold_count) && likely(!b->state)) {
		__unlink_buffer(b);
		__free_buffer_wake(b);
	}
}

/*
 * Free the given buffer.
 *
@@ -1447,15 +1478,36 @@ void dm_bufio_forget(struct dm_bufio_client *c, sector_t block)
	dm_bufio_lock(c);

	b = __find(c, block);
	if (b && likely(!b->hold_count) && likely(!b->state)) {
		__unlink_buffer(b);
		__free_buffer_wake(b);
	}
	if (b)
		forget_buffer_locked(b);

	dm_bufio_unlock(c);
}
EXPORT_SYMBOL_GPL(dm_bufio_forget);

void dm_bufio_forget_buffers(struct dm_bufio_client *c, sector_t block, sector_t n_blocks)
{
	struct dm_buffer *b;
	sector_t end_block = block + n_blocks;

	while (block < end_block) {
		dm_bufio_lock(c);

		b = __find_next(c, block);
		if (b) {
			block = b->block + 1;
			forget_buffer_locked(b);
		}

		dm_bufio_unlock(c);

		if (!b)
			break;
	}

}
EXPORT_SYMBOL_GPL(dm_bufio_forget_buffers);

void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n)
{
	c->minimum_buffers = n;
+7 −0
Original line number Diff line number Diff line
@@ -136,6 +136,13 @@ void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block);
 */
void dm_bufio_forget(struct dm_bufio_client *c, sector_t block);

/*
 * Free the given range of buffers.
 * This is just a hint, if the buffer is in use or dirty, this function
 * does nothing.
 */
void dm_bufio_forget_buffers(struct dm_bufio_client *c, sector_t block, sector_t n_blocks);

/*
 * Set the minimum number of buffers before cleanup happens.
 */