]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/md/dm-mpath.c
Merge tag 'jg-20061012-00' of git://electric-eye.fr.zoreil.com/home/romieu/linux...
[linux-2.6-omap-h63xx.git] / drivers / md / dm-mpath.c
index f72a82fb943489872b3d91abdffe4cb292c92267..d754e0bc6e90c09f8ea73311e509e3d0a88f707d 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/workqueue.h>
 #include <asm/atomic.h>
 
+#define DM_MSG_PREFIX "multipath"
 #define MESG_STR(x) x, sizeof(x)
 
 /* Path properties */
@@ -113,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;
 }
@@ -132,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;
 }
@@ -167,24 +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);
-               m->mpio_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
-                                             mempool_free_slab, _mpio_cache);
+               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;
@@ -447,8 +444,6 @@ struct param {
        char *error;
 };
 
-#define ESTR(s) ("dm-multipath: " s)
-
 static int read_param(struct param *param, char *str, unsigned *v, char **error)
 {
        if (!str ||
@@ -496,12 +491,12 @@ static int parse_path_selector(struct arg_set *as, struct priority_group *pg,
        unsigned ps_argc;
 
        static struct param _params[] = {
-               {0, 1024, ESTR("invalid number of path selector args")},
+               {0, 1024, "invalid number of path selector args"},
        };
 
        pst = dm_get_path_selector(shift(as));
        if (!pst) {
-               ti->error = ESTR("unknown path selector type");
+               ti->error = "unknown path selector type";
                return -EINVAL;
        }
 
@@ -512,7 +507,7 @@ static int parse_path_selector(struct arg_set *as, struct priority_group *pg,
        r = pst->create(&pg->ps, ps_argc, as->argv);
        if (r) {
                dm_put_path_selector(pst);
-               ti->error = ESTR("path selector constructor failed");
+               ti->error = "path selector constructor failed";
                return r;
        }
 
@@ -530,7 +525,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
 
        /* we need at least a path arg */
        if (as->argc < 1) {
-               ti->error = ESTR("no device given");
+               ti->error = "no device given";
                return NULL;
        }
 
@@ -541,7 +536,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
        r = dm_get_device(ti, shift(as), ti->begin, ti->len,
                          dm_table_get_mode(ti->table), &p->path.dev);
        if (r) {
-               ti->error = ESTR("error getting device");
+               ti->error = "error getting device";
                goto bad;
        }
 
@@ -559,27 +554,27 @@ 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, ESTR("invalid number of paths")},
-               {0, 1024, ESTR("invalid number of selector args")}
+               {1, 1024, "invalid number of paths"},
+               {0, 1024, "invalid number of selector args"}
        };
 
        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;
-               ti->error = ESTR("not enough priority group aruments");
+               ti->error = "not enough priority group aruments";
                return NULL;
        }
 
        pg = alloc_priority_group();
        if (!pg) {
-               ti->error = ESTR("couldn't allocate priority group");
+               ti->error = "couldn't allocate priority group";
                return NULL;
        }
        pg->m = m;
@@ -626,15 +621,15 @@ 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, ESTR("invalid number of hardware handler args")},
+               {0, 1024, "invalid number of hardware handler args"},
        };
 
        r = read_param(_params, shift(as), &hw_argc, &ti->error);
@@ -646,14 +641,14 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m,
 
        hwht = dm_get_hw_handler(shift(as));
        if (!hwht) {
-               ti->error = ESTR("unknown hardware handler type");
+               ti->error = "unknown hardware handler type";
                return -EINVAL;
        }
 
        r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv);
        if (r) {
                dm_put_hw_handler(hwht);
-               ti->error = ESTR("hardware handler constructor failed");
+               ti->error = "hardware handler constructor failed";
                return r;
        }
 
@@ -663,14 +658,14 @@ 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, ESTR("invalid number of feature args")},
+               {0, 1, "invalid number of feature args"},
        };
 
        r = read_param(_params, shift(as), &argc, &ti->error);
@@ -693,8 +688,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
 {
        /* target parameters */
        static struct param _params[] = {
-               {1, 1024, ESTR("invalid number of priority groups")},
-               {1, 1024, ESTR("invalid initial priority group number")},
+               {1, 1024, "invalid number of priority groups"},
+               {1, 1024, "invalid initial priority group number"},
        };
 
        int r;
@@ -706,17 +701,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 = ESTR("can't allocate multipath");
+               ti->error = "can't allocate multipath";
                return -EINVAL;
        }
 
-       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 +727,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;
@@ -747,14 +742,11 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
        }
 
        if (pg_count != m->nr_priority_groups) {
-               ti->error = ESTR("priority group count mismatch");
+               ti->error = "priority group count mismatch";
                r = -EINVAL;
                goto bad;
        }
 
-       ti->private = m;
-       m->ti = ti;
-
        return 0;
 
  bad:
@@ -808,7 +800,7 @@ static int fail_path(struct pgpath *pgpath)
        if (!pgpath->path.is_active)
                goto out;
 
-       DMWARN("dm-multipath: Failing path %s.", pgpath->path.dev->name);
+       DMWARN("Failing path %s.", pgpath->path.dev->name);
 
        pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path);
        pgpath->path.is_active = 0;
@@ -1251,7 +1243,7 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
        r = dm_get_device(ti, argv[1], ti->begin, ti->len,
                          dm_table_get_mode(ti->table), &dev);
        if (r) {
-               DMWARN("dm-multipath message: error getting device %s",
+               DMWARN("message: error getting device %s",
                       argv[1]);
                return -EINVAL;
        }
@@ -1267,12 +1259,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_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,
@@ -1282,6 +1309,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)
@@ -1310,7 +1338,7 @@ static int __init dm_multipath_init(void)
                return -ENOMEM;
        }
 
-       DMINFO("dm-multipath version %u.%u.%u loaded",
+       DMINFO("version %u.%u.%u loaded",
               multipath_target.version[0], multipath_target.version[1],
               multipath_target.version[2]);