From 5b5fe17c2dc2873c0bc65b69783f3483e04cfb41 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 21 Jan 2003 21:34:45 +0000 Subject: [PATCH] Update to 2.4.20-dm-7 (with 3 DMWARNs removed) --- kernel/common/device-mapper.h | 24 +++++--- kernel/common/dm-linear.c | 3 +- kernel/common/dm-snapshot.c | 19 ++++--- kernel/common/dm-stripe.c | 49 ++++++++-------- kernel/common/dm-table.c | 38 ++++++------- kernel/common/dm-target.c | 31 +++++------ kernel/common/dm.c | 102 ++++++++++++++++++++-------------- kernel/common/kcopyd.c | 22 ++++---- kernel/common/kcopyd.h | 2 +- kernel/ioctl/dm-ioctl.c | 34 +++++++++--- kernel/ioctl/dm-ioctl.h | 4 +- 11 files changed, 187 insertions(+), 141 deletions(-) diff --git a/kernel/common/device-mapper.h b/kernel/common/device-mapper.h index 5a51622..a42cf69 100644 --- a/kernel/common/device-mapper.h +++ b/kernel/common/device-mapper.h @@ -7,8 +7,6 @@ #ifndef _LINUX_DEVICE_MAPPER_H #define _LINUX_DEVICE_MAPPER_H -#ifdef __KERNEL__ - typedef unsigned long sector_t; struct dm_target; @@ -21,13 +19,13 @@ typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t; * In the constructor the target parameter will already have the * table, type, begin and len fields filled in. */ -typedef int (*dm_ctr_fn) (struct dm_target *target, int argc, char **argv); +typedef int (*dm_ctr_fn) (struct dm_target * target, int argc, char **argv); /* * The destructor doesn't need to free the dm_target, just * anything hidden ti->private. */ -typedef void (*dm_dtr_fn) (struct dm_target *ti); +typedef void (*dm_dtr_fn) (struct dm_target * ti); /* * The map function must return: @@ -35,8 +33,19 @@ typedef void (*dm_dtr_fn) (struct dm_target *ti); * = 0: The target will handle the io by resubmitting it later * > 0: simple remap complete */ -typedef int (*dm_map_fn) (struct dm_target *ti, struct buffer_head *bh, int rw); -typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, +typedef int (*dm_map_fn) (struct dm_target * ti, struct buffer_head * bh, + int rw, void **map_context); + +/* + * Returns: + * < 0 : error (currently ignored) + * 0 : ended successfully + * 1 : for some reason the io has still not completed (eg, + * multipath target might want to requeue a failed io). + */ +typedef int (*dm_endio_fn) (struct dm_target * ti, struct buffer_head * bh, + int rw, int error, void *map_context); +typedef int (*dm_status_fn) (struct dm_target * ti, status_type_t status_type, char *result, int maxlen); void dm_error(const char *message); @@ -59,6 +68,7 @@ struct target_type { dm_ctr_fn ctr; dm_dtr_fn dtr; dm_map_fn map; + dm_endio_fn end_io; dm_status_fn status; }; @@ -80,6 +90,4 @@ struct dm_target { int dm_register_target(struct target_type *t); int dm_unregister_target(struct target_type *t); -#endif /* __KERNEL__ */ - #endif /* _LINUX_DEVICE_MAPPER_H */ diff --git a/kernel/common/dm-linear.c b/kernel/common/dm-linear.c index 9a7f60a..5bdb440 100644 --- a/kernel/common/dm-linear.c +++ b/kernel/common/dm-linear.c @@ -64,7 +64,8 @@ static void linear_dtr(struct dm_target *ti) kfree(lc); } -static int linear_map(struct dm_target *ti, struct buffer_head *bh, int rw) +static int linear_map(struct dm_target *ti, struct buffer_head *bh, int rw, + void **map_context) { struct linear_c *lc = (struct linear_c *) ti->private; diff --git a/kernel/common/dm-snapshot.c b/kernel/common/dm-snapshot.c index 232abf1..8f7f319 100644 --- a/kernel/common/dm-snapshot.c +++ b/kernel/common/dm-snapshot.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -398,7 +399,7 @@ static int snapshot_ctr(struct dm_target *ti, int argc, char **argv) struct dm_snapshot *s; unsigned long chunk_size; int r = -EINVAL; - char *persistent; + char persistent; char *origin_path; char *cow_path; char *value; @@ -412,9 +413,9 @@ static int snapshot_ctr(struct dm_target *ti, int argc, char **argv) origin_path = argv[0]; cow_path = argv[1]; - persistent = argv[2]; + persistent = toupper(*argv[2]); - if ((*persistent & 0x5f) != 'P' && (*persistent & 0x5f) != 'N') { + if (persistent != 'P' && persistent != 'N') { ti->error = "Persistent flag is not P or N"; r = -EINVAL; goto bad; @@ -430,7 +431,7 @@ static int snapshot_ctr(struct dm_target *ti, int argc, char **argv) s = kmalloc(sizeof(*s), GFP_KERNEL); if (s == NULL) { ti->error = "Cannot allocate snapshot context private " - "structure"; + "structure"; r = -ENOMEM; goto bad; } @@ -480,7 +481,7 @@ static int snapshot_ctr(struct dm_target *ti, int argc, char **argv) s->chunk_size = chunk_size; s->chunk_mask = chunk_size - 1; - s->type = *persistent; + s->type = persistent; for (s->chunk_shift = 0; chunk_size; s->chunk_shift++, chunk_size >>= 1) ; @@ -504,7 +505,7 @@ static int snapshot_ctr(struct dm_target *ti, int argc, char **argv) */ s->store.snap = s; - if ((*persistent & 0x5f) == 'P') + if (persistent == 'P') r = dm_create_persistent(&s->store, s->chunk_size); else r = dm_create_transient(&s->store, s, blocksize); @@ -785,7 +786,8 @@ static inline void remap_exception(struct dm_snapshot *s, struct exception *e, (bh->b_rsector & s->chunk_mask); } -static int snapshot_map(struct dm_target *ti, struct buffer_head *bh, int rw) +static int snapshot_map(struct dm_target *ti, struct buffer_head *bh, int rw, + void **map_context) { struct exception *e; struct dm_snapshot *s = (struct dm_snapshot *) ti->private; @@ -1028,7 +1030,8 @@ static void origin_dtr(struct dm_target *ti) dm_put_device(ti, dev); } -static int origin_map(struct dm_target *ti, struct buffer_head *bh, int rw) +static int origin_map(struct dm_target *ti, struct buffer_head *bh, int rw, + void **map_context) { struct dm_dev *dev = (struct dm_dev *) ti->private; bh->b_rdev = dev->dev; diff --git a/kernel/common/dm-stripe.c b/kernel/common/dm-stripe.c index b074039..40d0bc2 100644 --- a/kernel/common/dm-stripe.c +++ b/kernel/common/dm-stripe.c @@ -116,31 +116,38 @@ static int stripe_ctr(struct dm_target *ti, int argc, char **argv) return -EINVAL; } + /* + * chunk_size is a power of two + */ + if (!chunk_size || (chunk_size & (chunk_size - 1))) { + ti->error = "dm-stripe: Invalid chunk size"; + return -EINVAL; + } + if (!multiple(ti->len, stripes, &width)) { ti->error = "dm-stripe: Target length not divisable by " "number of stripes"; return -EINVAL; } + /* + * Do we have enough arguments for that many stripes ? + */ + if (argc != (2 + 2 * stripes)) { + ti->error = "dm-stripe: Not enough destinations specified"; + return -EINVAL; + } + sc = alloc_context(stripes); if (!sc) { ti->error = "dm-stripe: Memory allocation for striped context " - "failed"; + "failed"; return -ENOMEM; } sc->stripes = stripes; sc->stripe_width = width; - /* - * chunk_size is a power of two - */ - if (!chunk_size || (chunk_size & (chunk_size - 1))) { - ti->error = "dm-stripe: Invalid chunk size"; - kfree(sc); - return -EINVAL; - } - sc->chunk_mask = ((sector_t) chunk_size) - 1; for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++) chunk_size >>= 1; @@ -150,19 +157,12 @@ static int stripe_ctr(struct dm_target *ti, int argc, char **argv) * Get the stripe destinations. */ for (i = 0; i < stripes; i++) { - if (argc < 2) { - ti->error = "dm-stripe: Not enough destinations " - "specified"; - kfree(sc); - return -EINVAL; - } - argv += 2; r = get_stripe(ti, sc, i, argv); if (r < 0) { ti->error = "dm-stripe: Couldn't parse stripe " - "destination"; + "destination"; while (i--) dm_put_device(ti, sc->stripe[i].dev); kfree(sc); @@ -185,7 +185,8 @@ static void stripe_dtr(struct dm_target *ti) kfree(sc); } -static int stripe_map(struct dm_target *ti, struct buffer_head *bh, int rw) +static int stripe_map(struct dm_target *ti, struct buffer_head *bh, int rw, + void **context) { struct stripe_c *sc = (struct stripe_c *) ti->private; @@ -216,11 +217,11 @@ static int stripe_status(struct dm_target *ti, offset = snprintf(result, maxlen, "%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1); for (i = 0; i < sc->stripes; i++) { - offset += snprintf(result + offset, maxlen - offset, - " %s " SECTOR_FORMAT, - kdevname(to_kdev_t - (sc->stripe[i].dev->bdev->bd_dev)), - sc->stripe[i].physical_start); + offset += + snprintf(result + offset, maxlen - offset, + " %s " SECTOR_FORMAT, + kdevname(to_kdev_t(sc->stripe[i].dev->bdev->bd_dev)), + sc->stripe[i].physical_start); } break; } diff --git a/kernel/common/dm-table.c b/kernel/common/dm-table.c index 07417ef..dedc4ea 100644 --- a/kernel/common/dm-table.c +++ b/kernel/common/dm-table.c @@ -204,12 +204,12 @@ void table_destroy(struct dm_table *t) /* free the targets */ for (i = 0; i < t->num_targets; i++) { - struct dm_target *tgt = &t->targets[i]; - - dm_put_target_type(t->targets[i].type); + struct dm_target *tgt = t->targets + i; if (tgt->type->dtr) tgt->type->dtr(tgt); + + dm_put_target_type(tgt->type); } vfree(t->highs); @@ -507,9 +507,8 @@ static int split_args(int max, int *argc, char **argv, char *input) int dm_table_add_target(struct dm_table *t, const char *type, sector_t start, sector_t len, char *params) { - int r, argc; + int r = -EINVAL, argc; char *argv[32]; - struct target_type *tt; struct dm_target *tgt; if ((r = check_space(t))) @@ -518,14 +517,13 @@ int dm_table_add_target(struct dm_table *t, const char *type, tgt = t->targets + t->num_targets; memset(tgt, 0, sizeof(*tgt)); - tt = dm_get_target_type(type); - if (!tt) { + tgt->type = dm_get_target_type(type); + if (!tgt->type) { tgt->error = "unknown target type"; - return -EINVAL; + goto bad; } tgt->table = t; - tgt->type = tt; tgt->begin = start; tgt->len = len; tgt->error = "Unknown error"; @@ -534,26 +532,27 @@ int dm_table_add_target(struct dm_table *t, const char *type, * Does this target adjoin the previous one ? */ if (!adjoin(t, tgt)) { - DMERR("Gap in table"); - dm_put_target_type(tt); - return -EINVAL; + tgt->error = "Gap in table"; + goto bad; } r = split_args(ARRAY_SIZE(argv), &argc, argv, params); if (r) { tgt->error = "couldn't split parameters"; - dm_put_target_type(tt); - return r; + goto bad; } - r = tt->ctr(tgt, argc, argv); - if (r) { - dm_put_target_type(tt); - return r; - } + r = tgt->type->ctr(tgt, argc, argv); + if (r) + goto bad; t->highs[t->num_targets++] = tgt->begin + tgt->len - 1; return 0; + + bad: + printk(KERN_ERR DM_NAME ": %s\n", tgt->error); + dm_put_target_type(tgt->type); + return r; } static int setup_indexes(struct dm_table *t) @@ -663,3 +662,4 @@ void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq) EXPORT_SYMBOL(dm_get_device); EXPORT_SYMBOL(dm_put_device); EXPORT_SYMBOL(dm_table_event); +EXPORT_SYMBOL(dm_table_get_mode); diff --git a/kernel/common/dm-target.c b/kernel/common/dm-target.c index 569d048..fcbd0ca 100644 --- a/kernel/common/dm-target.c +++ b/kernel/common/dm-target.c @@ -18,7 +18,7 @@ struct tt_internal { }; static LIST_HEAD(_targets); -static rwlock_t _lock = RW_LOCK_UNLOCKED; +static DECLARE_RWSEM(_lock); #define DM_MOD_NAME_SIZE 32 @@ -41,7 +41,7 @@ static struct tt_internal *get_target_type(const char *name) { struct tt_internal *ti; - read_lock(&_lock); + down_read(&_lock); ti = __find_target_type(name); if (ti) { @@ -49,7 +49,7 @@ static struct tt_internal *get_target_type(const char *name) __MOD_INC_USE_COUNT(ti->tt.module); ti->use++; } - read_unlock(&_lock); + up_read(&_lock); return ti; } @@ -64,8 +64,6 @@ static void load_module(const char *name) strcat(module_name, name); request_module(module_name); - - return; } struct target_type *dm_get_target_type(const char *name) @@ -84,13 +82,13 @@ void dm_put_target_type(struct target_type *t) { struct tt_internal *ti = (struct tt_internal *) t; - read_lock(&_lock); + down_read(&_lock); if (--ti->use == 0 && ti->tt.module) __MOD_DEC_USE_COUNT(ti->tt.module); if (ti->use < 0) BUG(); - read_unlock(&_lock); + up_read(&_lock); return; } @@ -115,13 +113,13 @@ int dm_register_target(struct target_type *t) if (!ti) return -ENOMEM; - write_lock(&_lock); + down_write(&_lock); if (__find_target_type(t->name)) rv = -EEXIST; else list_add(&ti->list, &_targets); - write_unlock(&_lock); + up_write(&_lock); return rv; } @@ -129,21 +127,21 @@ int dm_unregister_target(struct target_type *t) { struct tt_internal *ti; - write_lock(&_lock); + down_write(&_lock); if (!(ti = __find_target_type(t->name))) { - write_unlock(&_lock); + up_write(&_lock); return -EINVAL; } if (ti->use) { - write_unlock(&_lock); + up_write(&_lock); return -ETXTBSY; } list_del(&ti->list); kfree(ti); - write_unlock(&_lock); + up_write(&_lock); return 0; } @@ -159,13 +157,12 @@ static int io_err_ctr(struct dm_target *ti, int argc, char **args) static void io_err_dtr(struct dm_target *ti) { /* empty */ - return; } -static int io_err_map(struct dm_target *ti, struct buffer_head *bh, int rw) +static int io_err_map(struct dm_target *ti, struct buffer_head *bh, int rw, + void **map_context) { - buffer_IO_error(bh); - return 0; + return -EIO; } static struct target_type error_target = { diff --git a/kernel/common/dm.c b/kernel/common/dm.c index d1542ee..7928859 100644 --- a/kernel/common/dm.c +++ b/kernel/common/dm.c @@ -28,6 +28,9 @@ static int _major = 0; struct dm_io { struct mapped_device *md; + struct dm_target *ti; + int rw; + void *map_context; void (*end_io) (struct buffer_head * bh, int uptodate); void *context; }; @@ -62,11 +65,15 @@ struct mapped_device { * The current mapping. */ struct dm_table *map; + + /* + * io objects are allocated from here. + */ + mempool_t *io_pool; }; #define MIN_IOS 256 static kmem_cache_t *_io_cache; -static mempool_t *_io_pool; /* block device arrays */ static int _block_size[MAX_DEVICES]; @@ -77,7 +84,6 @@ static struct mapped_device *get_kdev(kdev_t dev); static int dm_request(request_queue_t *q, int rw, struct buffer_head *bh); static int dm_user_bmap(struct inode *inode, struct lv_bmap *lvb); - static __init int local_init(void) { int r; @@ -89,18 +95,10 @@ static __init int local_init(void) if (!_io_cache) return -ENOMEM; - _io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, - mempool_free_slab, _io_cache); - if (!_io_pool) { - kmem_cache_destroy(_io_cache); - return -ENOMEM; - } - _major = major; r = register_blkdev(_major, _name, &dm_blk_dops); if (r < 0) { DMERR("register_blkdev failed"); - mempool_destroy(_io_pool); kmem_cache_destroy(_io_cache); return r; } @@ -121,7 +119,6 @@ static __init int local_init(void) static void local_exit(void) { - mempool_destroy(_io_pool); kmem_cache_destroy(_io_cache); if (unregister_blkdev(_major, _name) < 0) @@ -209,14 +206,14 @@ static int dm_blk_close(struct inode *inode, struct file *file) return 0; } -static inline struct dm_io *alloc_io(void) +static inline struct dm_io *alloc_io(struct mapped_device *md) { - return mempool_alloc(_io_pool, GFP_NOIO); + return mempool_alloc(md->io_pool, GFP_NOIO); } -static inline void free_io(struct dm_io *io) +static inline void free_io(struct mapped_device *md, struct dm_io *io) { - mempool_free(io, _io_pool); + mempool_free(io, md->io_pool); } static inline struct deferred_io *alloc_deferred(void) @@ -297,7 +294,7 @@ static int queue_io(struct mapped_device *md, struct buffer_head *bh, int rw) down_write(&md->lock); - if (!test_bit(DMF_SUSPENDED, &md->flags)) { + if (!test_bit(DMF_BLOCK_IO, &md->flags)) { up_write(&md->lock); free_deferred(di); return 1; @@ -318,7 +315,20 @@ static int queue_io(struct mapped_device *md, struct buffer_head *bh, int rw) */ static void dec_pending(struct buffer_head *bh, int uptodate) { + int r; struct dm_io *io = bh->b_private; + dm_endio_fn endio = io->ti->type->end_io; + + if (endio) { + r = endio(io->ti, bh, io->rw, uptodate ? 0 : -EIO, + io->map_context); + if (r < 0) + uptodate = 0; + + else if (r > 0) + /* the target wants another shot at the io */ + return; + } if (atomic_dec_and_test(&io->md->pending)) /* nudge anyone waiting on suspend queue */ @@ -326,7 +336,7 @@ static void dec_pending(struct buffer_head *bh, int uptodate) bh->b_end_io = io->end_io; bh->b_private = io->context; - free_io(io); + free_io(io->md, io); bh->b_end_io(bh, uptodate); } @@ -335,35 +345,28 @@ static void dec_pending(struct buffer_head *bh, int uptodate) * Do the bh mapping for a given leaf */ static inline int __map_buffer(struct mapped_device *md, - int rw, struct buffer_head *bh) + int rw, struct buffer_head *bh, struct dm_io *io) { int r; - struct dm_io *io; struct dm_target *ti; ti = dm_table_find_target(md->map, bh->b_rsector); if (!ti) return -EINVAL; - io = alloc_io(); - if (!io) - return -ENOMEM; - - io->md = md; - io->end_io = bh->b_end_io; - io->context = bh->b_private; - - r = ti->type->map(ti, bh, rw); + r = ti->type->map(ti, bh, rw, &io->map_context); - if (r > 0) { + if (r >= 0) { /* hook the end io request fn */ atomic_inc(&md->pending); + io->md = md; + io->ti = ti; + io->rw = rw; + io->end_io = bh->b_end_io; + io->context = bh->b_private; bh->b_end_io = dec_pending; bh->b_private = io; - - } else - /* we don't need to hook */ - free_io(io); + } return r; } @@ -409,6 +412,7 @@ static inline int __deferring(struct mapped_device *md, int rw, static int dm_request(request_queue_t *q, int rw, struct buffer_head *bh) { int r; + struct dm_io *io; struct mapped_device *md; md = get_kdev(bh->b_rdev); @@ -417,6 +421,7 @@ static int dm_request(request_queue_t *q, int rw, struct buffer_head *bh) return 0; } + io = alloc_io(md); down_read(&md->lock); r = __deferring(md, rw, bh); @@ -425,7 +430,7 @@ static int dm_request(request_queue_t *q, int rw, struct buffer_head *bh) else if (!r) { /* not deferring */ - r = __map_buffer(md, rw, bh); + r = __map_buffer(md, rw, bh, io); if (r < 0) goto bad; } else @@ -436,6 +441,7 @@ static int dm_request(request_queue_t *q, int rw, struct buffer_head *bh) return r; bad: + free_io(md, io); buffer_IO_error(bh); up_read(&md->lock); dm_put(md); @@ -460,6 +466,7 @@ static int __bmap(struct mapped_device *md, kdev_t dev, unsigned long block, { struct buffer_head bh; struct dm_target *ti; + void *map_context; int r; if (test_bit(DMF_BLOCK_IO, &md->flags)) { @@ -481,7 +488,8 @@ static int __bmap(struct mapped_device *md, kdev_t dev, unsigned long block, ti = dm_table_find_target(md->map, bh.b_rsector); /* do the mapping */ - r = ti->type->map(ti, &bh, READ); + r = ti->type->map(ti, &bh, READ, &map_context); + ti->type->end_io(ti, &bh, READ, 0, map_context); if (!r) { *r_dev = bh.b_rdev; @@ -608,6 +616,15 @@ static struct mapped_device *alloc_dev(int minor) } memset(md, 0, sizeof(*md)); + + md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, + mempool_free_slab, _io_cache); + if (!md->io_pool) { + free_minor(minor); + kfree(md); + return NULL; + } + md->dev = mk_kdev(_major, minor); init_rwsem(&md->lock); atomic_set(&md->holders, 1); @@ -620,6 +637,7 @@ static struct mapped_device *alloc_dev(int minor) static void free_dev(struct mapped_device *md) { free_minor(minor(md->dev)); + mempool_destroy(md->io_pool); kfree(md); } @@ -769,15 +787,14 @@ int dm_suspend(struct mapped_device *md) } set_bit(DMF_BLOCK_IO, &md->flags); + add_wait_queue(&md->wait, &wait); up_write(&md->lock); /* * Then we wait for the already mapped ios to * complete. */ - down_read(&md->lock); - - add_wait_queue(&md->wait, &wait); + run_task_queue(&tq_disk); while (1) { set_current_state(TASK_INTERRUPTIBLE); @@ -788,11 +805,11 @@ int dm_suspend(struct mapped_device *md) } current->state = TASK_RUNNING; - remove_wait_queue(&md->wait, &wait); - up_read(&md->lock); - /* set_bit is atomic */ + down_write(&md->lock); + remove_wait_queue(&md->wait, &wait); set_bit(DMF_SUSPENDED, &md->flags); + up_write(&md->lock); return 0; } @@ -802,8 +819,7 @@ int dm_resume(struct mapped_device *md) struct deferred_io *def; down_write(&md->lock); - if (!test_bit(DMF_SUSPENDED, &md->flags) || - !dm_table_get_size(md->map)) { + if (!test_bit(DMF_SUSPENDED, &md->flags) || !dm_table_get_size(md->map)) { up_write(&md->lock); return -EINVAL; } diff --git a/kernel/common/kcopyd.c b/kernel/common/kcopyd.c index a9ba802..57c759e 100644 --- a/kernel/common/kcopyd.c +++ b/kernel/common/kcopyd.c @@ -65,8 +65,10 @@ static int init_pages(void) return 0; bad: - while (i--) + while (i--) { + UnlockPage(_pages_array[i]); __free_page(_pages_array[i]); + } return -ENOMEM; } @@ -334,7 +336,6 @@ static void dispatch_bh(struct kcopyd_job *job, p = block >> job->bpp_shift; block &= job->bpp_mask; - bh->b_dev = B_FREE; bh->b_size = job->block_size; set_bh_page(bh, job->pages[p], ((block << job->block_shift) + job->offset) << SECTOR_SHIFT); @@ -343,9 +344,11 @@ static void dispatch_bh(struct kcopyd_job *job, init_buffer(bh, end_bh, job); bh->b_dev = job->disk.dev; - bh->b_state = ((1 << BH_Mapped) | (1 << BH_Lock) | (1 << BH_Req)); + atomic_set(&bh->b_count, 1); + + bh->b_state = ((1 << BH_Uptodate) | (1 << BH_Mapped) | + (1 << BH_Lock) | (1 << BH_Req)); - set_bit(BH_Uptodate, &bh->b_state); if (job->rw == WRITE) clear_bit(BH_Dirty, &bh->b_state); @@ -404,7 +407,7 @@ static int run_pages_job(struct kcopyd_job *job) } if (r == -ENOMEM) - /* can complete now */ + /* can't complete now */ return 1; return r; @@ -657,8 +660,10 @@ void copy_write(struct kcopyd_job *job) { struct copy_info *info = (struct copy_info *) job->context; - if (job->err && info->notify) { - info->notify(job->err, job->context); + if (job->err) { + if (info->notify) + info->notify(job->err, job->context); + kcopyd_free_job(job); free_copy_info(info); return; @@ -667,7 +672,6 @@ void copy_write(struct kcopyd_job *job) job->rw = WRITE; memcpy(&job->disk, &info->to, sizeof(job->disk)); job->callback = copy_complete; - job->context = info; /* * Queue the write. @@ -714,7 +718,6 @@ int kcopyd_write_pages(struct kcopyd_region *to, int nr_pages, memcpy(&job->disk, &info->to, sizeof(job->disk)); job->offset = offset; - calc_block_sizes(job); job->callback = page_write_complete; job->context = info; @@ -755,7 +758,6 @@ int kcopyd_copy(struct kcopyd_region *from, struct kcopyd_region *to, memcpy(&job->disk, from, sizeof(*from)); job->offset = 0; - calc_block_sizes(job); job->callback = copy_write; job->context = info; diff --git a/kernel/common/kcopyd.h b/kernel/common/kcopyd.h index c927ca8..cd8d865 100644 --- a/kernel/common/kcopyd.h +++ b/kernel/common/kcopyd.h @@ -66,7 +66,7 @@ struct kcopyd_job { * Set this to ensure you are notified when the job has * completed. 'context' is for callback to use. */ - void (*callback) (struct kcopyd_job *job); + void (*callback) (struct kcopyd_job * job); void *context; }; diff --git a/kernel/ioctl/dm-ioctl.c b/kernel/ioctl/dm-ioctl.c index fc5981a..52ed81b 100644 --- a/kernel/ioctl/dm-ioctl.c +++ b/kernel/ioctl/dm-ioctl.c @@ -14,6 +14,7 @@ #include #include #include + #include #define DM_DRIVER_EMAIL "dm@uk.sistina.com" @@ -314,7 +315,6 @@ int dm_hash_rename(const char *old, const char *new) return 0; } - /*----------------------------------------------------------------- * Implementation of the ioctl commands *---------------------------------------------------------------*/ @@ -323,7 +323,7 @@ int dm_hash_rename(const char *old, const char *new) * All the ioctl commands get dispatched to functions with this * prototype. */ -typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user); +typedef int (*ioctl_fn) (struct dm_ioctl * param, struct dm_ioctl * user); /* * Check a string doesn't overrun the chunk of @@ -817,6 +817,24 @@ static int remove(struct dm_ioctl *param, struct dm_ioctl *user) return -EINVAL; } + /* + * You may ask the interface to drop its reference to an + * in use device. This is no different to unlinking a + * file that someone still has open. The device will not + * actually be destroyed until the last opener closes it. + * The name and uuid of the device (both are interface + * properties) will be available for reuse immediately. + * + * You don't want to drop a _suspended_ device from the + * interface, since that will leave you with no way of + * resuming it. + */ + if (dm_suspended(hc->md)) { + DMWARN("refusing to remove a suspended device."); + up_write(&_hash_lock); + return -EPERM; + } + __hash_remove(hc); up_write(&_hash_lock); return 0; @@ -875,6 +893,7 @@ static int reload(struct dm_ioctl *param, struct dm_ioctl *user) dm_table_put(t); return r; } + dm_table_put(t); /* md will have taken its own reference */ dev = dm_kdev(md); set_device_ro(dev, (param->flags & DM_READONLY_FLAG)); @@ -902,7 +921,6 @@ static int rename(struct dm_ioctl *param, struct dm_ioctl *user) return dm_hash_rename(param->name, new_name); } - /*----------------------------------------------------------------- * Implementation of open/close/ioctl on the special char * device. @@ -1069,8 +1087,8 @@ static int ctl_ioctl(struct inode *inode, struct file *file, } static struct file_operations _ctl_fops = { - .ioctl = ctl_ioctl, - .owner = THIS_MODULE, + .ioctl = ctl_ioctl, + .owner = THIS_MODULE, }; static devfs_handle_t _ctl_handle; @@ -1125,15 +1143,15 @@ int __init dm_interface_init(void) return 0; failed: - dm_hash_exit(); misc_deregister(&_dm_misc); + dm_hash_exit(); return r; } void dm_interface_exit(void) { - dm_hash_exit(); - if (misc_deregister(&_dm_misc) < 0) DMERR("misc_deregister failed for control device"); + + dm_hash_exit(); } diff --git a/kernel/ioctl/dm-ioctl.h b/kernel/ioctl/dm-ioctl.h index d64e9e9..2bacfd9 100644 --- a/kernel/ioctl/dm-ioctl.h +++ b/kernel/ioctl/dm-ioctl.h @@ -131,8 +131,8 @@ enum { #define DM_VERSION_MAJOR 1 #define DM_VERSION_MINOR 0 -#define DM_VERSION_PATCHLEVEL 8 -#define DM_VERSION_EXTRA "-ioctl-cvs (2002-11-21)" +#define DM_VERSION_PATCHLEVEL 9 +#define DM_VERSION_EXTRA "-ioctl (2003-01-21)" /* Status bits */ #define DM_READONLY_FLAG 0x00000001 -- 2.43.5