/*
  * Copyright (C) 2010-2011 Neil Brown
- * Copyright (C) 2010-2014 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the GPL.
  */
        const unsigned level;           /* RAID level. */
        const unsigned algorithm;       /* RAID algorithm. */
 } raid_types[] = {
+       {"raid0",    "RAID0 (striping)",                0, 2, 0, 0 /* NONE */},
        {"raid1",    "RAID1 (mirroring)",               0, 2, 1, 0 /* NONE */},
        {"raid10",   "RAID10 (striped mirrors)",        0, 2, 10, UINT_MAX /* Varies */},
        {"raid4",    "RAID4 (dedicated parity disk)",   1, 2, 5, ALGORITHM_PARITY_0},
                rs->md.layout = raid10_format_to_md_layout(raid10_format,
                                                           raid10_copies);
                rs->md.new_layout = rs->md.layout;
-       } else if ((rs->raid_type->level > 1) &&
+       } else if ((!rs->raid_type->level || rs->raid_type->level > 1) &&
                   sector_div(sectors_per_dev,
                              (rs->md.raid_disks - rs->raid_type->parity_devs))) {
                rs->ti->error = "Target length not divisible by number of data devices";
        return 0;
 }
 
-static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
+static int super_validate(struct raid_set *rs, struct md_rdev *rdev)
 {
+       struct mddev *mddev = &rs->md;
        struct dm_raid_superblock *sb = page_address(rdev->sb_page);
 
        /*
        if (!mddev->events && super_init_validation(mddev, rdev))
                return -EINVAL;
 
-       mddev->bitmap_info.offset = 4096 >> 9; /* Enable bitmap creation */
-       rdev->mddev->bitmap_info.default_offset = 4096 >> 9;
+       /* Enable bitmap creation for RAID levels != 0 */
+       mddev->bitmap_info.offset = (rs->raid_type->level) ? to_sector(4096) : 0;
+       rdev->mddev->bitmap_info.default_offset = mddev->bitmap_info.offset;
+
        if (!test_bit(FirstUse, &rdev->flags)) {
                rdev->recovery_offset = le64_to_cpu(sb->disk_recovery_offset);
                if (rdev->recovery_offset != MaxSector)
                 * that the "sync" directive is disallowed during the
                 * reshape.
                 */
+               rdev->sectors = to_sector(i_size_read(rdev->bdev->bd_inode));
+
                if (rs->ctr_flags & CTR_FLAG_SYNC)
                        continue;
 
         * validation for the remaining devices.
         */
        ti->error = "Unable to assemble array: Invalid superblocks";
-       if (super_validate(mddev, freshest))
+       if (super_validate(rs, freshest))
                return -EINVAL;
 
        rdev_for_each(rdev, mddev)
-               if ((rdev != freshest) && super_validate(mddev, rdev))
+               if ((rdev != freshest) && super_validate(rs, rdev))
                        return -EINVAL;
 
        return 0;
         */
        configure_discard_support(ti, rs);
 
-       mutex_lock(&rs->md.reconfig_mutex);
+       /* Has to be held on running the array */
+       mddev_lock_nointr(&rs->md);
        ret = md_run(&rs->md);
        rs->md.in_sync = 0; /* Assume already marked dirty */
-       mutex_unlock(&rs->md.reconfig_mutex);
+       mddev_unlock(&rs->md);
 
        if (ret) {
                ti->error = "Fail to run raid array";
        case STATUSTYPE_INFO:
                DMEMIT("%s %d ", rs->raid_type->name, rs->md.raid_disks);
 
-               if (test_bit(MD_RECOVERY_RUNNING, &rs->md.recovery))
-                       sync = rs->md.curr_resync_completed;
-               else
-                       sync = rs->md.recovery_cp;
-
-               if (sync >= rs->md.resync_max_sectors) {
-                       /*
-                        * Sync complete.
-                        */
+               if (rs->raid_type->level) {
+                       if (test_bit(MD_RECOVERY_RUNNING, &rs->md.recovery))
+                               sync = rs->md.curr_resync_completed;
+                       else
+                               sync = rs->md.recovery_cp;
+
+                       if (sync >= rs->md.resync_max_sectors) {
+                               /*
+                                * Sync complete.
+                                */
+                               array_in_sync = 1;
+                               sync = rs->md.resync_max_sectors;
+                       } else if (test_bit(MD_RECOVERY_REQUESTED, &rs->md.recovery)) {
+                               /*
+                                * If "check" or "repair" is occurring, the array has
+                                * undergone and initial sync and the health characters
+                                * should not be 'a' anymore.
+                                */
+                               array_in_sync = 1;
+                       } else {
+                               /*
+                                * The array may be doing an initial sync, or it may
+                                * be rebuilding individual components.  If all the
+                                * devices are In_sync, then it is the array that is
+                                * being initialized.
+                                */
+                               for (i = 0; i < rs->md.raid_disks; i++)
+                                       if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+                                               array_in_sync = 1;
+                       }
+               } else {
+                       /* RAID0 */
                        array_in_sync = 1;
                        sync = rs->md.resync_max_sectors;
-               } else if (test_bit(MD_RECOVERY_REQUESTED, &rs->md.recovery)) {
-                       /*
-                        * If "check" or "repair" is occurring, the array has
-                        * undergone and initial sync and the health characters
-                        * should not be 'a' anymore.
-                        */
-                       array_in_sync = 1;
-               } else {
-                       /*
-                        * The array may be doing an initial sync, or it may
-                        * be rebuilding individual components.  If all the
-                        * devices are In_sync, then it is the array that is
-                        * being initialized.
-                        */
-                       for (i = 0; i < rs->md.raid_disks; i++)
-                               if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
-                                       array_in_sync = 1;
                }
 
                /*
 {
        struct raid_set *rs = ti->private;
 
-       set_bit(MD_CHANGE_DEVS, &rs->md.flags);
-       if (!rs->bitmap_loaded) {
-               bitmap_load(&rs->md);
-               rs->bitmap_loaded = 1;
-       } else {
-               /*
-                * A secondary resume while the device is active.
-                * Take this opportunity to check whether any failed
-                * devices are reachable again.
-                */
-               attempt_restore_of_faulty_devices(rs);
+       if (rs->raid_type->level) {
+               set_bit(MD_CHANGE_DEVS, &rs->md.flags);
+
+               if (!rs->bitmap_loaded) {
+                       bitmap_load(&rs->md);
+                       rs->bitmap_loaded = 1;
+               } else {
+                       /*
+                        * A secondary resume while the device is active.
+                        * Take this opportunity to check whether any failed
+                        * devices are reachable again.
+                        */
+                       attempt_restore_of_faulty_devices(rs);
+               }
+
+               clear_bit(MD_RECOVERY_FROZEN, &rs->md.recovery);
        }
 
-       clear_bit(MD_RECOVERY_FROZEN, &rs->md.recovery);
        mddev_resume(&rs->md);
 }
 
+static int raid_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+                     struct bio_vec *biovec, int max_size)
+{
+       struct raid_set *rs = ti->private;
+       struct md_personality *pers = rs->md.pers;
+
+       if (pers && pers->mergeable_bvec)
+               return min(max_size, pers->mergeable_bvec(&rs->md, bvm, biovec));
+
+       /*
+        * In case we can't request the personality because
+        * the raid set is not running yet
+        *
+        * -> return safe minimum
+        */
+       return rs->md.chunk_sectors;
+}
+
 static struct target_type raid_target = {
        .name = "raid",
-       .version = {1, 6, 0},
+       .version = {1, 7, 0},
        .module = THIS_MODULE,
        .ctr = raid_ctr,
        .dtr = raid_dtr,
        .presuspend = raid_presuspend,
        .postsuspend = raid_postsuspend,
        .resume = raid_resume,
+       .merge = raid_merge,
 };
 
 static int __init dm_raid_init(void)