]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/md/dm-mpath.c
[PATCH] dm: map and endio symbolic return codes
[linux-2.6-omap-h63xx.git] / drivers / md / dm-mpath.c
index 93f701ea87bc3438bf5ab2426b74e5f43085827a..d325edcbb3f5eac5e66911c842870ef8b03a0fbc 100644 (file)
@@ -31,7 +31,7 @@ struct pgpath {
        struct priority_group *pg;      /* Owning PG */
        unsigned fail_count;            /* Cumulative failure count */
 
-       struct path path;
+       struct dm_path path;
 };
 
 #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
@@ -101,11 +101,11 @@ typedef int (*action_fn) (struct pgpath *pgpath);
 
 #define MIN_IOS 256    /* Mempool size */
 
-static kmem_cache_t *_mpio_cache;
+static struct kmem_cache *_mpio_cache;
 
 struct workqueue_struct *kmultipathd;
-static void process_queued_ios(void *data);
-static void trigger_event(void *data);
+static void process_queued_ios(struct work_struct *work);
+static void trigger_event(struct work_struct *work);
 
 
 /*-----------------------------------------------
@@ -114,12 +114,10 @@ static void trigger_event(void *data);
 
 static struct pgpath *alloc_pgpath(void)
 {
-       struct pgpath *pgpath = kmalloc(sizeof(*pgpath), GFP_KERNEL);
+       struct pgpath *pgpath = kzalloc(sizeof(*pgpath), GFP_KERNEL);
 
-       if (pgpath) {
-               memset(pgpath, 0, sizeof(*pgpath));
+       if (pgpath)
                pgpath->path.is_active = 1;
-       }
 
        return pgpath;
 }
@@ -133,12 +131,10 @@ static struct priority_group *alloc_priority_group(void)
 {
        struct priority_group *pg;
 
-       pg = kmalloc(sizeof(*pg), GFP_KERNEL);
-       if (!pg)
-               return NULL;
+       pg = kzalloc(sizeof(*pg), GFP_KERNEL);
 
-       memset(pg, 0, sizeof(*pg));
-       INIT_LIST_HEAD(&pg->pgpaths);
+       if (pg)
+               INIT_LIST_HEAD(&pg->pgpaths);
 
        return pg;
 }
@@ -168,23 +164,24 @@ static void free_priority_group(struct priority_group *pg,
        kfree(pg);
 }
 
-static struct multipath *alloc_multipath(void)
+static struct multipath *alloc_multipath(struct dm_target *ti)
 {
        struct multipath *m;
 
-       m = kmalloc(sizeof(*m), GFP_KERNEL);
+       m = kzalloc(sizeof(*m), GFP_KERNEL);
        if (m) {
-               memset(m, 0, sizeof(*m));
                INIT_LIST_HEAD(&m->priority_groups);
                spin_lock_init(&m->lock);
                m->queue_io = 1;
-               INIT_WORK(&m->process_queued_ios, process_queued_ios, m);
-               INIT_WORK(&m->trigger_event, trigger_event, m);
+               INIT_WORK(&m->process_queued_ios, process_queued_ios);
+               INIT_WORK(&m->trigger_event, trigger_event);
                m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
                if (!m->mpio_pool) {
                        kfree(m);
                        return NULL;
                }
+               m->ti = ti;
+               ti->private = m;
        }
 
        return m;
@@ -232,7 +229,7 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
 
 static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
 {
-       struct path *path;
+       struct dm_path *path;
 
        path = pg->ps.type->select_path(&pg->ps, &m->repeat_count);
        if (!path)
@@ -288,7 +285,7 @@ failed:
 static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
                  unsigned was_queued)
 {
-       int r = 1;
+       int r = DM_MAPIO_REMAPPED;
        unsigned long flags;
        struct pgpath *pgpath;
 
@@ -313,7 +310,7 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
                    !m->queue_io)
                        queue_work(kmultipathd, &m->process_queued_ios);
                pgpath = NULL;
-               r = 0;
+               r = DM_MAPIO_SUBMITTED;
        } else if (!pgpath)
                r = -EIO;               /* Failed */
        else
@@ -375,16 +372,17 @@ static void dispatch_queued_ios(struct multipath *m)
                r = map_io(m, bio, mpio, 1);
                if (r < 0)
                        bio_endio(bio, bio->bi_size, r);
-               else if (r == 1)
+               else if (r == DM_MAPIO_REMAPPED)
                        generic_make_request(bio);
 
                bio = next;
        }
 }
 
-static void process_queued_ios(void *data)
+static void process_queued_ios(struct work_struct *work)
 {
-       struct multipath *m = (struct multipath *) data;
+       struct multipath *m =
+               container_of(work, struct multipath, process_queued_ios);
        struct hw_handler *hwh = &m->hw_handler;
        struct pgpath *pgpath = NULL;
        unsigned init_required = 0, must_queue = 1;
@@ -424,9 +422,10 @@ out:
  * An event is triggered whenever a path is taken out of use.
  * Includes path failure and PG bypass.
  */
-static void trigger_event(void *data)
+static void trigger_event(struct work_struct *work)
 {
-       struct multipath *m = (struct multipath *) data;
+       struct multipath *m =
+               container_of(work, struct multipath, trigger_event);
 
        dm_table_event(m->ti->table);
 }
@@ -557,8 +556,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
 }
 
 static struct priority_group *parse_priority_group(struct arg_set *as,
-                                                  struct multipath *m,
-                                                  struct dm_target *ti)
+                                                  struct multipath *m)
 {
        static struct param _params[] = {
                {1, 1024, "invalid number of paths"},
@@ -568,6 +566,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
        int r;
        unsigned i, nr_selector_args, nr_params;
        struct priority_group *pg;
+       struct dm_target *ti = m->ti;
 
        if (as->argc < 2) {
                as->argc = 0;
@@ -624,12 +623,12 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
        return NULL;
 }
 
-static int parse_hw_handler(struct arg_set *as, struct multipath *m,
-                           struct dm_target *ti)
+static int parse_hw_handler(struct arg_set *as, struct multipath *m)
 {
        int r;
        struct hw_handler_type *hwht;
        unsigned hw_argc;
+       struct dm_target *ti = m->ti;
 
        static struct param _params[] = {
                {0, 1024, "invalid number of hardware handler args"},
@@ -661,11 +660,11 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m,
        return 0;
 }
 
-static int parse_features(struct arg_set *as, struct multipath *m,
-                         struct dm_target *ti)
+static int parse_features(struct arg_set *as, struct multipath *m)
 {
        int r;
        unsigned argc;
+       struct dm_target *ti = m->ti;
 
        static struct param _params[] = {
                {0, 1, "invalid number of feature args"},
@@ -704,19 +703,17 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
        as.argc = argc;
        as.argv = argv;
 
-       m = alloc_multipath();
+       m = alloc_multipath(ti);
        if (!m) {
                ti->error = "can't allocate multipath";
                return -EINVAL;
        }
 
-       m->ti = ti;
-
-       r = parse_features(&as, m, ti);
+       r = parse_features(&as, m);
        if (r)
                goto bad;
 
-       r = parse_hw_handler(&as, m, ti);
+       r = parse_hw_handler(&as, m);
        if (r)
                goto bad;
 
@@ -732,7 +729,7 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
        while (as.argc) {
                struct priority_group *pg;
 
-               pg = parse_priority_group(&as, m, ti);
+               pg = parse_priority_group(&as, m);
                if (!pg) {
                        r = -EINVAL;
                        goto bad;
@@ -752,8 +749,6 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
                goto bad;
        }
 
-       ti->private = m;
-
        return 0;
 
  bad:
@@ -962,7 +957,7 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
 /*
  * pg_init must call this when it has completed its initialisation
  */
-void dm_pg_init_complete(struct path *path, unsigned err_flags)
+void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
 {
        struct pgpath *pgpath = path_to_pgpath(path);
        struct priority_group *pg = pgpath->pg;
@@ -1047,7 +1042,7 @@ static int do_end_io(struct multipath *m, struct bio *bio,
                queue_work(kmultipathd, &m->process_queued_ios);
        spin_unlock_irqrestore(&m->lock, flags);
 
-       return 1;       /* io not complete */
+       return DM_ENDIO_INCOMPLETE;     /* io not complete */
 }
 
 static int multipath_end_io(struct dm_target *ti, struct bio *bio,
@@ -1065,7 +1060,7 @@ static int multipath_end_io(struct dm_target *ti, struct bio *bio,
                if (ps->type->end_io)
                        ps->type->end_io(ps, &pgpath->path);
        }
-       if (r <= 0)
+       if (r != DM_ENDIO_INCOMPLETE)
                mempool_free(mpio, m->mpio_pool);
 
        return r;
@@ -1266,12 +1261,47 @@ error:
        return -EINVAL;
 }
 
+static int multipath_ioctl(struct dm_target *ti, struct inode *inode,
+                          struct file *filp, unsigned int cmd,
+                          unsigned long arg)
+{
+       struct multipath *m = (struct multipath *) ti->private;
+       struct block_device *bdev = NULL;
+       unsigned long flags;
+       struct file fake_file = {};
+       struct dentry fake_dentry = {};
+       int r = 0;
+
+       fake_file.f_path.dentry = &fake_dentry;
+
+       spin_lock_irqsave(&m->lock, flags);
+
+       if (!m->current_pgpath)
+               __choose_pgpath(m);
+
+       if (m->current_pgpath) {
+               bdev = m->current_pgpath->path.dev->bdev;
+               fake_dentry.d_inode = bdev->bd_inode;
+               fake_file.f_mode = m->current_pgpath->path.dev->mode;
+       }
+
+       if (m->queue_io)
+               r = -EAGAIN;
+       else if (!bdev)
+               r = -EIO;
+
+       spin_unlock_irqrestore(&m->lock, flags);
+
+       return r ? : blkdev_driver_ioctl(bdev->bd_inode, &fake_file,
+                                        bdev->bd_disk, cmd, arg);
+}
+
 /*-----------------------------------------------------------------
  * Module setup
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
        .name = "multipath",
-       .version = {1, 0, 4},
+       .version = {1, 0, 5},
        .module = THIS_MODULE,
        .ctr = multipath_ctr,
        .dtr = multipath_dtr,
@@ -1281,6 +1311,7 @@ static struct target_type multipath_target = {
        .resume = multipath_resume,
        .status = multipath_status,
        .message = multipath_message,
+       .ioctl  = multipath_ioctl,
 };
 
 static int __init dm_multipath_init(void)