sched: Remove proliferation of wait_on_bit() action functions
[deliverable/linux.git] / drivers / md / dm-snap.c
index 8e0caed0bf74650d85279b9331d1b1fec132058f..864b03f477276f9c01bee8fd34a25e2303af1116 100644 (file)
@@ -1032,21 +1032,13 @@ static void start_merge(struct dm_snapshot *s)
                snapshot_merge_next_chunks(s);
 }
 
-static int wait_schedule(void *ptr)
-{
-       schedule();
-
-       return 0;
-}
-
 /*
  * Stop the merging process and wait until it finishes.
  */
 static void stop_merge(struct dm_snapshot *s)
 {
        set_bit(SHUTDOWN_MERGE, &s->state_bits);
-       wait_on_bit(&s->state_bits, RUNNING_MERGE, wait_schedule,
-                   TASK_UNINTERRUPTIBLE);
+       wait_on_bit(&s->state_bits, RUNNING_MERGE, TASK_UNINTERRUPTIBLE);
        clear_bit(SHUTDOWN_MERGE, &s->state_bits);
 }
 
@@ -2141,6 +2133,11 @@ static int origin_write_extent(struct dm_snapshot *merging_snap,
  * Origin: maps a linear range of a device, with hooks for snapshotting.
  */
 
+struct dm_origin {
+       struct dm_dev *dev;
+       unsigned split_boundary;
+};
+
 /*
  * Construct an origin mapping: <dev_path>
  * The context for an origin is merely a 'struct dm_dev *'
@@ -2149,41 +2146,65 @@ static int origin_write_extent(struct dm_snapshot *merging_snap,
 static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
        int r;
-       struct dm_dev *dev;
+       struct dm_origin *o;
 
        if (argc != 1) {
                ti->error = "origin: incorrect number of arguments";
                return -EINVAL;
        }
 
-       r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev);
+       o = kmalloc(sizeof(struct dm_origin), GFP_KERNEL);
+       if (!o) {
+               ti->error = "Cannot allocate private origin structure";
+               r = -ENOMEM;
+               goto bad_alloc;
+       }
+
+       r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &o->dev);
        if (r) {
                ti->error = "Cannot get target device";
-               return r;
+               goto bad_open;
        }
 
-       ti->private = dev;
+       ti->private = o;
        ti->num_flush_bios = 1;
 
        return 0;
+
+bad_open:
+       kfree(o);
+bad_alloc:
+       return r;
 }
 
 static void origin_dtr(struct dm_target *ti)
 {
-       struct dm_dev *dev = ti->private;
-       dm_put_device(ti, dev);
+       struct dm_origin *o = ti->private;
+       dm_put_device(ti, o->dev);
+       kfree(o);
 }
 
 static int origin_map(struct dm_target *ti, struct bio *bio)
 {
-       struct dm_dev *dev = ti->private;
-       bio->bi_bdev = dev->bdev;
+       struct dm_origin *o = ti->private;
+       unsigned available_sectors;
 
-       if (bio->bi_rw & REQ_FLUSH)
+       bio->bi_bdev = o->dev->bdev;
+
+       if (unlikely(bio->bi_rw & REQ_FLUSH))
+               return DM_MAPIO_REMAPPED;
+
+       if (bio_rw(bio) != WRITE)
                return DM_MAPIO_REMAPPED;
 
+       available_sectors = o->split_boundary -
+               ((unsigned)bio->bi_iter.bi_sector & (o->split_boundary - 1));
+
+       if (bio_sectors(bio) > available_sectors)
+               dm_accept_partial_bio(bio, available_sectors);
+
        /* Only tell snapshots if this is a write */
-       return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
+       return do_origin(o->dev, bio);
 }
 
 /*
@@ -2192,15 +2213,15 @@ static int origin_map(struct dm_target *ti, struct bio *bio)
  */
 static void origin_resume(struct dm_target *ti)
 {
-       struct dm_dev *dev = ti->private;
+       struct dm_origin *o = ti->private;
 
-       ti->max_io_len = get_origin_minimum_chunksize(dev->bdev);
+       o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev);
 }
 
 static void origin_status(struct dm_target *ti, status_type_t type,
                          unsigned status_flags, char *result, unsigned maxlen)
 {
-       struct dm_dev *dev = ti->private;
+       struct dm_origin *o = ti->private;
 
        switch (type) {
        case STATUSTYPE_INFO:
@@ -2208,7 +2229,7 @@ static void origin_status(struct dm_target *ti, status_type_t type,
                break;
 
        case STATUSTYPE_TABLE:
-               snprintf(result, maxlen, "%s", dev->name);
+               snprintf(result, maxlen, "%s", o->dev->name);
                break;
        }
 }
@@ -2216,13 +2237,13 @@ static void origin_status(struct dm_target *ti, status_type_t type,
 static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
                        struct bio_vec *biovec, int max_size)
 {
-       struct dm_dev *dev = ti->private;
-       struct request_queue *q = bdev_get_queue(dev->bdev);
+       struct dm_origin *o = ti->private;
+       struct request_queue *q = bdev_get_queue(o->dev->bdev);
 
        if (!q->merge_bvec_fn)
                return max_size;
 
-       bvm->bi_bdev = dev->bdev;
+       bvm->bi_bdev = o->dev->bdev;
 
        return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
 }
@@ -2230,9 +2251,9 @@ static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
 static int origin_iterate_devices(struct dm_target *ti,
                                  iterate_devices_callout_fn fn, void *data)
 {
-       struct dm_dev *dev = ti->private;
+       struct dm_origin *o = ti->private;
 
-       return fn(ti, dev, 0, ti->len, data);
+       return fn(ti, o->dev, 0, ti->len, data);
 }
 
 static struct target_type origin_target = {
This page took 0.035025 seconds and 5 git commands to generate.