Skip to content

Commit

Permalink
[SCSI] sd: Update thin provisioning support
Browse files Browse the repository at this point in the history
Add support for the Thin Provisioning VPD page and use the TPU and TPWS
bits to switch between UNMAP and WRITE SAME(16) for discards.  If no TP
VPD page is present we fall back to old scheme where the max descriptor
count combined with the max lba count are used trigger UNMAP.

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Martin K. Petersen authored and James Bottomley committed Sep 17, 2010
1 parent a36c61f commit 045d3fe
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
46 changes: 41 additions & 5 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2039,14 +2039,24 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
lba_count = get_unaligned_be32(&buffer[20]);
desc_count = get_unaligned_be32(&buffer[24]);

if (lba_count) {
q->limits.max_discard_sectors =
lba_count * sector_sz >> 9;

if (desc_count)
if (lba_count && desc_count) {
if (sdkp->tpvpd && !sdkp->tpu)
sdkp->unmap = 0;
else
sdkp->unmap = 1;
}

if (sdkp->tpvpd && !sdkp->tpu && !sdkp->tpws) {
sd_printk(KERN_ERR, sdkp, "Thin provisioning is " \
"enabled but neither TPU, nor TPWS are " \
"set. Disabling discard!\n");
goto out;
}

if (lba_count)
q->limits.max_discard_sectors =
lba_count * sector_sz >> 9;

granularity = get_unaligned_be32(&buffer[28]);

if (granularity)
Expand Down Expand Up @@ -2087,6 +2097,31 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
kfree(buffer);
}

/**
* sd_read_thin_provisioning - Query thin provisioning VPD page
* @disk: disk to query
*/
static void sd_read_thin_provisioning(struct scsi_disk *sdkp)
{
unsigned char *buffer;
const int vpd_len = 8;

if (sdkp->thin_provisioning == 0)
return;

buffer = kmalloc(vpd_len, GFP_KERNEL);

if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb2, buffer, vpd_len))
goto out;

sdkp->tpvpd = 1;
sdkp->tpu = (buffer[5] >> 7) & 1; /* UNMAP */
sdkp->tpws = (buffer[5] >> 6) & 1; /* WRITE SAME(16) with UNMAP */

out:
kfree(buffer);
}

static int sd_try_extended_inquiry(struct scsi_device *sdp)
{
/*
Expand Down Expand Up @@ -2138,6 +2173,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
sd_read_capacity(sdkp, buffer);

if (sd_try_extended_inquiry(sdp)) {
sd_read_thin_provisioning(sdkp);
sd_read_block_limits(sdkp);
sd_read_block_characteristics(sdkp);
}
Expand Down
3 changes: 3 additions & 0 deletions drivers/scsi/sd.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ struct scsi_disk {
unsigned first_scan : 1;
unsigned thin_provisioning : 1;
unsigned unmap : 1;
unsigned tpws : 1;
unsigned tpu : 1;
unsigned tpvpd : 1;
};
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)

Expand Down

0 comments on commit 045d3fe

Please sign in to comment.