]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
md: raid 0 supports TRIM
authorShaohua Li <shli@fusionio.com>
Mon, 24 Sep 2012 06:41:25 +0000 (16:41 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 24 Sep 2012 06:41:25 +0000 (16:41 +1000)
This makes md raid 0 support TRIM.

Signed-off-by: Shaohua Li <shli@fusionio.com>
Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/raid0.c

index de63a1fc3737b7ac2af3c0f7cbf60cd99b495a31..1a8e5e3692b90c43d587a0fa4080680c5c258633 100644 (file)
@@ -88,6 +88,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
        char b[BDEVNAME_SIZE];
        char b2[BDEVNAME_SIZE];
        struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+       bool discard_supported = false;
 
        if (!conf)
                return -ENOMEM;
@@ -195,6 +196,9 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
                if (!smallest || (rdev1->sectors < smallest->sectors))
                        smallest = rdev1;
                cnt++;
+
+               if (blk_queue_discard(bdev_get_queue(rdev1->bdev)))
+                       discard_supported = true;
        }
        if (cnt != mddev->raid_disks) {
                printk(KERN_ERR "md/raid0:%s: too few disks (%d of %d) - "
@@ -272,6 +276,11 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
        blk_queue_io_opt(mddev->queue,
                         (mddev->chunk_sectors << 9) * mddev->raid_disks);
 
+       if (!discard_supported)
+               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+       else
+               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+
        pr_debug("md/raid0:%s: done.\n", mdname(mddev));
        *private_conf = conf;
 
@@ -422,6 +431,7 @@ static int raid0_run(struct mddev *mddev)
        if (md_check_no_bitmap(mddev))
                return -EINVAL;
        blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
+       blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
 
        /* if private is not null, we are here after takeover */
        if (mddev->private == NULL) {
@@ -509,7 +519,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
                sector_t sector = bio->bi_sector;
                struct bio_pair *bp;
                /* Sanity check -- queue functions should prevent this happening */
-               if (bio->bi_vcnt != 1 ||
+               if ((bio->bi_vcnt != 1 && bio->bi_vcnt != 0) ||
                    bio->bi_idx != 0)
                        goto bad_map;
                /* This is a one page bio that upper layers
@@ -535,6 +545,13 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
        bio->bi_sector = sector_offset + zone->dev_start +
                tmp_dev->data_offset;
 
+       if (unlikely((bio->bi_rw & REQ_DISCARD) &&
+                    !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
+               /* Just ignore it */
+               bio_endio(bio, 0);
+               return;
+       }
+
        generic_make_request(bio);
        return;