diff options
author | Heinz Mauelshagen <heinzm@redhat.com> | 2014-09-24 19:47:19 +0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2014-10-06 04:03:36 +0400 |
commit | 48cf06bc5f508d5f71bc0fd7530daebb12a48428 (patch) | |
tree | 17a0a3c51bde7dcee9ce0e45a4799d83b254dbbd /drivers | |
parent | 75b8e04bbf01bdd5c42a1d8ac54abf757196ce49 (diff) | |
download | linux-48cf06bc5f508d5f71bc0fd7530daebb12a48428.tar.xz |
dm raid: add discard support for RAID levels 4, 5 and 6
In case of RAID levels 4, 5 and 6 we have to verify each RAID members'
ability to zero data on discards to avoid stripe data corruption -- if
discard_zeroes_data is not set for each RAID member discard support must
be disabled. But given the uncertainty of whether or not a RAID member
properly supports zeroing data on discard we require the user to
explicitly allow discard support on RAID levels 4, 5, and 6 by setting
a dm-raid module paramter, e.g.: dm-raid.devices_handle_discard_safely=Y
Otherwise, discards could cause data corruption on RAID4/5/6.
Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/dm-raid.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 030e2d6bc261..4857fa4a5484 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -18,6 +18,8 @@ #define DM_MSG_PREFIX "raid" +static bool devices_handle_discard_safely = false; + /* * The following flags are used by dm-raid.c to set up the array state. * They must be cleared before md_run is called. @@ -475,6 +477,8 @@ too_many: * will form the "stripe" * [[no]sync] Force or prevent recovery of the * entire array + * [devices_handle_discard_safely] Allow discards on RAID4/5/6; useful if RAID + * member device(s) properly support TRIM/UNMAP * [rebuild <idx>] Rebuild the drive indicated by the index * [daemon_sleep <ms>] Time between bitmap daemon work to * clear bits @@ -1150,23 +1154,45 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) } /* - * Enable/disable discard support on RAID set depending on RAID level. + * Enable/disable discard support on RAID set depending on + * RAID level and discard properties of underlying RAID members. */ static void configure_discard_support(struct dm_target *ti, struct raid_set *rs) { + int i; + bool raid456; + /* Assume discards not supported until after checks below. */ ti->discards_supported = false; /* RAID level 4,5,6 require discard_zeroes_data for data integrity! */ - if (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6) - return; /* discard_zeroes_data cannot be trusted as reliable */ + raid456 = (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6); + for (i = 0; i < rs->md.raid_disks; i++) { + struct request_queue *q = bdev_get_queue(rs->dev[i].rdev.bdev); + + if (!q || !blk_queue_discard(q)) + return; + + if (raid456) { + if (!q->limits.discard_zeroes_data) + return; + if (!devices_handle_discard_safely) { + DMERR("raid456 discard support disabled due to discard_zeroes_data uncertainty."); + DMERR("Set dm-raid.devices_handle_discard_safely=Y to override."); + return; + } + } + } + + /* All RAID members properly support discards */ ti->discards_supported = true; /* * RAID1 and RAID10 personalities require bio splitting, + * RAID0/4/5/6 don't and process large discard bios properly. */ - ti->split_discard_bios = true; + ti->split_discard_bios = !!(rs->md.level == 1 || rs->md.level == 10); ti->num_discard_bios = 1; } @@ -1709,6 +1735,10 @@ static void __exit dm_raid_exit(void) module_init(dm_raid_init); module_exit(dm_raid_exit); +module_param(devices_handle_discard_safely, bool, 0644); +MODULE_PARM_DESC(devices_handle_discard_safely, + "Set to Y if all devices in each array reliably return zeroes on reads from discarded regions"); + MODULE_DESCRIPTION(DM_NAME " raid4/5/6 target"); MODULE_ALIAS("dm-raid1"); MODULE_ALIAS("dm-raid10"); |