diff options
-rw-r--r-- | drivers/md/dm-log.c | 89 | ||||
-rw-r--r-- | drivers/md/dm-log.h | 84 | ||||
-rw-r--r-- | drivers/md/dm-raid1.c | 36 | ||||
-rw-r--r-- | drivers/md/dm.h | 6 | ||||
-rw-r--r-- | include/linux/device-mapper.h | 2 |
5 files changed, 114 insertions, 103 deletions
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 14f785fc308a..b776701cc8fa 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -12,13 +12,14 @@ #include "dm-log.h" #include "dm-io.h" +#include "dm.h" #define DM_MSG_PREFIX "dirty region log" static LIST_HEAD(_log_types); static DEFINE_SPINLOCK(_lock); -int dm_register_dirty_log_type(struct dirty_log_type *type) +int dm_dirty_log_type_register(struct dm_dirty_log_type *type) { spin_lock(&_lock); type->use_count = 0; @@ -27,8 +28,9 @@ int dm_register_dirty_log_type(struct dirty_log_type *type) return 0; } +EXPORT_SYMBOL(dm_dirty_log_type_register); -int dm_unregister_dirty_log_type(struct dirty_log_type *type) +int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type) { spin_lock(&_lock); @@ -41,10 +43,11 @@ int dm_unregister_dirty_log_type(struct dirty_log_type *type) return 0; } +EXPORT_SYMBOL(dm_dirty_log_type_unregister); -static struct dirty_log_type *_get_type(const char *type_name) +static struct dm_dirty_log_type *_get_type(const char *type_name) { - struct dirty_log_type *type; + struct dm_dirty_log_type *type; spin_lock(&_lock); list_for_each_entry (type, &_log_types, list) @@ -79,10 +82,10 @@ static struct dirty_log_type *_get_type(const char *type_name) * * Returns: dirty_log_type* on success, NULL on failure */ -static struct dirty_log_type *get_type(const char *type_name) +static struct dm_dirty_log_type *get_type(const char *type_name) { char *p, *type_name_dup; - struct dirty_log_type *type; + struct dm_dirty_log_type *type; type = _get_type(type_name); if (type) @@ -111,7 +114,7 @@ static struct dirty_log_type *get_type(const char *type_name) return type; } -static void put_type(struct dirty_log_type *type) +static void put_type(struct dm_dirty_log_type *type) { spin_lock(&_lock); if (!--type->use_count) @@ -119,11 +122,12 @@ static void put_type(struct dirty_log_type *type) spin_unlock(&_lock); } -struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti, - unsigned int argc, char **argv) +struct dm_dirty_log *dm_dirty_log_create(const char *type_name, + struct dm_target *ti, + unsigned int argc, char **argv) { - struct dirty_log_type *type; - struct dirty_log *log; + struct dm_dirty_log_type *type; + struct dm_dirty_log *log; log = kmalloc(sizeof(*log), GFP_KERNEL); if (!log) @@ -144,13 +148,15 @@ struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *t return log; } +EXPORT_SYMBOL(dm_dirty_log_create); -void dm_destroy_dirty_log(struct dirty_log *log) +void dm_dirty_log_destroy(struct dm_dirty_log *log) { log->type->dtr(log); put_type(log->type); kfree(log); } +EXPORT_SYMBOL(dm_dirty_log_destroy); /*----------------------------------------------------------------- * Persistent and core logs share a lot of their implementation. @@ -216,7 +222,7 @@ struct log_c { * The touched member needs to be updated every time we access * one of the bitsets. */ -static inline int log_test_bit(uint32_t *bs, unsigned bit) +static inline int log_test_bit(uint32_t *bs, unsigned bit) { return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0; } @@ -303,7 +309,7 @@ static inline int write_header(struct log_c *log) * argv contains region_size followed optionally by [no]sync *--------------------------------------------------------------*/ #define BYTE_SHIFT 3 -static int create_log_context(struct dirty_log *log, struct dm_target *ti, +static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, unsigned int argc, char **argv, struct dm_dev *dev) { @@ -435,7 +441,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti, return 0; } -static int core_ctr(struct dirty_log *log, struct dm_target *ti, +static int core_ctr(struct dm_dirty_log *log, struct dm_target *ti, unsigned int argc, char **argv) { return create_log_context(log, ti, argc, argv, NULL); @@ -448,7 +454,7 @@ static void destroy_log_context(struct log_c *lc) kfree(lc); } -static void core_dtr(struct dirty_log *log) +static void core_dtr(struct dm_dirty_log *log) { struct log_c *lc = (struct log_c *) log->context; @@ -461,7 +467,7 @@ static void core_dtr(struct dirty_log *log) * * argv contains log_device region_size followed optionally by [no]sync *--------------------------------------------------------------*/ -static int disk_ctr(struct dirty_log *log, struct dm_target *ti, +static int disk_ctr(struct dm_dirty_log *log, struct dm_target *ti, unsigned int argc, char **argv) { int r; @@ -486,7 +492,7 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti, return 0; } -static void disk_dtr(struct dirty_log *log) +static void disk_dtr(struct dm_dirty_log *log) { struct log_c *lc = (struct log_c *) log->context; @@ -515,7 +521,7 @@ static void fail_log_device(struct log_c *lc) dm_table_event(lc->ti->table); } -static int disk_resume(struct dirty_log *log) +static int disk_resume(struct dm_dirty_log *log) { int r; unsigned i; @@ -571,38 +577,38 @@ static int disk_resume(struct dirty_log *log) return r; } -static uint32_t core_get_region_size(struct dirty_log *log) +static uint32_t core_get_region_size(struct dm_dirty_log *log) { struct log_c *lc = (struct log_c *) log->context; return lc->region_size; } -static int core_resume(struct dirty_log *log) +static int core_resume(struct dm_dirty_log *log) { struct log_c *lc = (struct log_c *) log->context; lc->sync_search = 0; return 0; } -static int core_is_clean(struct dirty_log *log, region_t region) +static int core_is_clean(struct dm_dirty_log *log, region_t region) { struct log_c *lc = (struct log_c *) log->context; return log_test_bit(lc->clean_bits, region); } -static int core_in_sync(struct dirty_log *log, region_t region, int block) +static int core_in_sync(struct dm_dirty_log *log, region_t region, int block) { struct log_c *lc = (struct log_c *) log->context; return log_test_bit(lc->sync_bits, region); } -static int core_flush(struct dirty_log *log) +static int core_flush(struct dm_dirty_log *log) { /* no op */ return 0; } -static int disk_flush(struct dirty_log *log) +static int disk_flush(struct dm_dirty_log *log) { int r; struct log_c *lc = (struct log_c *) log->context; @@ -620,19 +626,19 @@ static int disk_flush(struct dirty_log *log) return r; } -static void core_mark_region(struct dirty_log *log, region_t region) +static void core_mark_region(struct dm_dirty_log *log, region_t region) { struct log_c *lc = (struct log_c *) log->context; log_clear_bit(lc, lc->clean_bits, region); } -static void core_clear_region(struct dirty_log *log, region_t region) +static void core_clear_region(struct dm_dirty_log *log, region_t region) { struct log_c *lc = (struct log_c *) log->context; log_set_bit(lc, lc->clean_bits, region); } -static int core_get_resync_work(struct dirty_log *log, region_t *region) +static int core_get_resync_work(struct dm_dirty_log *log, region_t *region) { struct log_c *lc = (struct log_c *) log->context; @@ -655,7 +661,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region) return 1; } -static void core_set_region_sync(struct dirty_log *log, region_t region, +static void core_set_region_sync(struct dm_dirty_log *log, region_t region, int in_sync) { struct log_c *lc = (struct log_c *) log->context; @@ -670,7 +676,7 @@ static void core_set_region_sync(struct dirty_log *log, region_t region, } } -static region_t core_get_sync_count(struct dirty_log *log) +static region_t core_get_sync_count(struct dm_dirty_log *log) { struct log_c *lc = (struct log_c *) log->context; @@ -681,7 +687,7 @@ static region_t core_get_sync_count(struct dirty_log *log) if (lc->sync != DEFAULTSYNC) \ DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "") -static int core_status(struct dirty_log *log, status_type_t status, +static int core_status(struct dm_dirty_log *log, status_type_t status, char *result, unsigned int maxlen) { int sz = 0; @@ -701,7 +707,7 @@ static int core_status(struct dirty_log *log, status_type_t status, return sz; } -static int disk_status(struct dirty_log *log, status_type_t status, +static int disk_status(struct dm_dirty_log *log, status_type_t status, char *result, unsigned int maxlen) { int sz = 0; @@ -723,7 +729,7 @@ static int disk_status(struct dirty_log *log, status_type_t status, return sz; } -static struct dirty_log_type _core_type = { +static struct dm_dirty_log_type _core_type = { .name = "core", .module = THIS_MODULE, .ctr = core_ctr, @@ -741,7 +747,7 @@ static struct dirty_log_type _core_type = { .status = core_status, }; -static struct dirty_log_type _disk_type = { +static struct dm_dirty_log_type _disk_type = { .name = "disk", .module = THIS_MODULE, .ctr = disk_ctr, @@ -764,14 +770,14 @@ int __init dm_dirty_log_init(void) { int r; - r = dm_register_dirty_log_type(&_core_type); + r = dm_dirty_log_type_register(&_core_type); if (r) DMWARN("couldn't register core log"); - r = dm_register_dirty_log_type(&_disk_type); + r = dm_dirty_log_type_register(&_disk_type); if (r) { DMWARN("couldn't register disk type"); - dm_unregister_dirty_log_type(&_core_type); + dm_dirty_log_type_unregister(&_core_type); } return r; @@ -779,15 +785,10 @@ int __init dm_dirty_log_init(void) void __exit dm_dirty_log_exit(void) { - dm_unregister_dirty_log_type(&_disk_type); - dm_unregister_dirty_log_type(&_core_type); + dm_dirty_log_type_unregister(&_disk_type); + dm_dirty_log_type_unregister(&_core_type); } -EXPORT_SYMBOL(dm_register_dirty_log_type); -EXPORT_SYMBOL(dm_unregister_dirty_log_type); -EXPORT_SYMBOL(dm_create_dirty_log); -EXPORT_SYMBOL(dm_destroy_dirty_log); - module_init(dm_dirty_log_init); module_exit(dm_dirty_log_exit); diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h index 3fae87eb5963..2da48a857cb9 100644 --- a/drivers/md/dm-log.h +++ b/drivers/md/dm-log.h @@ -1,52 +1,58 @@ /* * 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 dm_dirty_log_type { struct list_head list; const char *name; struct module *module; - unsigned int use_count; + unsigned 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 +65,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 +80,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 +95,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 */ diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 32c7c6d10939..5beeced4e522 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -74,7 +74,7 @@ struct region_hash { unsigned region_shift; /* holds persistent region state */ - struct dirty_log *log; + struct dm_dirty_log *log; /* hash table */ rwlock_t hash_lock; @@ -184,7 +184,7 @@ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); #define MIN_REGIONS 64 #define MAX_RECOVERY 1 static int rh_init(struct region_hash *rh, struct mirror_set *ms, - struct dirty_log *log, uint32_t region_size, + struct dm_dirty_log *log, uint32_t region_size, region_t nr_regions) { unsigned int nr_buckets, max_buckets; @@ -249,7 +249,7 @@ static void rh_exit(struct region_hash *rh) } if (rh->log) - dm_destroy_dirty_log(rh->log); + dm_dirty_log_destroy(rh->log); if (rh->region_pool) mempool_destroy(rh->region_pool); vfree(rh->buckets); @@ -831,7 +831,7 @@ static void do_recovery(struct mirror_set *ms) { int r; struct region *reg; - struct dirty_log *log = ms->rh.log; + struct dm_dirty_log *log = ms->rh.log; /* * Start quiescing some regions. @@ -1017,7 +1017,7 @@ static void __bio_mark_nosync(struct mirror_set *ms, { unsigned long flags; struct region_hash *rh = &ms->rh; - struct dirty_log *log = ms->rh.log; + struct dm_dirty_log *log = ms->rh.log; struct region *reg; region_t region = bio_to_region(rh, bio); int recovering = 0; @@ -1301,7 +1301,7 @@ static void do_mirror(struct work_struct *work) static struct mirror_set *alloc_context(unsigned int nr_mirrors, uint32_t region_size, struct dm_target *ti, - struct dirty_log *dl) + struct dm_dirty_log *dl) { size_t len; struct mirror_set *ms = NULL; @@ -1401,12 +1401,12 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti, /* * Create dirty log: log_type #log_params <log_params> */ -static struct dirty_log *create_dirty_log(struct dm_target *ti, +static struct dm_dirty_log *create_dirty_log(struct dm_target *ti, unsigned int argc, char **argv, unsigned int *args_used) { unsigned int param_count; - struct dirty_log *dl; + struct dm_dirty_log *dl; if (argc < 2) { ti->error = "Insufficient mirror log arguments"; @@ -1425,7 +1425,7 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti, return NULL; } - dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2); + dl = dm_dirty_log_create(argv[0], ti, param_count, argv + 2); if (!dl) { ti->error = "Error creating mirror dirty log"; return NULL; @@ -1433,7 +1433,7 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti, if (!_check_region_size(ti, dl->type->get_region_size(dl))) { ti->error = "Invalid region size"; - dm_destroy_dirty_log(dl); + dm_dirty_log_destroy(dl); return NULL; } @@ -1494,7 +1494,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) int r; unsigned int nr_mirrors, m, args_used; struct mirror_set *ms; - struct dirty_log *dl; + struct dm_dirty_log *dl; dl = create_dirty_log(ti, argc, argv, &args_used); if (!dl) @@ -1506,7 +1506,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 || nr_mirrors < 2 || nr_mirrors > DM_KCOPYD_MAX_REGIONS + 1) { ti->error = "Invalid number of mirrors"; - dm_destroy_dirty_log(dl); + dm_dirty_log_destroy(dl); return -EINVAL; } @@ -1514,13 +1514,13 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (argc < nr_mirrors * 2) { ti->error = "Too few mirror arguments"; - dm_destroy_dirty_log(dl); + dm_dirty_log_destroy(dl); return -EINVAL; } ms = alloc_context(nr_mirrors, dl->type->get_region_size(dl), ti, dl); if (!ms) { - dm_destroy_dirty_log(dl); + dm_dirty_log_destroy(dl); return -ENOMEM; } @@ -1732,7 +1732,7 @@ out: static void mirror_presuspend(struct dm_target *ti) { struct mirror_set *ms = (struct mirror_set *) ti->private; - struct dirty_log *log = ms->rh.log; + struct dm_dirty_log *log = ms->rh.log; atomic_set(&ms->suspend, 1); @@ -1761,7 +1761,7 @@ static void mirror_presuspend(struct dm_target *ti) static void mirror_postsuspend(struct dm_target *ti) { struct mirror_set *ms = ti->private; - struct dirty_log *log = ms->rh.log; + struct dm_dirty_log *log = ms->rh.log; if (log->type->postsuspend && log->type->postsuspend(log)) /* FIXME: need better error handling */ @@ -1771,7 +1771,7 @@ static void mirror_postsuspend(struct dm_target *ti) static void mirror_resume(struct dm_target *ti) { struct mirror_set *ms = ti->private; - struct dirty_log *log = ms->rh.log; + struct dm_dirty_log *log = ms->rh.log; atomic_set(&ms->suspend, 0); if (log->type->resume && log->type->resume(log)) @@ -1809,7 +1809,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type, { unsigned int m, sz = 0; struct mirror_set *ms = (struct mirror_set *) ti->private; - struct dirty_log *log = ms->rh.log; + struct dm_dirty_log *log = ms->rh.log; char buffer[ms->nr_mirrors + 1]; switch (type) { diff --git a/drivers/md/dm.h b/drivers/md/dm.h index b4584a39383b..17f2d6a8b124 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -189,4 +189,10 @@ 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); + #endif diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index cb784579956b..4db23378cfb1 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -10,6 +10,8 @@ #ifdef __KERNEL__ +#include <linux/bio.h> + struct dm_target; struct dm_table; struct dm_dev; |