Commit 6f97b220 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm

* git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm: (24 commits)
  dm crypt: add documentation
  dm: remove md argument from specific_minor
  dm table: remove unused dm_create_error_table
  dm table: drop void suspend_targets return
  dm: unplug queues in threads
  dm raid1: use timer
  dm: move include files
  dm kcopyd: rename
  dm: expose macros
  dm kcopyd: remove redundant client counting
  dm kcopyd: private mempool
  dm kcopyd: per device
  dm log: make module use tracking internal
  dm log: move register functions
  dm log: clean interface
  dm kcopyd: clean interface
  dm io: clean interface
  dm io: rename error to error_bits
  dm snapshot: store pointer to target instance
  dm log: move dirty region log code into separate module
  ...
parents 4b7227ca e3dcc5a3
dm-crypt
=========
Device-Mapper's "crypt" target provides transparent encryption of block devices
using the kernel crypto API.
Parameters: <cipher> <key> <iv_offset> <device path> <offset>
<cipher>
Encryption cipher and an optional IV generation mode.
(In format cipher-chainmode-ivopts:ivmode).
Examples:
des
aes-cbc-essiv:sha256
twofish-ecb
/proc/crypto contains supported crypto modes
<key>
Key used for encryption. It is encoded as a hexadecimal number.
You can only use key sizes that are valid for the selected cipher.
<iv_offset>
The IV offset is a sector count that is added to the sector number
before creating the IV.
<device path>
This is the device that is going to be used as backend and contains the
encrypted data. You can specify it as a path like /dev/xxx or a device
number <major>:<minor>.
<offset>
Starting sector within the device where the encrypted data begins.
Example scripts
===============
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
encryption with dm-crypt using the 'cryptsetup' utility, see
http://luks.endorphin.org/
[[
#!/bin/sh
# Create a crypt device using dmsetup
dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
]]
[[
#!/bin/sh
# Create a crypt device using cryptsetup and LUKS header with default cipher
cryptsetup luksFormat $1
cryptsetup luksOpen $1 crypt1
]]
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
# #
dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
dm-ioctl.o dm-io.o kcopyd.o dm-ioctl.o dm-io.o dm-kcopyd.o
dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-snapshot-objs := dm-snap.o dm-exception-store.o
dm-mirror-objs := dm-log.o dm-raid1.o dm-mirror-objs := dm-raid1.o
dm-rdac-objs := dm-mpath-rdac.o dm-rdac-objs := dm-mpath-rdac.o
dm-hp-sw-objs := dm-mpath-hp-sw.o dm-hp-sw-objs := dm-mpath-hp-sw.o
md-mod-objs := md.o bitmap.o md-mod-objs := md.o bitmap.o
...@@ -39,7 +39,7 @@ obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o ...@@ -39,7 +39,7 @@ obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
obj-$(CONFIG_DM_MULTIPATH_HP) += dm-hp-sw.o obj-$(CONFIG_DM_MULTIPATH_HP) += dm-hp-sw.o
obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o obj-$(CONFIG_DM_ZERO) += dm-zero.o
quiet_cmd_unroll = UNROLL $@ quiet_cmd_unroll = UNROLL $@
......
...@@ -9,13 +9,13 @@ ...@@ -9,13 +9,13 @@
#include "dm.h" #include "dm.h"
#include "dm-snap.h" #include "dm-snap.h"
#include "dm-io.h"
#include "kcopyd.h"
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dm-io.h>
#include <linux/dm-kcopyd.h>
#define DM_MSG_PREFIX "snapshots" #define DM_MSG_PREFIX "snapshots"
#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */ #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
...@@ -131,7 +131,7 @@ struct pstore { ...@@ -131,7 +131,7 @@ struct pstore {
static unsigned sectors_to_pages(unsigned sectors) static unsigned sectors_to_pages(unsigned sectors)
{ {
return sectors / (PAGE_SIZE >> 9); return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
} }
static int alloc_area(struct pstore *ps) static int alloc_area(struct pstore *ps)
...@@ -159,7 +159,7 @@ static void free_area(struct pstore *ps) ...@@ -159,7 +159,7 @@ static void free_area(struct pstore *ps)
} }
struct mdata_req { struct mdata_req {
struct io_region *where; struct dm_io_region *where;
struct dm_io_request *io_req; struct dm_io_request *io_req;
struct work_struct work; struct work_struct work;
int result; int result;
...@@ -177,7 +177,7 @@ static void do_metadata(struct work_struct *work) ...@@ -177,7 +177,7 @@ static void do_metadata(struct work_struct *work)
*/ */
static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata) static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
{ {
struct io_region where = { struct dm_io_region where = {
.bdev = ps->snap->cow->bdev, .bdev = ps->snap->cow->bdev,
.sector = ps->snap->chunk_size * chunk, .sector = ps->snap->chunk_size * chunk,
.count = ps->snap->chunk_size, .count = ps->snap->chunk_size,
......
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
* This file is released under the GPL. * This file is released under the GPL.
*/ */
#include "dm-io.h" #include "dm.h"
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/mempool.h> #include <linux/mempool.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dm-io.h>
struct dm_io_client { struct dm_io_client {
mempool_t *pool; mempool_t *pool;
...@@ -20,7 +21,7 @@ struct dm_io_client { ...@@ -20,7 +21,7 @@ struct dm_io_client {
/* FIXME: can we shrink this ? */ /* FIXME: can we shrink this ? */
struct io { struct io {
unsigned long error; unsigned long error_bits;
atomic_t count; atomic_t count;
struct task_struct *sleeper; struct task_struct *sleeper;
struct dm_io_client *client; struct dm_io_client *client;
...@@ -107,14 +108,14 @@ static inline unsigned bio_get_region(struct bio *bio) ...@@ -107,14 +108,14 @@ static inline unsigned bio_get_region(struct bio *bio)
static void dec_count(struct io *io, unsigned int region, int error) static void dec_count(struct io *io, unsigned int region, int error)
{ {
if (error) if (error)
set_bit(region, &io->error); set_bit(region, &io->error_bits);
if (atomic_dec_and_test(&io->count)) { if (atomic_dec_and_test(&io->count)) {
if (io->sleeper) if (io->sleeper)
wake_up_process(io->sleeper); wake_up_process(io->sleeper);
else { else {
unsigned long r = io->error; unsigned long r = io->error_bits;
io_notify_fn fn = io->callback; io_notify_fn fn = io->callback;
void *context = io->context; void *context = io->context;
...@@ -271,7 +272,7 @@ static void km_dp_init(struct dpages *dp, void *data) ...@@ -271,7 +272,7 @@ static void km_dp_init(struct dpages *dp, void *data)
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
* IO routines that accept a list of pages. * IO routines that accept a list of pages.
*---------------------------------------------------------------*/ *---------------------------------------------------------------*/
static void do_region(int rw, unsigned int region, struct io_region *where, static void do_region(int rw, unsigned region, struct dm_io_region *where,
struct dpages *dp, struct io *io) struct dpages *dp, struct io *io)
{ {
struct bio *bio; struct bio *bio;
...@@ -320,7 +321,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where, ...@@ -320,7 +321,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
} }
static void dispatch_io(int rw, unsigned int num_regions, static void dispatch_io(int rw, unsigned int num_regions,
struct io_region *where, struct dpages *dp, struct dm_io_region *where, struct dpages *dp,
struct io *io, int sync) struct io *io, int sync)
{ {
int i; int i;
...@@ -347,17 +348,17 @@ static void dispatch_io(int rw, unsigned int num_regions, ...@@ -347,17 +348,17 @@ static void dispatch_io(int rw, unsigned int num_regions,
} }
static int sync_io(struct dm_io_client *client, unsigned int num_regions, static int sync_io(struct dm_io_client *client, unsigned int num_regions,
struct io_region *where, int rw, struct dpages *dp, struct dm_io_region *where, int rw, struct dpages *dp,
unsigned long *error_bits) unsigned long *error_bits)
{ {
struct io io; struct io io;
if (num_regions > 1 && rw != WRITE) { if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
WARN_ON(1); WARN_ON(1);
return -EIO; return -EIO;
} }
io.error = 0; io.error_bits = 0;
atomic_set(&io.count, 1); /* see dispatch_io() */ atomic_set(&io.count, 1); /* see dispatch_io() */
io.sleeper = current; io.sleeper = current;
io.client = client; io.client = client;
...@@ -378,25 +379,25 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, ...@@ -378,25 +379,25 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
return -EINTR; return -EINTR;
if (error_bits) if (error_bits)
*error_bits = io.error; *error_bits = io.error_bits;
return io.error ? -EIO : 0; return io.error_bits ? -EIO : 0;
} }
static int async_io(struct dm_io_client *client, unsigned int num_regions, static int async_io(struct dm_io_client *client, unsigned int num_regions,
struct io_region *where, int rw, struct dpages *dp, struct dm_io_region *where, int rw, struct dpages *dp,
io_notify_fn fn, void *context) io_notify_fn fn, void *context)
{ {
struct io *io; struct io *io;
if (num_regions > 1 && rw != WRITE) { if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
WARN_ON(1); WARN_ON(1);
fn(1, context); fn(1, context);
return -EIO; return -EIO;
} }
io = mempool_alloc(client->pool, GFP_NOIO); io = mempool_alloc(client->pool, GFP_NOIO);
io->error = 0; io->error_bits = 0;
atomic_set(&io->count, 1); /* see dispatch_io() */ atomic_set(&io->count, 1); /* see dispatch_io() */
io->sleeper = NULL; io->sleeper = NULL;
io->client = client; io->client = client;
...@@ -435,10 +436,15 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp) ...@@ -435,10 +436,15 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp)
} }
/* /*
* New collapsed (a)synchronous interface * New collapsed (a)synchronous interface.
*
* If the IO is asynchronous (i.e. it has notify.fn), you must either unplug
* the queue with blk_unplug() some time later or set the BIO_RW_SYNC bit in
* io_req->bi_rw. If you fail to do one of these, the IO will be submitted to
* the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c.
*/ */
int dm_io(struct dm_io_request *io_req, unsigned num_regions, int dm_io(struct dm_io_request *io_req, unsigned num_regions,
struct io_region *where, unsigned long *sync_error_bits) struct dm_io_region *where, unsigned long *sync_error_bits)
{ {
int r; int r;
struct dpages dp; struct dpages dp;
......
This diff is collapsed.
This diff is collapsed.
...@@ -18,10 +18,10 @@ ...@@ -18,10 +18,10 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/dm-kcopyd.h>
#include "dm-snap.h" #include "dm-snap.h"
#include "dm-bio-list.h" #include "dm-bio-list.h"
#include "kcopyd.h"
#define DM_MSG_PREFIX "snapshots" #define DM_MSG_PREFIX "snapshots"
...@@ -36,9 +36,9 @@ ...@@ -36,9 +36,9 @@
#define SNAPSHOT_COPY_PRIORITY 2 #define SNAPSHOT_COPY_PRIORITY 2
/* /*
* Each snapshot reserves this many pages for io * Reserve 1MB for each snapshot initially (with minimum of 1 page).
*/ */
#define SNAPSHOT_PAGES 256 #define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1)
static struct workqueue_struct *ksnapd; static struct workqueue_struct *ksnapd;
static void flush_queued_bios(struct work_struct *work); static void flush_queued_bios(struct work_struct *work);
...@@ -536,7 +536,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -536,7 +536,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
s->last_percent = 0; s->last_percent = 0;
init_rwsem(&s->lock); init_rwsem(&s->lock);
spin_lock_init(&s->pe_lock); spin_lock_init(&s->pe_lock);
s->table = ti->table; s->ti = ti;
/* Allocate hash table for COW data */ /* Allocate hash table for COW data */
if (init_hash_tables(s)) { if (init_hash_tables(s)) {
...@@ -558,7 +558,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -558,7 +558,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad4; goto bad4;
} }
r = kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client); r = dm_kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
if (r) { if (r) {
ti->error = "Could not create kcopyd client"; ti->error = "Could not create kcopyd client";
goto bad5; goto bad5;
...@@ -591,7 +591,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -591,7 +591,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return 0; return 0;
bad6: bad6:
kcopyd_client_destroy(s->kcopyd_client); dm_kcopyd_client_destroy(s->kcopyd_client);
bad5: bad5:
s->store.destroy(&s->store); s->store.destroy(&s->store);
...@@ -613,7 +613,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -613,7 +613,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
static void __free_exceptions(struct dm_snapshot *s) static void __free_exceptions(struct dm_snapshot *s)
{ {
kcopyd_client_destroy(s->kcopyd_client); dm_kcopyd_client_destroy(s->kcopyd_client);
s->kcopyd_client = NULL; s->kcopyd_client = NULL;
exit_exception_table(&s->pending, pending_cache); exit_exception_table(&s->pending, pending_cache);
...@@ -699,7 +699,7 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err) ...@@ -699,7 +699,7 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
s->valid = 0; s->valid = 0;
dm_table_event(s->table); dm_table_event(s->ti->table);
} }
static void get_pending_exception(struct dm_snap_pending_exception *pe) static void get_pending_exception(struct dm_snap_pending_exception *pe)
...@@ -824,7 +824,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context) ...@@ -824,7 +824,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
static void start_copy(struct dm_snap_pending_exception *pe) static void start_copy(struct dm_snap_pending_exception *pe)
{ {
struct dm_snapshot *s = pe->snap; struct dm_snapshot *s = pe->snap;
struct io_region src, dest; struct dm_io_region src, dest;
struct block_device *bdev = s->origin->bdev; struct block_device *bdev = s->origin->bdev;
sector_t dev_size; sector_t dev_size;
...@@ -839,7 +839,7 @@ static void start_copy(struct dm_snap_pending_exception *pe) ...@@ -839,7 +839,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
dest.count = src.count; dest.count = src.count;
/* Hand over to kcopyd */ /* Hand over to kcopyd */
kcopyd_copy(s->kcopyd_client, dm_kcopyd_copy(s->kcopyd_client,
&src, 1, &dest, 0, copy_callback, pe); &src, 1, &dest, 0, copy_callback, pe);
} }
...@@ -1060,7 +1060,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) ...@@ -1060,7 +1060,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
goto next_snapshot; goto next_snapshot;
/* Nothing to do if writing beyond end of snapshot */ /* Nothing to do if writing beyond end of snapshot */
if (bio->bi_sector >= dm_table_get_size(snap->table)) if (bio->bi_sector >= dm_table_get_size(snap->ti->table))
goto next_snapshot; goto next_snapshot;
/* /*
......
...@@ -132,7 +132,7 @@ struct exception_store { ...@@ -132,7 +132,7 @@ struct exception_store {
struct dm_snapshot { struct dm_snapshot {
struct rw_semaphore lock; struct rw_semaphore lock;
struct dm_table *table; struct dm_target *ti;
struct dm_dev *origin; struct dm_dev *origin;
struct dm_dev *cow; struct dm_dev *cow;
...@@ -169,7 +169,7 @@ struct dm_snapshot { ...@@ -169,7 +169,7 @@ struct dm_snapshot {
/* The on disk metadata handler */ /* The on disk metadata handler */
struct exception_store store; struct exception_store store;
struct kcopyd_client *kcopyd_client; struct dm_kcopyd_client *kcopyd_client;
/* Queue of snapshot writes for ksnapd to flush */ /* Queue of snapshot writes for ksnapd to flush */
struct bio_list queued_bios; struct bio_list queued_bios;
......
...@@ -245,44 +245,6 @@ int dm_table_create(struct dm_table **result, int mode, ...@@ -245,44 +245,6 @@ int dm_table_create(struct dm_table **result, int mode,
return 0; return 0;
} }
int dm_create_error_table(struct dm_table **result, struct mapped_device *md)
{
struct dm_table *t;
sector_t dev_size = 1;
int r;
/*
* Find current size of device.
* Default to 1 sector if inactive.
*/
t = dm_get_table(md);
if (t) {
dev_size = dm_table_get_size(t);
dm_table_put(t);
}
r = dm_table_create(&t, FMODE_READ, 1, md);
if (r)
return r;
r = dm_table_add_target(t, "error", 0, dev_size, NULL);
if (r)
goto out;
r = dm_table_complete(t);
if (r)
goto out;
*result = t;
out:
if (r)
dm_table_put(t);
return r;
}
EXPORT_SYMBOL_GPL(dm_create_error_table);
static void free_devices(struct list_head *devices) static void free_devices(struct list_head *devices)
{ {
struct list_head *tmp, *next; struct list_head *tmp, *next;
...@@ -954,7 +916,7 @@ void dm_table_presuspend_targets(struct dm_table *t) ...@@ -954,7 +916,7 @@ void dm_table_presuspend_targets(struct dm_table *t)
if (!t) if (!t)
return; return;
return suspend_targets(t, 0); suspend_targets(t, 0);
} }
void dm_table_postsuspend_targets(struct dm_table *t) void dm_table_postsuspend_targets(struct dm_table *t)
...@@ -962,7 +924,7 @@ void dm_table_postsuspend_targets(struct dm_table *t) ...@@ -962,7 +924,7 @@ void dm_table_postsuspend_targets(struct dm_table *t)
if (!t) if (!t)
return; return;
return suspend_targets(t, 1); suspend_targets(t, 1);
} }
int dm_table_resume_targets(struct dm_table *t) int dm_table_resume_targets(struct dm_table *t)
......
...@@ -204,6 +204,7 @@ static int (*_inits[])(void) __initdata = { ...@@ -204,6 +204,7 @@ static int (*_inits[])(void) __initdata = {
dm_target_init, dm_target_init,
dm_linear_init, dm_linear_init,
dm_stripe_init, dm_stripe_init,
dm_kcopyd_init,
dm_interface_init, dm_interface_init,
}; };
...@@ -212,6 +213,7 @@ static void (*_exits[])(void) = { ...@@ -212,6 +213,7 @@ static void (*_exits[])(void) = {
dm_target_exit, dm_target_exit,
dm_linear_exit, dm_linear_exit,
dm_stripe_exit, dm_stripe_exit,
dm_kcopyd_exit,
dm_interface_exit, dm_interface_exit,
}; };
...@@ -922,7 +924,7 @@ static void free_minor(int minor) ...@@ -922,7 +924,7 @@ static void free_minor(int minor)
/* /*
* See if the device with a specific minor # is free. * See if the device with a specific minor # is free.
*/ */
static int specific_minor(struct mapped_device *md, int minor) static int specific_minor(int minor)
{ {
int r, m; int r, m;
...@@ -955,7 +957,7 @@ out: ...@@ -955,7 +957,7 @@ out:
return r; return r;
} }
static int next_free_minor(struct mapped_device *md, int *minor) static int next_free_minor(int *minor)
{ {
int r, m; int r, m;
...@@ -966,9 +968,8 @@ static int next_free_minor(struct mapped_device *md, int *minor) ...@@ -966,9 +968,8 @@ static int next_free_minor(struct mapped_device *md, int *minor)
spin_lock(&_minor_lock); spin_lock(&_minor_lock);
r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m); r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
if (r) { if (r)
goto out; goto out;
}
if (m >= (1 << MINORBITS)) { if (m >= (1 << MINORBITS)) {
idr_remove(&_minor_idr, m); idr_remove(&_minor_idr, m);
...@@ -991,7 +992,7 @@ static struct block_device_operations dm_blk_dops; ...@@ -991,7 +992,7 @@ static struct block_device_operations dm_blk_dops;
static struct mapped_device *alloc_dev(int minor) static struct mapped_device *alloc_dev(int minor)
{ {
int r; int r;
struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL); struct mapped_device *md = kzalloc(sizeof(*md), GFP_KERNEL);
void *old_md; void *old_md;
if (!md) { if (!md) {
...@@ -1004,13 +1005,12 @@ static struct mapped_device *alloc_dev(int minor) ...@@ -1004,13 +1005,12 @@ static struct mapped_device *alloc_dev(int minor)
/* get a minor number for the dev */ /* get a minor number for the dev */
if (minor == DM_ANY_MINOR) if (minor == DM_ANY_MINOR)
r = next_free_minor(md, &minor); r = next_free_minor(&minor);
else else
r = specific_minor(md, minor); r = specific_minor(minor);
if (r < 0) if (r < 0)
goto bad_minor; goto bad_minor;
memset(md, 0, sizeof(*md));
init_rwsem(&md->io_lock); init_rwsem(&md->io_lock);
mutex_init(&md->suspend_lock); mutex_init(&md->suspend_lock);
spin_lock_init(&md->pushback_lock); spin_lock_init(&md->pushback_lock);
......
...@@ -16,67 +16,6 @@ ...@@ -16,67 +16,6 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#define DM_NAME "device-mapper"
#define DMERR(f, arg...) \
printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
#define DMERR_LIMIT(f, arg...) \
do { \
if (printk_ratelimit()) \
printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
f "\n", ## arg); \
} while (0)
#define DMWARN(f, arg...) \
printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
#define DMWARN_LIMIT(f, arg...) \
do { \
if (printk_ratelimit()) \
printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
f "\n", ## arg); \
} while (0)
#define DMINFO(f, arg...) \
printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
#define DMINFO_LIMIT(f, arg...) \
do { \
if (printk_ratelimit()) \
printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
"\n", ## arg); \
} while (0)
#ifdef CONFIG_DM_DEBUG
# define DMDEBUG(f, arg...) \
printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
# define DMDEBUG_LIMIT(f, arg...) \
do { \
if (printk_ratelimit()) \
printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
"\n", ## arg); \
} while (0)
#else
# define DMDEBUG(f, arg...) do {} while (0)
# define DMDEBUG_LIMIT(f, arg...) do {} while (0)
#endif
#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
0 : scnprintf(result + sz, maxlen - sz, x))
#define SECTOR_SHIFT 9
/*
* Definitions of return values from target end_io function.
*/
#define DM_ENDIO_INCOMPLETE 1
#define DM_ENDIO_REQUEUE 2
/*
* Definitions of return values from target map function.
*/
#define DM_MAPIO_SUBMITTED 0
#define DM_MAPIO_REMAPPED 1
#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE
/* /*
* Suspend feature flags * Suspend feature flags
*/ */
...@@ -136,34 +75,6 @@ static inline int array_too_big(unsigned long fixed, unsigned long obj, ...@@ -136,34 +75,6 @@ static inline int array_too_big(unsigned long fixed, unsigned long obj,
return (num > (ULONG_MAX - fixed) / obj); return (num > (ULONG_MAX - fixed) / obj);
} }
/*
* Ceiling(n / sz)
*/
#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
#define dm_sector_div_up(n, sz) ( \
{ \
sector_t _r = ((n) + (sz) - 1); \
sector_div(_r, (sz)); \
_r; \
} \
)
/*
* ceiling(n / size) * size
*/
#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
static inline sector_t to_sector(unsigned long n)
{
return (n >> 9);
}
static inline unsigned long to_bytes(sector_t n)
{
return (n << 9);
}
int dm_split_args(int *argc, char ***argvp, char *input); int dm_split_args(int *argc, char ***argvp, char *input);
/* /*
...@@ -189,4 +100,13 @@ int dm_lock_for_deletion(struct mapped_device *md); ...@@ -189,4 +100,13 @@ int dm_lock_for_deletion(struct mapped_device *md);
void dm_kobject_uevent(struct mapped_device *md); void dm_kobject_uevent(struct mapped_device *md);
/*
* Dirty log
*/
int dm_dirty_log_init(void);
void dm_dirty_log_exit(void);
int dm_kcopyd_init(void);
void dm_kcopyd_exit(void);
#endif #endif
/*
* Copyright (C) 2001 Sistina Software
*
* This file is released under the GPL.
*
* Kcopyd provides a simple interface for copying an area of one
* block-device to one or more other block-devices, with an asynchronous
* completion notification.
*/
#ifndef DM_KCOPYD_H
#define DM_KCOPYD_H
#include "dm-io.h"
/* FIXME: make this configurable */
#define KCOPYD_MAX_REGIONS 8
#define KCOPYD_IGNORE_ERROR 1
/*
* To use kcopyd you must first create a kcopyd client object.
*/
struct kcopyd_client;
int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result);
void kcopyd_client_destroy(struct kcopyd_client *kc);
/*
* Submit a copy job to kcopyd. This is built on top of the
* previous three fns.
*
* read_err is a boolean,
* write_err is a bitset, with 1 bit for each destination region
*/
typedef void (*kcopyd_notify_fn)(int read_err, unsigned long write_err,
void *context);
int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
unsigned int num_dests, struct io_region *dests,
unsigned int flags, kcopyd_notify_fn fn, void *context);
#endif
/* /*
* Copyright (C) 2001 Sistina Software (UK) Limited. * Copyright (C) 2001 Sistina Software (UK) Limited.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
* *
* This file is released under the LGPL. * This file is released under the LGPL.
*/ */
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/bio.h>
struct dm_target; struct dm_target;
struct dm_table; struct dm_table;
struct dm_dev; struct dm_dev;
...@@ -250,11 +252,97 @@ void dm_table_event(struct dm_table *t); ...@@ -250,11 +252,97 @@ void dm_table_event(struct dm_table *t);
*/ */
int dm_swap_table(struct mapped_device *md, struct dm_table *t); int dm_swap_table(struct mapped_device *md, struct dm_table *t);
/*-----------------------------------------------------------------
* Macros.
*---------------------------------------------------------------*/
#define DM_NAME "device-mapper"
#define DMERR(f, arg...) \
printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
#define DMERR_LIMIT(f, arg...) \
do { \
if (printk_ratelimit()) \
printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
f "\n", ## arg); \
} while (0)
#define DMWARN(f, arg...) \
printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
#define DMWARN_LIMIT(f, arg...) \
do { \
if (printk_ratelimit()) \
printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
f "\n", ## arg); \
} while (0)
#define DMINFO(f, arg...) \
printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
#define DMINFO_LIMIT(f, arg...) \
do { \
if (printk_ratelimit()) \
printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
"\n", ## arg); \
} while (0)
#ifdef CONFIG_DM_DEBUG
# define DMDEBUG(f, arg...) \
printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
# define DMDEBUG_LIMIT(f, arg...) \
do { \
if (printk_ratelimit()) \
printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
"\n", ## arg); \
} while (0)
#else
# define DMDEBUG(f, arg...) do {} while (0)
# define DMDEBUG_LIMIT(f, arg...) do {} while (0)
#endif
#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
0 : scnprintf(result + sz, maxlen - sz, x))
#define SECTOR_SHIFT 9
/*
* Definitions of return values from target end_io function.
*/
#define DM_ENDIO_INCOMPLETE 1
#define DM_ENDIO_REQUEUE 2
/*
* Definitions of return values from target map function.
*/
#define DM_MAPIO_SUBMITTED 0
#define DM_MAPIO_REMAPPED 1
#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE
/*
* Ceiling(n / sz)
*/
#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
#define dm_sector_div_up(n, sz) ( \
{ \
sector_t _r = ((n) + (sz) - 1); \
sector_div(_r, (sz)); \
_r; \
} \
)
/* /*
* Prepare a table for a device that will error all I/O. * ceiling(n / size) * size
* To make it active, call dm_suspend(), dm_swap_table() then dm_resume().
*/ */
int dm_create_error_table(struct dm_table **result, struct mapped_device *md); #define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
static inline sector_t to_sector(unsigned long n)
{
return (n >> SECTOR_SHIFT);
}
static inline unsigned long to_bytes(sector_t n)
{
return (n << SECTOR_SHIFT);
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_DEVICE_MAPPER_H */ #endif /* _LINUX_DEVICE_MAPPER_H */
/* /*
* Copyright (C) 2003 Sistina Software * Copyright (C) 2003 Sistina Software
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
*
* Device-Mapper dirty region log.
* *
* This file is released under the LGPL. * This file is released under the LGPL.
*/ */
#ifndef DM_DIRTY_LOG #ifndef _LINUX_DM_DIRTY_LOG
#define DM_DIRTY_LOG #define _LINUX_DM_DIRTY_LOG
#ifdef __KERNEL__
#include "dm.h" #include <linux/types.h>
#include <linux/device-mapper.h>
typedef sector_t region_t; typedef sector_t region_t;
struct dirty_log_type; struct dm_dirty_log_type;
struct dirty_log { struct dm_dirty_log {
struct dirty_log_type *type; struct dm_dirty_log_type *type;
void *context; void *context;
}; };
struct dirty_log_type { struct dm_dirty_log_type {
struct list_head list;
const char *name; const char *name;
struct module *module; struct module *module;
unsigned int use_count;
int (*ctr)(struct dirty_log *log, struct dm_target *ti, int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,
unsigned int argc, char **argv); unsigned argc, char **argv);
void (*dtr)(struct dirty_log *log); void (*dtr)(struct dm_dirty_log *log);
/* /*
* There are times when we don't want the log to touch * There are times when we don't want the log to touch
* the disk. * the disk.
*/ */
int (*presuspend)(struct dirty_log *log); int (*presuspend)(struct dm_dirty_log *log);
int (*postsuspend)(struct dirty_log *log); int (*postsuspend)(struct dm_dirty_log *log);
int (*resume)(struct dirty_log *log); int (*resume)(struct dm_dirty_log *log);
/* /*
* Retrieves the smallest size of region that the log can * Retrieves the smallest size of region that the log can
* deal with. * deal with.
*/ */
uint32_t (*get_region_size)(struct dirty_log *log); uint32_t (*get_region_size)(struct dm_dirty_log *log);
/* /*
* A predicate to say whether a region is clean or not. * A predicate to say whether a region is clean or not.
* May block. * May block.
*/ */
int (*is_clean)(struct dirty_log *log, region_t region); int (*is_clean)(struct dm_dirty_log *log, region_t region);
/* /*
* Returns: 0, 1, -EWOULDBLOCK, < 0 * Returns: 0, 1, -EWOULDBLOCK, < 0
...@@ -59,13 +63,14 @@ struct dirty_log_type { ...@@ -59,13 +63,14 @@ struct dirty_log_type {
* passed to a daemon to deal with, since a daemon is * passed to a daemon to deal with, since a daemon is
* allowed to block. * allowed to block.
*/ */
int (*in_sync)(struct dirty_log *log, region_t region, int can_block); int (*in_sync)(struct dm_dirty_log *log, region_t region,
int can_block);
/* /*
* Flush the current log state (eg, to disk). This * Flush the current log state (eg, to disk). This
* function may block. * function may block.
*/ */
int (*flush)(struct dirty_log *log); int (*flush)(struct dm_dirty_log *log);
/* /*
* Mark an area as clean or dirty. These functions may * Mark an area as clean or dirty. These functions may
...@@ -73,8 +78,8 @@ struct dirty_log_type { ...@@ -73,8 +78,8 @@ struct dirty_log_type {
* be extremely rare (eg, allocating another chunk of * be extremely rare (eg, allocating another chunk of
* memory for some reason). * memory for some reason).
*/ */
void (*mark_region)(struct dirty_log *log, region_t region); void (*mark_region)(struct dm_dirty_log *log, region_t region);
void (*clear_region)(struct dirty_log *log, region_t region); void (*clear_region)(struct dm_dirty_log *log, region_t region);
/* /*
* Returns: <0 (error), 0 (no region), 1 (region) * Returns: <0 (error), 0 (no region), 1 (region)
...@@ -88,44 +93,39 @@ struct dirty_log_type { ...@@ -88,44 +93,39 @@ struct dirty_log_type {
* tells you if an area is synchronised, the other * tells you if an area is synchronised, the other
* assigns recovery work. * assigns recovery work.
*/ */
int (*get_resync_work)(struct dirty_log *log, region_t *region); int (*get_resync_work)(struct dm_dirty_log *log, region_t *region);
/* /*
* This notifies the log that the resync status of a region * This notifies the log that the resync status of a region
* has changed. It also clears the region from the recovering * has changed. It also clears the region from the recovering
* list (if present). * list (if present).
*/ */
void (*set_region_sync)(struct dirty_log *log, void (*set_region_sync)(struct dm_dirty_log *log,
region_t region, int in_sync); region_t region, int in_sync);
/* /*
* Returns the number of regions that are in sync. * Returns the number of regions that are in sync.
*/ */
region_t (*get_sync_count)(struct dirty_log *log); region_t (*get_sync_count)(struct dm_dirty_log *log);
/* /*
* Support function for mirror status requests. * Support function for mirror status requests.
*/ */
int (*status)(struct dirty_log *log, status_type_t status_type, int (*status)(struct dm_dirty_log *log, status_type_t status_type,
char *result, unsigned int maxlen); char *result, unsigned maxlen);
}; };
int dm_register_dirty_log_type(struct dirty_log_type *type); int dm_dirty_log_type_register(struct dm_dirty_log_type *type);
int dm_unregister_dirty_log_type(struct dirty_log_type *type); int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type);
/* /*
* Make sure you use these two functions, rather than calling * Make sure you use these two functions, rather than calling
* type->constructor/destructor() directly. * type->constructor/destructor() directly.
*/ */
struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti, struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
unsigned int argc, char **argv); struct dm_target *ti,
void dm_destroy_dirty_log(struct dirty_log *log); unsigned argc, char **argv);
void dm_dirty_log_destroy(struct dm_dirty_log *log);
/*
* init/exit functions.
*/
int dm_dirty_log_init(void);
void dm_dirty_log_exit(void);
#endif #endif /* __KERNEL__ */
#endif /* _LINUX_DM_DIRTY_LOG_H */
/* /*
* Copyright (C) 2003 Sistina Software * Copyright (C) 2003 Sistina Software
* Copyright (C) 2004 - 2008 Red Hat, Inc. All rights reserved.
*
* Device-Mapper low-level I/O.
* *
* This file is released under the GPL. * This file is released under the GPL.
*/ */
#ifndef _DM_IO_H #ifndef _LINUX_DM_IO_H
#define _DM_IO_H #define _LINUX_DM_IO_H
#ifdef __KERNEL__
#include "dm.h" #include <linux/types.h>
struct io_region { struct dm_io_region {
struct block_device *bdev; struct block_device *bdev;
sector_t sector; sector_t sector;
sector_t count; /* If this is zero the region is ignored. */ sector_t count; /* If this is zero the region is ignored. */
...@@ -74,6 +79,7 @@ void dm_io_client_destroy(struct dm_io_client *client); ...@@ -74,6 +79,7 @@ void dm_io_client_destroy(struct dm_io_client *client);
* error occurred doing io to the corresponding region. * error occurred doing io to the corresponding region.
*/ */
int dm_io(struct dm_io_request *io_req, unsigned num_regions, int dm_io(struct dm_io_request *io_req, unsigned num_regions,
struct io_region *region, unsigned long *sync_error_bits); struct dm_io_region *region, unsigned long *sync_error_bits);
#endif #endif /* __KERNEL__ */
#endif /* _LINUX_DM_IO_H */
/*
* Copyright (C) 2001 - 2003 Sistina Software
* Copyright (C) 2004 - 2008 Red Hat, Inc. All rights reserved.
*
* kcopyd provides a simple interface for copying an area of one
* block-device to one or more other block-devices, either synchronous
* or with an asynchronous completion notification.
*
* This file is released under the GPL.
*/
#ifndef _LINUX_DM_KCOPYD_H
#define _LINUX_DM_KCOPYD_H
#ifdef __KERNEL__
#include <linux/dm-io.h>
/* FIXME: make this configurable */
#define DM_KCOPYD_MAX_REGIONS 8
#define DM_KCOPYD_IGNORE_ERROR 1
/*
* To use kcopyd you must first create a dm_kcopyd_client object.
*/
struct dm_kcopyd_client;
int dm_kcopyd_client_create(unsigned num_pages,
struct dm_kcopyd_client **result);
void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc);
/*
* Submit a copy job to kcopyd. This is built on top of the
* previous three fns.
*
* read_err is a boolean,
* write_err is a bitset, with 1 bit for each destination region
*/
typedef void (*dm_kcopyd_notify_fn)(int read_err, unsigned long write_err,
void *context);
int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
unsigned num_dests, struct dm_io_region *dests,
unsigned flags, dm_kcopyd_notify_fn fn, void *context);
#endif /* __KERNEL__ */
#endif /* _LINUX_DM_KCOPYD_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment