Currently RAID 4/5/6 requires an module parameter to enable discard bios. This was done due the to general inadequacies of relying on hardware to correctly self identify. Since ZDM does not rely on lower level device support to for TRIM handling it seems reasonable to allow another method to communicate to MD-RAID that enabling discard is safe. This method is also more targeted. Devices are not expected to set this parameter directly. And the kernel module parameter which assumes devices are unsafe remains intact. Signed-off-by: Shaun Tancheff <shaun.tancheff@xxxxxxxxxxx> --- block/blk-settings.c | 1 + block/blk-sysfs.c | 11 +++++++++++ drivers/md/dm-zoned.c | 4 ++++ drivers/md/dm-zoned.h | 1 + drivers/md/raid5.c | 4 +++- include/linux/blkdev.h | 22 ++++++++++++++++++---- 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/block/blk-settings.c b/block/blk-settings.c index c7bb666..04bd7a4 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -101,6 +101,7 @@ void blk_set_default_limits(struct queue_limits *lim) lim->discard_alignment = 0; lim->discard_misaligned = 0; lim->discard_zeroes_data = 0; + lim->raid_discard_safe = 0; lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); lim->alignment_offset = 0; diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index dd93763..c12618a 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -186,6 +186,11 @@ static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *pag return queue_var_show(queue_discard_zeroes_data(q), page); } +static ssize_t queue_raid_discard_safe_show(struct request_queue *q, char *page) +{ + return queue_var_show(queue_raid_discard_safe(q), page); +} + static ssize_t queue_write_same_max_show(struct request_queue *q, char *page) { return sprintf(page, "%llu\n", @@ -437,6 +442,11 @@ static struct queue_sysfs_entry queue_discard_zeroes_data_entry = { .show = queue_discard_zeroes_data_show, }; +static struct queue_sysfs_entry queue_raid_discard_safe_entry = { + .attr = {.name = "raid_discard_safe", .mode = S_IRUGO }, + .show = queue_raid_discard_safe_show, +}; + static struct queue_sysfs_entry queue_write_same_max_entry = { .attr = {.name = "write_same_max_bytes", .mode = S_IRUGO }, .show = queue_write_same_max_show, @@ -496,6 +506,7 @@ static struct attribute *default_attrs[] = { &queue_discard_max_entry.attr, &queue_discard_max_hw_entry.attr, &queue_discard_zeroes_data_entry.attr, + &queue_raid_discard_safe_entry.attr, &queue_write_same_max_entry.attr, &queue_nonrot_entry.attr, &queue_nomerges_entry.attr, diff --git a/drivers/md/dm-zoned.c b/drivers/md/dm-zoned.c index 4e04464..6cab33e 100644 --- a/drivers/md/dm-zoned.c +++ b/drivers/md/dm-zoned.c @@ -663,6 +663,7 @@ static int zoned_ctr(struct dm_target *ti, unsigned argc, char **argv) } znd->trim = 1; + znd->raid5_trim = 0; if (argc < 1) { ti->error = "Invalid argument count"; @@ -692,6 +693,8 @@ static int zoned_ctr(struct dm_target *ti, unsigned argc, char **argv) znd->trim = 1; if (!strcasecmp("nodiscard", argv[r])) znd->trim = 0; + if (!strcasecmp("raid5_trim", argv[r])) + znd->raid5_trim = 1; if (!strncasecmp("reserve=", argv[r], 8)) { long long mz_resv; @@ -2021,6 +2024,7 @@ static void zoned_io_hints(struct dm_target *ti, struct queue_limits *limits) limits->max_discard_sectors = 1 << 30; limits->max_hw_discard_sectors = 1 << 30; limits->discard_zeroes_data = 1; + limits->raid_discard_safe = znd->raid5_trim; } } diff --git a/drivers/md/dm-zoned.h b/drivers/md/dm-zoned.h index c73ddea..67f8190 100644 --- a/drivers/md/dm-zoned.h +++ b/drivers/md/dm-zoned.h @@ -663,6 +663,7 @@ struct zoned { unsigned issue_close_zone:1; unsigned is_empty:1; unsigned trim:1; + unsigned raid5_trim:1; }; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index c96655e..a101399 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -7001,12 +7001,14 @@ static int raid5_run(struct mddev *mddev) !bdev_get_queue(rdev->bdev)-> limits.discard_zeroes_data) discard_supported = false; + /* Unfortunately, discard_zeroes_data is not currently * a guarantee - just a hint. So we only allow DISCARD * if the sysadmin has confirmed that only safe devices * are in use by setting a module parameter. */ - if (!devices_handle_discard_safely) { + if (!devices_handle_discard_safely && + !bdev_discard_raid_safe(rdev->bdev)) { if (discard_supported) { pr_info("md/raid456: discard support disabled due to uncertainty.\n"); pr_info("Set raid456.devices_handle_discard_safely=Y to override.\n"); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 413c84f..ecd50f5 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -273,11 +273,12 @@ struct queue_limits { unsigned short max_segments; unsigned short max_integrity_segments; - unsigned char misaligned; - unsigned char discard_misaligned; - unsigned char cluster; - unsigned char discard_zeroes_data; unsigned char raid_partial_stripes_expensive; + unsigned misaligned:1; + unsigned discard_misaligned:1; + unsigned cluster:1; + unsigned discard_zeroes_data:1; + unsigned raid_discard_safe:1; }; struct request_queue { @@ -1320,6 +1321,19 @@ static inline unsigned int bdev_discard_zeroes_data(struct block_device *bdev) return queue_discard_zeroes_data(bdev_get_queue(bdev)); } +static inline unsigned int queue_raid_discard_safe(struct request_queue *q) +{ + if (queue_discard_zeroes_data(q) && q->limits.raid_discard_safe) + return 1; + + return 0; +} + +static inline unsigned int bdev_discard_raid_safe(struct block_device *bdev) +{ + return queue_raid_discard_safe(bdev_get_queue(bdev)); +} + static inline unsigned int bdev_write_same(struct block_device *bdev) { struct request_queue *q = bdev_get_queue(bdev); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html