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

Commit 7c9e6c17 authored by Alasdair G Kergon's avatar Alasdair G Kergon
Browse files

dm exception store: refactor zero_area



Use a separate buffer for writing zeroes to the on-disk snapshot
exception store, make the updating of ps->current_area explicit and
refactor the code in preparation for the fix in the next patch.

No functional change.

Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Cc: stable@kernel.org
parent f68d4f3d
Loading
Loading
Loading
Loading
+68 −34
Original line number Diff line number Diff line
@@ -104,6 +104,11 @@ struct pstore {
	 */
	void *area;

	/*
	 * An area of zeros used to clear the next area.
	 */
	void *zero_area;

	/*
	 * Used to keep track of which metadata area the data in
	 * 'chunk' refers to.
@@ -149,6 +154,13 @@ static int alloc_area(struct pstore *ps)
	if (!ps->area)
		return r;

	ps->zero_area = vmalloc(len);
	if (!ps->zero_area) {
		vfree(ps->area);
		return r;
	}
	memset(ps->zero_area, 0, len);

	return 0;
}

@@ -156,6 +168,8 @@ static void free_area(struct pstore *ps)
{
	vfree(ps->area);
	ps->area = NULL;
	vfree(ps->zero_area);
	ps->zero_area = NULL;
}

struct mdata_req {
@@ -220,25 +234,41 @@ static chunk_t area_location(struct pstore *ps, chunk_t area)
 * Read or write a metadata area.  Remembering to skip the first
 * chunk which holds the header.
 */
static int area_io(struct pstore *ps, chunk_t area, int rw)
static int area_io(struct pstore *ps, int rw)
{
	int r;
	chunk_t chunk;

	chunk = area_location(ps, area);
	chunk = area_location(ps, ps->current_area);

	r = chunk_io(ps, chunk, rw, 0);
	if (r)
		return r;

	ps->current_area = area;
	return 0;
}

static int zero_area(struct pstore *ps, chunk_t area)
static void zero_memory_area(struct pstore *ps)
{
	memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
	return area_io(ps, area, WRITE);
}

static int zero_disk_area(struct pstore *ps, chunk_t area)
{
	struct dm_io_region where = {
		.bdev = ps->snap->cow->bdev,
		.sector = ps->snap->chunk_size * area_location(ps, area),
		.count = ps->snap->chunk_size,
	};
	struct dm_io_request io_req = {
		.bi_rw = WRITE,
		.mem.type = DM_IO_VMA,
		.mem.ptr.vma = ps->zero_area,
		.client = ps->io_client,
		.notify.fn = NULL,
	};

	return dm_io(&io_req, 1, &where, NULL);
}

static int read_header(struct pstore *ps, int *new_snapshot)
@@ -411,15 +441,14 @@ static int insert_exceptions(struct pstore *ps, int *full)

static int read_exceptions(struct pstore *ps)
{
	chunk_t area;
	int r, full = 1;

	/*
	 * Keeping reading chunks and inserting exceptions until
	 * we find a partially full area.
	 */
	for (area = 0; full; area++) {
		r = area_io(ps, area, READ);
	for (ps->current_area = 0; full; ps->current_area++) {
		r = area_io(ps, READ);
		if (r)
			return r;

@@ -428,6 +457,8 @@ static int read_exceptions(struct pstore *ps)
			return r;
	}

	ps->current_area--;

	return 0;
}

@@ -486,12 +517,13 @@ static int persistent_read_metadata(struct exception_store *store)
			return r;
		}

		r = zero_area(ps, 0);
		ps->current_area = 0;
		zero_memory_area(ps);
		r = zero_disk_area(ps, 0);
		if (r) {
			DMWARN("zero_area(0) failed");
			DMWARN("zero_disk_area(0) failed");
			return r;
		}

	} else {
		/*
		 * Sanity checks.
@@ -551,7 +583,6 @@ static void persistent_commit(struct exception_store *store,
			      void (*callback) (void *, int success),
			      void *callback_context)
{
	int r;
	unsigned int i;
	struct pstore *ps = get_info(store);
	struct disk_exception de;
@@ -572,34 +603,37 @@ static void persistent_commit(struct exception_store *store,
	cb->context = callback_context;

	/*
	 * If there are no more exceptions in flight, or we have
	 * filled this metadata area we commit the exceptions to
	 * disk.
	 * If there are exceptions in flight and we have not yet
	 * filled this metadata area there's nothing more to do.
	 */
	if (atomic_dec_and_test(&ps->pending_count) ||
	    (ps->current_committed == ps->exceptions_per_area)) {
		r = area_io(ps, ps->current_area, WRITE);
		if (r)
	if (!atomic_dec_and_test(&ps->pending_count) &&
	    (ps->current_committed != ps->exceptions_per_area))
		return;

	/*
	 * Commit exceptions to disk.
	 */
	if (area_io(ps, WRITE))
		ps->valid = 0;

	/*
		 * Have we completely filled the current area ?
	 * Advance to the next area if this one is full.
	 */
	if (ps->current_committed == ps->exceptions_per_area) {
			ps->current_committed = 0;
			r = zero_area(ps, ps->current_area + 1);
			if (r)
		if (zero_disk_area(ps, ps->current_area + 1))
			ps->valid = 0;
		ps->current_committed = 0;
		ps->current_area++;
		zero_memory_area(ps);
	}

	for (i = 0; i < ps->callback_count; i++) {
		cb = ps->callbacks + i;
			cb->callback(cb->context, r == 0 ? 1 : 0);
		cb->callback(cb->context, ps->valid);
	}

	ps->callback_count = 0;
}
}

static void persistent_drop(struct exception_store *store)
{