diff options
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r-- | drivers/md/dm-raid.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 4880b69e2e9e..4857fa4a5484 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2010-2011 Neil Brown | 2 | * Copyright (C) 2010-2011 Neil Brown |
3 | * Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2010-2014 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This file is released under the GPL. | 5 | * This file is released under the GPL. |
6 | */ | 6 | */ |
@@ -18,6 +18,8 @@ | |||
18 | 18 | ||
19 | #define DM_MSG_PREFIX "raid" | 19 | #define DM_MSG_PREFIX "raid" |
20 | 20 | ||
21 | static bool devices_handle_discard_safely = false; | ||
22 | |||
21 | /* | 23 | /* |
22 | * The following flags are used by dm-raid.c to set up the array state. | 24 | * The following flags are used by dm-raid.c to set up the array state. |
23 | * They must be cleared before md_run is called. | 25 | * They must be cleared before md_run is called. |
@@ -475,6 +477,8 @@ too_many: | |||
475 | * will form the "stripe" | 477 | * will form the "stripe" |
476 | * [[no]sync] Force or prevent recovery of the | 478 | * [[no]sync] Force or prevent recovery of the |
477 | * entire array | 479 | * entire array |
480 | * [devices_handle_discard_safely] Allow discards on RAID4/5/6; useful if RAID | ||
481 | * member device(s) properly support TRIM/UNMAP | ||
478 | * [rebuild <idx>] Rebuild the drive indicated by the index | 482 | * [rebuild <idx>] Rebuild the drive indicated by the index |
479 | * [daemon_sleep <ms>] Time between bitmap daemon work to | 483 | * [daemon_sleep <ms>] Time between bitmap daemon work to |
480 | * clear bits | 484 | * clear bits |
@@ -1150,6 +1154,49 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) | |||
1150 | } | 1154 | } |
1151 | 1155 | ||
1152 | /* | 1156 | /* |
1157 | * Enable/disable discard support on RAID set depending on | ||
1158 | * RAID level and discard properties of underlying RAID members. | ||
1159 | */ | ||
1160 | static void configure_discard_support(struct dm_target *ti, struct raid_set *rs) | ||
1161 | { | ||
1162 | int i; | ||
1163 | bool raid456; | ||
1164 | |||
1165 | /* Assume discards not supported until after checks below. */ | ||
1166 | ti->discards_supported = false; | ||
1167 | |||
1168 | /* RAID level 4,5,6 require discard_zeroes_data for data integrity! */ | ||
1169 | raid456 = (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6); | ||
1170 | |||
1171 | for (i = 0; i < rs->md.raid_disks; i++) { | ||
1172 | struct request_queue *q = bdev_get_queue(rs->dev[i].rdev.bdev); | ||
1173 | |||
1174 | if (!q || !blk_queue_discard(q)) | ||
1175 | return; | ||
1176 | |||
1177 | if (raid456) { | ||
1178 | if (!q->limits.discard_zeroes_data) | ||
1179 | return; | ||
1180 | if (!devices_handle_discard_safely) { | ||
1181 | DMERR("raid456 discard support disabled due to discard_zeroes_data uncertainty."); | ||
1182 | DMERR("Set dm-raid.devices_handle_discard_safely=Y to override."); | ||
1183 | return; | ||
1184 | } | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | /* All RAID members properly support discards */ | ||
1189 | ti->discards_supported = true; | ||
1190 | |||
1191 | /* | ||
1192 | * RAID1 and RAID10 personalities require bio splitting, | ||
1193 | * RAID0/4/5/6 don't and process large discard bios properly. | ||
1194 | */ | ||
1195 | ti->split_discard_bios = !!(rs->md.level == 1 || rs->md.level == 10); | ||
1196 | ti->num_discard_bios = 1; | ||
1197 | } | ||
1198 | |||
1199 | /* | ||
1153 | * Construct a RAID4/5/6 mapping: | 1200 | * Construct a RAID4/5/6 mapping: |
1154 | * Args: | 1201 | * Args: |
1155 | * <raid_type> <#raid_params> <raid_params> \ | 1202 | * <raid_type> <#raid_params> <raid_params> \ |
@@ -1231,6 +1278,11 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
1231 | ti->private = rs; | 1278 | ti->private = rs; |
1232 | ti->num_flush_bios = 1; | 1279 | ti->num_flush_bios = 1; |
1233 | 1280 | ||
1281 | /* | ||
1282 | * Disable/enable discard support on RAID set. | ||
1283 | */ | ||
1284 | configure_discard_support(ti, rs); | ||
1285 | |||
1234 | mutex_lock(&rs->md.reconfig_mutex); | 1286 | mutex_lock(&rs->md.reconfig_mutex); |
1235 | ret = md_run(&rs->md); | 1287 | ret = md_run(&rs->md); |
1236 | rs->md.in_sync = 0; /* Assume already marked dirty */ | 1288 | rs->md.in_sync = 0; /* Assume already marked dirty */ |
@@ -1652,7 +1704,7 @@ static void raid_resume(struct dm_target *ti) | |||
1652 | 1704 | ||
1653 | static struct target_type raid_target = { | 1705 | static struct target_type raid_target = { |
1654 | .name = "raid", | 1706 | .name = "raid", |
1655 | .version = {1, 5, 2}, | 1707 | .version = {1, 6, 0}, |
1656 | .module = THIS_MODULE, | 1708 | .module = THIS_MODULE, |
1657 | .ctr = raid_ctr, | 1709 | .ctr = raid_ctr, |
1658 | .dtr = raid_dtr, | 1710 | .dtr = raid_dtr, |
@@ -1683,6 +1735,10 @@ static void __exit dm_raid_exit(void) | |||
1683 | module_init(dm_raid_init); | 1735 | module_init(dm_raid_init); |
1684 | module_exit(dm_raid_exit); | 1736 | module_exit(dm_raid_exit); |
1685 | 1737 | ||
1738 | module_param(devices_handle_discard_safely, bool, 0644); | ||
1739 | MODULE_PARM_DESC(devices_handle_discard_safely, | ||
1740 | "Set to Y if all devices in each array reliably return zeroes on reads from discarded regions"); | ||
1741 | |||
1686 | MODULE_DESCRIPTION(DM_NAME " raid4/5/6 target"); | 1742 | MODULE_DESCRIPTION(DM_NAME " raid4/5/6 target"); |
1687 | MODULE_ALIAS("dm-raid1"); | 1743 | MODULE_ALIAS("dm-raid1"); |
1688 | MODULE_ALIAS("dm-raid10"); | 1744 | MODULE_ALIAS("dm-raid10"); |