]> sourceware.org Git - dm.git/commitdiff
Update to 2.4.20-dm-7 (with 3 DMWARNs removed)
authorAlasdair Kergon <agk@redhat.com>
Tue, 21 Jan 2003 21:34:45 +0000 (21:34 +0000)
committerAlasdair Kergon <agk@redhat.com>
Tue, 21 Jan 2003 21:34:45 +0000 (21:34 +0000)
kernel/common/device-mapper.h
kernel/common/dm-linear.c
kernel/common/dm-snapshot.c
kernel/common/dm-stripe.c
kernel/common/dm-table.c
kernel/common/dm-target.c
kernel/common/dm.c
kernel/common/kcopyd.c
kernel/common/kcopyd.h
kernel/ioctl/dm-ioctl.c
kernel/ioctl/dm-ioctl.h

index 5a51622a3e8708e57cc27d029d98bac8b68161a3..a42cf692057ea272b645712a2c5293dfb470bb91 100644 (file)
@@ -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 */
index 9a7f60a2832bc126edbded3ed7012e29bb3ddbd3..5bdb440afe1b6c5b684b63390fbf18bc0e5740d2 100644 (file)
@@ -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;
 
index 232abf10e36c975b3b810fcedeeeaedcae0c51e3..8f7f3192eec6e2bc6fa471462ad3cba1a5e40cc6 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -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;
index b074039bdddd8b2a9a6de4935bbdbeec9c706218..40d0bc2baf42ad6edcd2a829b6694ee26dce0041 100644 (file)
@@ -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;
        }
index 07417efb994b24c80226f365e093f2b25d019bc0..dedc4ea9c5cadf025944df1384903efd1aa46969 100644 (file)
@@ -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);
index 569d04828ed78592e26a07f313f6f4cc6a763acc..fcbd0ca5e8b68409ce4e1e918586be6f488caea4 100644 (file)
@@ -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 = {
index d1542ee93d15a447f38102aa9e32191abaa1c6af..7928859653bb0c22cd60bcc24258944a582948e6 100644 (file)
@@ -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;
        }
index a9ba80230cd2d2d6e07d2d2f1659269aaed212aa..57c759eeb6b6b5c349c9e3d0409ce711c3bf908b 100644 (file)
@@ -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;
 
index c927ca8608d41475097c86673c7700e79d463a1f..cd8d865d63394b514f283c40a511ae91a28e9d16 100644 (file)
@@ -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;
 };
 
index fc5981a1835146e294cc8a8fc6fb0994c2b2aa00..52ed81beddbf3194028bbaf990387e3770eff3c6 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/wait.h>
 #include <linux/blk.h>
 #include <linux/slab.h>
+
 #include <asm/uaccess.h>
 
 #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();
 }
index d64e9e93306ab438c643a55c41f04168c064b58b..2bacfd9f46f678ba9a7829e78f33a8b947e2207b 100644 (file)
@@ -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
This page took 0.057996 seconds and 5 git commands to generate.