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 @@
#
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-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-hp-sw-objs := dm-mpath-hp-sw.o
md-mod-objs := md.o bitmap.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_RDAC) += dm-rdac.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
quiet_cmd_unroll = UNROLL $@
......
......@@ -9,13 +9,13 @@
#include "dm.h"
#include "dm-snap.h"
#include "dm-io.h"
#include "kcopyd.h"
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/dm-io.h>
#include <linux/dm-kcopyd.h>
#define DM_MSG_PREFIX "snapshots"
#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
......@@ -131,7 +131,7 @@ struct pstore {
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)
......@@ -159,7 +159,7 @@ static void free_area(struct pstore *ps)
}
struct mdata_req {
struct io_region *where;
struct dm_io_region *where;
struct dm_io_request *io_req;
struct work_struct work;
int result;
......@@ -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)
{
struct io_region where = {
struct dm_io_region where = {
.bdev = ps->snap->cow->bdev,
.sector = ps->snap->chunk_size * chunk,
.count = ps->snap->chunk_size,
......
......@@ -5,13 +5,14 @@
* This file is released under the GPL.
*/
#include "dm-io.h"
#include "dm.h"
#include <linux/bio.h>
#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/dm-io.h>
struct dm_io_client {
mempool_t *pool;
......@@ -20,7 +21,7 @@ struct dm_io_client {
/* FIXME: can we shrink this ? */
struct io {
unsigned long error;
unsigned long error_bits;
atomic_t count;
struct task_struct *sleeper;
struct dm_io_client *client;
......@@ -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)
{
if (error)
set_bit(region, &io->error);
set_bit(region, &io->error_bits);
if (atomic_dec_and_test(&io->count)) {
if (io->sleeper)
wake_up_process(io->sleeper);
else {
unsigned long r = io->error;
unsigned long r = io->error_bits;
io_notify_fn fn = io->callback;
void *context = io->context;
......@@ -271,7 +272,7 @@ static void km_dp_init(struct dpages *dp, void *data)
/*-----------------------------------------------------------------
* 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 bio *bio;
......@@ -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,
struct io_region *where, struct dpages *dp,
struct dm_io_region *where, struct dpages *dp,
struct io *io, int sync)
{
int i;
......@@ -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,
struct io_region *where, int rw, struct dpages *dp,
struct dm_io_region *where, int rw, struct dpages *dp,
unsigned long *error_bits)
{
struct io io;
if (num_regions > 1 && rw != WRITE) {
if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
WARN_ON(1);
return -EIO;
}
io.error = 0;
io.error_bits = 0;
atomic_set(&io.count, 1); /* see dispatch_io() */
io.sleeper = current;
io.client = client;
......@@ -378,25 +379,25 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
return -EINTR;
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,
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)
{
struct io *io;
if (num_regions > 1 && rw != WRITE) {
if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
WARN_ON(1);
fn(1, context);
return -EIO;
}
io = mempool_alloc(client->pool, GFP_NOIO);
io->error = 0;
io->error_bits = 0;
atomic_set(&io->count, 1); /* see dispatch_io() */
io->sleeper = NULL;
io->client = client;
......@@ -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,
struct io_region *where, unsigned long *sync_error_bits)
struct dm_io_region *where, unsigned long *sync_error_bits)
{
int r;
struct dpages dp;
......
This diff is collapsed.
This diff is collapsed.
......@@ -18,10 +18,10 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/log2.h>
#include <linux/dm-kcopyd.h>
#include "dm-snap.h"
#include "dm-bio-list.h"
#include "kcopyd.h"
#define DM_MSG_PREFIX "snapshots"
......@@ -36,9 +36,9 @@
#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 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)
s->last_percent = 0;
init_rwsem(&s->lock);
spin_lock_init(&s->pe_lock);
s->table = ti->table;
s->ti = ti;
/* Allocate hash table for COW data */
if (init_hash_tables(s)) {
......@@ -558,7 +558,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad4;
}
r = kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
r = dm_kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
if (r) {
ti->error = "Could not create kcopyd client";
goto bad5;
......@@ -591,7 +591,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return 0;
bad6:
kcopyd_client_destroy(s->kcopyd_client);
dm_kcopyd_client_destroy(s->kcopyd_client);
bad5:
s->store.destroy(&s->store);
......@@ -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)
{
kcopyd_client_destroy(s->kcopyd_client);
dm_kcopyd_client_destroy(s->kcopyd_client);
s->kcopyd_client = NULL;
exit_exception_table(&s->pending, pending_cache);
......@@ -699,7 +699,7 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
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)
......@@ -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)
{
struct dm_snapshot *s = pe->snap;
struct io_region src, dest;
struct dm_io_region src, dest;
struct block_device *bdev = s->origin->bdev;
sector_t dev_size;
......@@ -839,7 +839,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
dest.count = src.count;
/* Hand over to kcopyd */
kcopyd_copy(s->kcopyd_client,
dm_kcopyd_copy(s->kcopyd_client,
&src, 1, &dest, 0, copy_callback, pe);
}
......@@ -1060,7 +1060,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
goto next_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;
/*
......
......@@ -132,7 +132,7 @@ struct exception_store {
struct dm_snapshot {
struct rw_semaphore lock;
struct dm_table *table;
struct dm_target *ti;
struct dm_dev *origin;
struct dm_dev *cow;
......@@ -169,7 +169,7 @@ struct dm_snapshot {
/* The on disk metadata handler */
struct exception_store store;
struct kcopyd_client *kcopyd_client;
struct dm_kcopyd_client *kcopyd_client;
/* Queue of snapshot writes for ksnapd to flush */
struct bio_list queued_bios;
......
......@@ -245,44 +245,6 @@ int dm_table_create(struct dm_table **result, int mode,
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)
{
struct list_head *tmp, *next;
......@@ -954,7 +916,7 @@ void dm_table_presuspend_targets(struct dm_table *t)
if (!t)
return;
return suspend_targets(t, 0);
suspend_targets(t, 0);
}
void dm_table_postsuspend_targets(struct dm_table *t)
......@@ -962,7 +924,7 @@ void dm_table_postsuspend_targets(struct dm_table *t)
if (!t)
return;
return suspend_targets(t, 1);
suspend_targets(t, 1);
}
int dm_table_resume_targets(struct dm_table *t)
......
......@@ -204,6 +204,7 @@ static int (*_inits[])(void) __initdata = {
dm_target_init,
dm_linear_init,
dm_stripe_init,
dm_kcopyd_init,
dm_interface_init,
};
......@@ -212,6 +213,7 @@ static void (*_exits[])(void) = {
dm_target_exit,
dm_linear_exit,
dm_stripe_exit,
dm_kcopyd_exit,
dm_interface_exit,
};
......@@ -922,7 +924,7 @@ static void free_minor(int minor)
/*
* 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;
......@@ -955,7 +957,7 @@ out:
return r;
}
static int next_free_minor(struct mapped_device *md, int *minor)
static int next_free_minor(int *minor)
{
int r, m;
......@@ -966,9 +968,8 @@ static int next_free_minor(struct mapped_device *md, int *minor)
spin_lock(&_minor_lock);
r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
if (r) {
if (r)
goto out;
}
if (m >= (1 << MINORBITS)) {
idr_remove(&_minor_idr, m);
......@@ -991,7 +992,7 @@ static struct block_device_operations dm_blk_dops;
static struct mapped_device *alloc_dev(int minor)
{
int r;
struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
struct mapped_device *md = kzalloc(sizeof(*md), GFP_KERNEL);
void *old_md;
if (!md) {
......@@ -1004,13 +1005,12 @@ static struct mapped_device *alloc_dev(int minor)
/* get a minor number for the dev */
if (minor == DM_ANY_MINOR)
r = next_free_minor(md, &minor);
r = next_free_minor(&minor);
else
r = specific_minor(md, minor);
r = specific_minor(minor);
if (r < 0)
goto bad_minor;
memset(md, 0, sizeof(*md));
init_rwsem(&md->io_lock);
mutex_init(&md->suspend_lock);
spin_lock_init(&md->pushback_lock);
......
......@@ -16,67 +16,6 @@
#include <linux/blkdev.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
*/
......@@ -136,34 +75,6 @@ static inline int array_too_big(unsigned long fixed, unsigned long 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);
/*
......@@ -189,4 +100,13 @@ int dm_lock_for_deletion(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
/*
* 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) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
*
* This file is released under the LGPL.
*/
......@@ -10,6 +10,8 @@
#ifdef __KERNEL__
#include <linux/bio.h>
struct dm_target;
struct dm_table;
struct dm_dev;
......@@ -250,11 +252,97 @@ void dm_table_event(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.
* To make it active, call dm_suspend(), dm_swap_table() then dm_resume().
* ceiling(n / size) * size
*/
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 /* _LINUX_DEVICE_MAPPER_H */
/*
* 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.
*/
#ifndef DM_DIRTY_LOG
#define DM_DIRTY_LOG
#ifndef _LINUX_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;
struct dirty_log_type;
struct dm_dirty_log_type;
struct dirty_log {
struct dirty_log_type *type;
struct dm_dirty_log {
struct dm_dirty_log_type *type;
void *context;
};
struct dirty_log_type {
struct list_head list;
struct dm_dirty_log_type {
const char *name;
struct module *module;
unsigned int use_count;
int (*ctr)(struct dirty_log *log, struct dm_target *ti,
unsigned int argc, char **argv);
void (*dtr)(struct dirty_log *log);
int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,
unsigned argc, char **argv);
void (*dtr)(struct dm_dirty_log *log);
/*
* There are times when we don't want the log to touch
* the disk.
*/
int (*presuspend)(struct dirty_log *log);
int (*postsuspend)(struct dirty_log *log);
int (*resume)(struct dirty_log *log);
int (*presuspend)(struct dm_dirty_log *log);
int (*postsuspend)(struct dm_dirty_log *log);
int (*resume)(struct dm_dirty_log *log);
/*
* Retrieves the smallest size of region that the log can
* 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.
* 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
......@@ -59,13 +63,14 @@ struct dirty_log_type {
* passed to a daemon to deal with, since a daemon is
* 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
* 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
......@@ -73,8 +78,8 @@ struct dirty_log_type {
* be extremely rare (eg, allocating another chunk of
* memory for some reason).
*/
void (*mark_region)(struct dirty_log *log, region_t region);
void (*clear_region)(struct dirty_log *log, region_t region);
void (*mark_region)(struct dm_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)
......@@ -88,44 +93,39 @@ struct dirty_log_type {
* tells you if an area is synchronised, the other
* 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
* has changed. It also clears the region from the recovering
* 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);
/*
* 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.
*/
int (*status)(struct dirty_log *log, status_type_t status_type,
char *result, unsigned int maxlen);
int (*status)(struct dm_dirty_log *log, status_type_t status_type,
char *result, unsigned maxlen);
};
int dm_register_dirty_log_type(struct dirty_log_type *type);
int dm_unregister_dirty_log_type(struct dirty_log_type *type);
int dm_dirty_log_type_register(struct dm_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
* type->constructor/destructor() directly.
*/
struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
unsigned int argc, char **argv);
void dm_destroy_dirty_log(struct dirty_log *log);
/*
* init/exit functions.
*/
int dm_dirty_log_init(void);
void dm_dirty_log_exit(void);
struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
struct dm_target *ti,
unsigned argc, char **argv);
void dm_dirty_log_destroy(struct dm_dirty_log *log);
#endif
#endif /* __KERNEL__ */
#endif /* _LINUX_DM_DIRTY_LOG_H */
/*
* 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.
*/
#ifndef _DM_IO_H
#define _DM_IO_H
#ifndef _LINUX_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;
sector_t sector;
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);
* error occurred doing io to the corresponding region.
*/
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