|
18 | 18 |
|
19 | 19 | #define DM_MSG_PREFIX "raid"
|
20 | 20 |
|
| 21 | +static bool devices_handle_discard_safely = false; |
| 22 | + |
21 | 23 | /*
|
22 | 24 | * The following flags are used by dm-raid.c to set up the array state.
|
23 | 25 | * They must be cleared before md_run is called.
|
@@ -475,6 +477,8 @@ static int validate_raid_redundancy(struct raid_set *rs)
|
475 | 477 | * will form the "stripe"
|
476 | 478 | * [[no]sync] Force or prevent recovery of the
|
477 | 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 | 482 | * [rebuild <idx>] Rebuild the drive indicated by the index
|
479 | 483 | * [daemon_sleep <ms>] Time between bitmap daemon work to
|
480 | 484 | * clear bits
|
@@ -1150,23 +1154,45 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
|
1150 | 1154 | }
|
1151 | 1155 |
|
1152 | 1156 | /*
|
1153 |
| - * Enable/disable discard support on RAID set depending on RAID level. |
| 1157 | + * Enable/disable discard support on RAID set depending on |
| 1158 | + * RAID level and discard properties of underlying RAID members. |
1154 | 1159 | */
|
1155 | 1160 | static void configure_discard_support(struct dm_target *ti, struct raid_set *rs)
|
1156 | 1161 | {
|
| 1162 | + int i; |
| 1163 | + bool raid456; |
| 1164 | + |
1157 | 1165 | /* Assume discards not supported until after checks below. */
|
1158 | 1166 | ti->discards_supported = false;
|
1159 | 1167 |
|
1160 | 1168 | /* RAID level 4,5,6 require discard_zeroes_data for data integrity! */
|
1161 |
| - if (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6) |
1162 |
| - return; /* discard_zeroes_data cannot be trusted as reliable */ |
| 1169 | + raid456 = (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6); |
1163 | 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 */ |
1164 | 1189 | ti->discards_supported = true;
|
1165 | 1190 |
|
1166 | 1191 | /*
|
1167 | 1192 | * RAID1 and RAID10 personalities require bio splitting,
|
| 1193 | + * RAID0/4/5/6 don't and process large discard bios properly. |
1168 | 1194 | */
|
1169 |
| - ti->split_discard_bios = true; |
| 1195 | + ti->split_discard_bios = !!(rs->md.level == 1 || rs->md.level == 10); |
1170 | 1196 | ti->num_discard_bios = 1;
|
1171 | 1197 | }
|
1172 | 1198 |
|
@@ -1709,6 +1735,10 @@ static void __exit dm_raid_exit(void)
|
1709 | 1735 | module_init(dm_raid_init);
|
1710 | 1736 | module_exit(dm_raid_exit);
|
1711 | 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 | + |
1712 | 1742 | MODULE_DESCRIPTION(DM_NAME " raid4/5/6 target");
|
1713 | 1743 | MODULE_ALIAS("dm-raid1");
|
1714 | 1744 | MODULE_ALIAS("dm-raid10");
|
|
0 commit comments