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

Commit 3e5cce62 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm:
  dm: tidy local_init
  dm: remove unused flush_all
  dm raid1: separate region_hash interface part1
  dm: mark split bio as cloned
  dm crypt: remove waitqueue
  dm crypt: fix async split
  dm crypt: tidy sector
  dm: remove dm header from targets
  dm: publish array_too_big
  dm exception store: fix misordered writes
  dm exception store: refactor zero_area
  dm snapshot: drop unused last_percent
  dm snapshot: fix primary_pe race
  dm kcopyd: avoid queue shuffle
parents f2e4bd2b 51157b4a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o dm-log.o
obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o dm-log.o dm-region-hash.o
obj-$(CONFIG_DM_ZERO)		+= dm-zero.o

quiet_cmd_unroll = UNROLL  $@
+45 −11
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@
#include <asm/page.h>
#include <asm/unaligned.h>

#include "dm.h"
#include <linux/device-mapper.h>

#define DM_MSG_PREFIX "crypt"
#define MESG_STR(x) x, sizeof(x)
@@ -56,6 +56,7 @@ struct dm_crypt_io {
	atomic_t pending;
	int error;
	sector_t sector;
	struct dm_crypt_io *base_io;
};

struct dm_crypt_request {
@@ -93,7 +94,6 @@ struct crypt_config {

	struct workqueue_struct *io_queue;
	struct workqueue_struct *crypt_queue;
	wait_queue_head_t writeq;

	/*
	 * crypto related data
@@ -534,6 +534,7 @@ static struct dm_crypt_io *crypt_io_alloc(struct dm_target *ti,
	io->base_bio = bio;
	io->sector = sector;
	io->error = 0;
	io->base_io = NULL;
	atomic_set(&io->pending, 0);

	return io;
@@ -547,6 +548,7 @@ static void crypt_inc_pending(struct dm_crypt_io *io)
/*
 * One of the bios was finished. Check for completion of
 * the whole request and correctly clean up the buffer.
 * If base_io is set, wait for the last fragment to complete.
 */
static void crypt_dec_pending(struct dm_crypt_io *io)
{
@@ -555,7 +557,14 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
	if (!atomic_dec_and_test(&io->pending))
		return;

	if (likely(!io->base_io))
		bio_endio(io->base_bio, io->error);
	else {
		if (io->error && !io->base_io->error)
			io->base_io->error = io->error;
		crypt_dec_pending(io->base_io);
	}

	mempool_free(io, cc->io_pool);
}

@@ -646,10 +655,7 @@ static void kcryptd_io_read(struct dm_crypt_io *io)
static void kcryptd_io_write(struct dm_crypt_io *io)
{
	struct bio *clone = io->ctx.bio_out;
	struct crypt_config *cc = io->target->private;

	generic_make_request(clone);
	wake_up(&cc->writeq);
}

static void kcryptd_io(struct work_struct *work)
@@ -688,7 +694,6 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
	BUG_ON(io->ctx.idx_out < clone->bi_vcnt);

	clone->bi_sector = cc->start + io->sector;
	io->sector += bio_sectors(clone);

	if (async)
		kcryptd_queue_io(io);
@@ -700,16 +705,18 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
{
	struct crypt_config *cc = io->target->private;
	struct bio *clone;
	struct dm_crypt_io *new_io;
	int crypt_finished;
	unsigned out_of_pages = 0;
	unsigned remaining = io->base_bio->bi_size;
	sector_t sector = io->sector;
	int r;

	/*
	 * Prevent io from disappearing until this function completes.
	 */
	crypt_inc_pending(io);
	crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector);
	crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, sector);

	/*
	 * The allocated buffers can be smaller than the whole bio,
@@ -726,6 +733,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
		io->ctx.idx_out = 0;

		remaining -= clone->bi_size;
		sector += bio_sectors(clone);

		crypt_inc_pending(io);
		r = crypt_convert(cc, &io->ctx);
@@ -741,6 +749,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
			 */
			if (unlikely(r < 0))
				break;

			io->sector = sector;
		}

		/*
@@ -750,8 +760,33 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
		if (unlikely(out_of_pages))
			congestion_wait(WRITE, HZ/100);

		if (unlikely(remaining))
			wait_event(cc->writeq, !atomic_read(&io->ctx.pending));
		/*
		 * With async crypto it is unsafe to share the crypto context
		 * between fragments, so switch to a new dm_crypt_io structure.
		 */
		if (unlikely(!crypt_finished && remaining)) {
			new_io = crypt_io_alloc(io->target, io->base_bio,
						sector);
			crypt_inc_pending(new_io);
			crypt_convert_init(cc, &new_io->ctx, NULL,
					   io->base_bio, sector);
			new_io->ctx.idx_in = io->ctx.idx_in;
			new_io->ctx.offset_in = io->ctx.offset_in;

			/*
			 * Fragments after the first use the base_io
			 * pending count.
			 */
			if (!io->base_io)
				new_io->base_io = io;
			else {
				new_io->base_io = io->base_io;
				crypt_inc_pending(io->base_io);
				crypt_dec_pending(io);
			}

			io = new_io;
		}
	}

	crypt_dec_pending(io);
@@ -1078,7 +1113,6 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
		goto bad_crypt_queue;
	}

	init_waitqueue_head(&cc->writeq);
	ti->private = cc;
	return 0;

+2 −1
Original line number Diff line number Diff line
@@ -13,7 +13,8 @@
#include <linux/bio.h>
#include <linux/slab.h>

#include "dm.h"
#include <linux/device-mapper.h>

#include "dm-bio-list.h"

#define DM_MSG_PREFIX "delay"
+73 −35
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@
 * This file is released under the GPL.
 */

#include "dm.h"
#include "dm-snap.h"

#include <linux/mm.h>
@@ -104,6 +103,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 +153,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 +167,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 +233,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 +440,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 +456,8 @@ static int read_exceptions(struct pstore *ps)
			return r;
	}

	ps->current_area--;

	return 0;
}

@@ -486,12 +516,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 +582,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 +602,42 @@ 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;

	/*
	 * If we completely filled the current area, then wipe the next one.
	 */
	if ((ps->current_committed == ps->exceptions_per_area) &&
	     zero_disk_area(ps, ps->current_area + 1))
		ps->valid = 0;

	/*
	 * Commit exceptions to disk.
	 */
	if (ps->valid && 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)
				ps->valid = 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)
{
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 * This file is released under the GPL.
 */

#include "dm.h"
#include <linux/device-mapper.h>

#include <linux/bio.h>
#include <linux/mempool.h>
Loading