aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2015-11-13 16:46:47 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2015-11-25 21:38:34 -0500
commit397737223c59e89dca7305feb6528caef8fbef84 (patch)
treecce407c1cc11362e59bc1389ad30fe4d1de2cbea
parent653cfb85fbe73be44fda14bb67f1b95818bfc37f (diff)
sd: Make discard granularity match logical block size when LBPRZ=1
A device may report an OPTIMAL UNMAP GRANULARITY and UNMAP GRANULARITY ALIGNMENT in the Block Limits VPD. These parameters describe the device's internal provisioning allocation units. By default the block layer will round and align any discard requests based on these limits. If a device reports LBPRZ=1 to guarantee zeroes after discard, however, it is imperative that the block layer does not leave out any parts of the requested block range. Otherwise the device can not do the required zeroing of any partial allocation units and this can lead to data corruption. Since the dm thinp personality relies on the block layer's current behavior and is unable to deal with partial discard blocks we work around the problem by setting the granularity to match the logical block size when LBPRZ is enabled. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/sd.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f7247778c225..e868d39c39bb 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -637,11 +637,24 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
637 unsigned int max_blocks = 0; 637 unsigned int max_blocks = 0;
638 638
639 q->limits.discard_zeroes_data = 0; 639 q->limits.discard_zeroes_data = 0;
640 q->limits.discard_alignment = sdkp->unmap_alignment * 640
641 logical_block_size; 641 /*
642 q->limits.discard_granularity = 642 * When LBPRZ is reported, discard alignment and granularity
643 max(sdkp->physical_block_size, 643 * must be fixed to the logical block size. Otherwise the block
644 sdkp->unmap_granularity * logical_block_size); 644 * layer will drop misaligned portions of the request which can
645 * lead to data corruption. If LBPRZ is not set, we honor the
646 * device preference.
647 */
648 if (sdkp->lbprz) {
649 q->limits.discard_alignment = 0;
650 q->limits.discard_granularity = 1;
651 } else {
652 q->limits.discard_alignment = sdkp->unmap_alignment *
653 logical_block_size;
654 q->limits.discard_granularity =
655 max(sdkp->physical_block_size,
656 sdkp->unmap_granularity * logical_block_size);
657 }
645 658
646 sdkp->provisioning_mode = mode; 659 sdkp->provisioning_mode = mode;
647 660