diff options
Diffstat (limited to 'drivers/md/raid1.c')
| -rw-r--r-- | drivers/md/raid1.c | 23 | 
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 611b5f79761..05c557e8f86 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -781,7 +781,12 @@ static void flush_pending_writes(struct r1conf *conf)  		while (bio) { /* submit pending writes */  			struct bio *next = bio->bi_next;  			bio->bi_next = NULL; -			generic_make_request(bio); +			if (unlikely((bio->bi_rw & REQ_DISCARD) && +			    !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) +				/* Just ignore it */ +				bio_endio(bio, 0); +			else +				generic_make_request(bio);  			bio = next;  		}  	} else @@ -994,6 +999,8 @@ static void make_request(struct mddev *mddev, struct bio * bio)  	const int rw = bio_data_dir(bio);  	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);  	const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); +	const unsigned long do_discard = (bio->bi_rw +					  & (REQ_DISCARD | REQ_SECURE));  	struct md_rdev *blocked_rdev;  	struct blk_plug_cb *cb;  	struct raid1_plug_cb *plug = NULL; @@ -1295,7 +1302,7 @@ read_again:  				   conf->mirrors[i].rdev->data_offset);  		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;  		mbio->bi_end_io	= raid1_end_write_request; -		mbio->bi_rw = WRITE | do_flush_fua | do_sync; +		mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard;  		mbio->bi_private = r1_bio;  		atomic_inc(&r1_bio->remaining); @@ -1549,6 +1556,8 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)  		clear_bit(Unmerged, &rdev->flags);  	}  	md_integrity_add_rdev(rdev, mddev); +	if (blk_queue_discard(bdev_get_queue(rdev->bdev))) +		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);  	print_conf(conf);  	return err;  } @@ -2783,6 +2792,7 @@ static int run(struct mddev *mddev)  	int i;  	struct md_rdev *rdev;  	int ret; +	bool discard_supported = false;  	if (mddev->level != 1) {  		printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n", @@ -2812,6 +2822,8 @@ static int run(struct mddev *mddev)  			continue;  		disk_stack_limits(mddev->gendisk, rdev->bdev,  				  rdev->data_offset << 9); +		if (blk_queue_discard(bdev_get_queue(rdev->bdev))) +			discard_supported = true;  	}  	mddev->degraded = 0; @@ -2846,6 +2858,13 @@ static int run(struct mddev *mddev)  		mddev->queue->backing_dev_info.congested_fn = raid1_congested;  		mddev->queue->backing_dev_info.congested_data = mddev;  		blk_queue_merge_bvec(mddev->queue, raid1_mergeable_bvec); + +		if (discard_supported) +			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, +						mddev->queue); +		else +			queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, +						  mddev->queue);  	}  	ret =  md_integrity_register(mddev);  |