Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Linus Torvalds committed Oct 23, 2008
2 parents f2e4bd2 + 51157b4 commit 3e5cce6
Show file tree
Hide file tree
Showing 21 changed files with 1,084 additions and 798 deletions.
2 changes: 1 addition & 1 deletion drivers/md/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 $@
Expand Down
56 changes: 45 additions & 11 deletions drivers/md/dm-crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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)
{
Expand All @@ -555,7 +557,14 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
if (!atomic_dec_and_test(&io->pending))
return;

bio_endio(io->base_bio, io->error);
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);
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -741,6 +749,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
*/
if (unlikely(r < 0))
break;

io->sector = sector;
}

/*
Expand All @@ -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);
Expand Down Expand Up @@ -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;

Expand Down
3 changes: 2 additions & 1 deletion drivers/md/dm-delay.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
108 changes: 73 additions & 35 deletions drivers/md/dm-exception-store.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* This file is released under the GPL.
*/

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

#include <linux/mm.h>
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -149,13 +153,22 @@ 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;
}

static void free_area(struct pstore *ps)
{
vfree(ps->area);
ps->area = NULL;
vfree(ps->zero_area);
ps->zero_area = NULL;
}

struct mdata_req {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;

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

ps->current_area--;

return 0;
}

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand All @@ -572,33 +602,41 @@ 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)
ps->valid = 0;
if (!atomic_dec_and_test(&ps->pending_count) &&
(ps->current_committed != ps->exceptions_per_area))
return;

/*
* Have we completely filled the current area ?
*/
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;
}
/*
* 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;

for (i = 0; i < ps->callback_count; i++) {
cb = ps->callbacks + i;
cb->callback(cb->context, r == 0 ? 1 : 0);
}
/*
* Commit exceptions to disk.
*/
if (ps->valid && area_io(ps, WRITE))
ps->valid = 0;

ps->callback_count = 0;
/*
* Advance to the next area if this one is full.
*/
if (ps->current_committed == ps->exceptions_per_area) {
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, ps->valid);
}

ps->callback_count = 0;
}

static void persistent_drop(struct exception_store *store)
Expand Down
2 changes: 1 addition & 1 deletion drivers/md/dm-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Loading

0 comments on commit 3e5cce6

Please sign in to comment.