Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke...
[safe/jmp/linux-2.6] / drivers / md / dm.c
index c254c6c..d21e128 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;
        }
@@ -635,8 +635,10 @@ static void dec_pending(struct dm_io *io, int error)
                        if (!md->barrier_error && io_error != -EOPNOTSUPP)
                                md->barrier_error = io_error;
                        end_io_acct(io);
+                       free_io(md, io);
                } else {
                        end_io_acct(io);
+                       free_io(md, io);
 
                        if (io_error != DM_ENDIO_REQUEUE) {
                                trace_block_bio_complete(md->queue, bio);
@@ -644,8 +646,6 @@ static void dec_pending(struct dm_io *io, int error)
                                bio_endio(bio, io_error);
                        }
                }
-
-               free_io(md, io);
        }
 }
 
@@ -1595,10 +1595,15 @@ static int dm_prep_fn(struct request_queue *q, struct request *rq)
        return BLKPREP_OK;
 }
 
-static void map_request(struct dm_target *ti, struct request *clone,
-                       struct mapped_device *md)
+/*
+ * Returns:
+ * 0  : the request has been processed (not requeued)
+ * !0 : the request has been requeued
+ */
+static int map_request(struct dm_target *ti, struct request *clone,
+                      struct mapped_device *md)
 {
-       int r;
+       int r, requeued = 0;
        struct dm_rq_target_io *tio = clone->end_io_data;
 
        /*
@@ -1618,11 +1623,14 @@ 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:
                /* The target wants to requeue the I/O */
                dm_requeue_unmapped_request(clone);
+               requeued = 1;
                break;
        default:
                if (r > 0) {
@@ -1634,6 +1642,8 @@ static void map_request(struct dm_target *ti, struct request *clone,
                dm_kill_unmapped_request(clone, r);
                break;
        }
+
+       return requeued;
 }
 
 /*
@@ -1675,12 +1685,17 @@ static void dm_request_fn(struct request_queue *q)
                atomic_inc(&md->pending[rq_data_dir(clone)]);
 
                spin_unlock(q->queue_lock);
-               map_request(ti, clone, md);
+               if (map_request(ti, clone, md))
+                       goto requeued;
+
                spin_lock_irq(q->queue_lock);
        }
 
        goto out;
 
+requeued:
+       spin_lock_irq(q->queue_lock);
+
 plug_and_out:
        if (!elv_queue_empty(q))
                /* Some requests still remain, retry later */
@@ -2180,7 +2195,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);
                }
@@ -2379,7 +2394,7 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
        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);
@@ -2459,7 +2474,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 +2563,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 +2581,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);
@@ -2603,18 +2618,19 @@ out:
 /*-----------------------------------------------------------------
  * Event notification.
  *---------------------------------------------------------------*/
-void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
+int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
                       unsigned cookie)
 {
        char udev_cookie[DM_COOKIE_LENGTH];
        char *envp[] = { udev_cookie, NULL };
 
        if (!cookie)
-               kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
+               return kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
        else {
                snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
                         DM_COOKIE_ENV_VAR_NAME, cookie);
-               kobject_uevent_env(&disk_to_dev(md->disk)->kobj, action, envp);
+               return kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
+                                         action, envp);
        }
 }
 
@@ -2677,19 +2693,20 @@ 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_noflush_suspending(struct dm_target *ti)
+int dm_suspended(struct dm_target *ti)
 {
-       struct mapped_device *md = dm_table_get_md(ti->table);
-       int r = __noflush_suspending(md);
-
-       dm_put(md);
+       return dm_suspended_md(dm_table_get_md(ti->table));
+}
+EXPORT_SYMBOL_GPL(dm_suspended);
 
-       return r;
+int dm_noflush_suspending(struct dm_target *ti)
+{
+       return __noflush_suspending(dm_table_get_md(ti->table));
 }
 EXPORT_SYMBOL_GPL(dm_noflush_suspending);