dm: export suspended state to targets
[safe/jmp/linux-2.6] / drivers / md / dm.c
index 255b75c..3167480 100644 (file)
@@ -415,7 +415,7 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
 
        tgt = dm_table_get_target(map, 0);
 
-       if (dm_suspended(md)) {
+       if (dm_suspended_md(md)) {
                r = -EAGAIN;
                goto out;
        }
@@ -1618,6 +1618,8 @@ static void map_request(struct dm_target *ti, struct request *clone,
                break;
        case DM_MAPIO_REMAPPED:
                /* The target has remapped the I/O so dispatch it */
+               trace_block_rq_remap(clone->q, clone, disk_devt(dm_disk(md)),
+                                    blk_rq_pos(tio->orig));
                dm_dispatch_request(clone);
                break;
        case DM_MAPIO_REQUEUE:
@@ -2033,9 +2035,13 @@ static void __set_size(struct mapped_device *md, sector_t size)
        mutex_unlock(&md->bdev->bd_inode->i_mutex);
 }
 
-static int __bind(struct mapped_device *md, struct dm_table *t,
-                 struct queue_limits *limits)
+/*
+ * Returns old map, which caller must destroy.
+ */
+static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
+                              struct queue_limits *limits)
 {
+       struct dm_table *old_map;
        struct request_queue *q = md->queue;
        sector_t size;
        unsigned long flags;
@@ -2050,11 +2056,6 @@ static int __bind(struct mapped_device *md, struct dm_table *t,
 
        __set_size(md, size);
 
-       if (!size) {
-               dm_table_destroy(t);
-               return 0;
-       }
-
        dm_table_event_callback(t, event_callback, md);
 
        /*
@@ -2070,11 +2071,12 @@ static int __bind(struct mapped_device *md, struct dm_table *t,
        __bind_mempools(md, t);
 
        write_lock_irqsave(&md->map_lock, flags);
+       old_map = md->map;
        md->map = t;
        dm_table_set_restrictions(t, q, limits);
        write_unlock_irqrestore(&md->map_lock, flags);
 
-       return 0;
+       return old_map;
 }
 
 /*
@@ -2180,7 +2182,7 @@ void dm_put(struct mapped_device *md)
                            MINOR(disk_devt(dm_disk(md))));
                set_bit(DMF_FREEING, &md->flags);
                spin_unlock(&_minor_lock);
-               if (!dm_suspended(md)) {
+               if (!dm_suspended_md(md)) {
                        dm_table_presuspend_targets(map);
                        dm_table_postsuspend_targets(map);
                }
@@ -2368,23 +2370,25 @@ static void dm_rq_barrier_work(struct work_struct *work)
 }
 
 /*
- * Swap in a new table (destroying old one).
+ * Swap in a new table, returning the old one for the caller to destroy.
  */
-int dm_swap_table(struct mapped_device *md, struct dm_table *table)
+struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
 {
-       struct dm_table *map;
+       struct dm_table *map = ERR_PTR(-EINVAL);
        struct queue_limits limits;
-       int r = -EINVAL;
+       int r;
 
        mutex_lock(&md->suspend_lock);
 
        /* device must be suspended */
-       if (!dm_suspended(md))
+       if (!dm_suspended_md(md))
                goto out;
 
        r = dm_calculate_queue_limits(table, &limits);
-       if (r)
+       if (r) {
+               map = ERR_PTR(r);
                goto out;
+       }
 
        /* cannot change the device type, once a table is bound */
        if (md->map &&
@@ -2393,13 +2397,11 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table)
                goto out;
        }
 
-       map = __unbind(md);
-       r = __bind(md, table, &limits);
-       dm_table_destroy(map);
+       map = __bind(md, table, &limits);
 
 out:
        mutex_unlock(&md->suspend_lock);
-       return r;
+       return map;
 }
 
 /*
@@ -2459,7 +2461,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
 
        mutex_lock(&md->suspend_lock);
 
-       if (dm_suspended(md)) {
+       if (dm_suspended_md(md)) {
                r = -EINVAL;
                goto out_unlock;
        }
@@ -2548,10 +2550,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
         * requests are being added to md->deferred list.
         */
 
-       dm_table_postsuspend_targets(map);
-
        set_bit(DMF_SUSPENDED, &md->flags);
 
+       dm_table_postsuspend_targets(map);
+
 out:
        dm_table_put(map);
 
@@ -2566,7 +2568,7 @@ int dm_resume(struct mapped_device *md)
        struct dm_table *map = NULL;
 
        mutex_lock(&md->suspend_lock);
-       if (!dm_suspended(md))
+       if (!dm_suspended_md(md))
                goto out;
 
        map = dm_get_live_table(md);
@@ -2677,11 +2679,22 @@ struct mapped_device *dm_get_from_kobject(struct kobject *kobj)
        return md;
 }
 
-int dm_suspended(struct mapped_device *md)
+int dm_suspended_md(struct mapped_device *md)
 {
        return test_bit(DMF_SUSPENDED, &md->flags);
 }
 
+int dm_suspended(struct dm_target *ti)
+{
+       struct mapped_device *md = dm_table_get_md(ti->table);
+       int r = dm_suspended_md(md);
+
+       dm_put(md);
+
+       return r;
+}
+EXPORT_SYMBOL_GPL(dm_suspended);
+
 int dm_noflush_suspending(struct dm_target *ti)
 {
        struct mapped_device *md = dm_table_get_md(ti->table);