Commit c98a0eb0 authored by Martin K. Petersen's avatar Martin K. Petersen Committed by James Bottomley

[SCSI] sd: Logical Block Provisioning update

SBC3r26 contains many changes to the Logical Block Provisioning
interfaces (formerly known as Thin Provisioning ditto). This patch
implements support for both the old and new schemes using the same
heuristic as before (whether the LBP VPD page is present).

The new code also allows the provisioning mode (i.e. choice of command)
to be overridden on a per-device basis via sysfs. Two additional modes
are supported in this version:

 - WRITE SAME(10) with the UNMAP bit set

 - WRITE SAME(10) without the UNMAP bit set. This allows us to support
   devices that predate the TP/LBP enhancements in SBC3 and which work
   by way zero-detection

Switching between modes has been consolidated in a helper function that
also updates the block layer topology according to the limitations of
the chosen command.

I experimented with trying WRITE SAME(16) if UNMAP fails, WRITE SAME(10)
if WRITE SAME(16) fails, etc. but found several devices that got
cranky. So for now we'll disable discard if one of the commands
fail. The user still has the option of selecting a different mode in
sysfs.
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 72f7d322
...@@ -867,6 +867,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) ...@@ -867,6 +867,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
description = "Host Data Integrity Failure"; description = "Host Data Integrity Failure";
action = ACTION_FAIL; action = ACTION_FAIL;
error = -EILSEQ; error = -EILSEQ;
/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
} else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
(cmd->cmnd[0] == UNMAP ||
cmd->cmnd[0] == WRITE_SAME_16 ||
cmd->cmnd[0] == WRITE_SAME)) {
description = "Discard failure";
action = ACTION_FAIL;
} else } else
action = ACTION_FAIL; action = ACTION_FAIL;
break; break;
......
This diff is collapsed.
...@@ -43,6 +43,15 @@ enum { ...@@ -43,6 +43,15 @@ enum {
SD_MEMPOOL_SIZE = 2, /* CDB pool size */ SD_MEMPOOL_SIZE = 2, /* CDB pool size */
}; };
enum {
SD_LBP_FULL = 0, /* Full logical block provisioning */
SD_LBP_UNMAP, /* Use UNMAP command */
SD_LBP_WS16, /* Use WRITE SAME(16) with UNMAP bit */
SD_LBP_WS10, /* Use WRITE SAME(10) with UNMAP bit */
SD_LBP_ZERO, /* Use WRITE SAME(10) with zero payload */
SD_LBP_DISABLE, /* Discard disabled due to failed cmd */
};
struct scsi_disk { struct scsi_disk {
struct scsi_driver *driver; /* always &sd_template */ struct scsi_driver *driver; /* always &sd_template */
struct scsi_device *device; struct scsi_device *device;
...@@ -50,21 +59,27 @@ struct scsi_disk { ...@@ -50,21 +59,27 @@ struct scsi_disk {
struct gendisk *disk; struct gendisk *disk;
atomic_t openers; atomic_t openers;
sector_t capacity; /* size in 512-byte sectors */ sector_t capacity; /* size in 512-byte sectors */
u32 max_ws_blocks;
u32 max_unmap_blocks;
u32 unmap_granularity;
u32 unmap_alignment;
u32 index; u32 index;
unsigned int physical_block_size; unsigned int physical_block_size;
u8 media_present; u8 media_present;
u8 write_prot; u8 write_prot;
u8 protection_type;/* Data Integrity Field */ u8 protection_type;/* Data Integrity Field */
u8 provisioning_mode;
unsigned ATO : 1; /* state of disk ATO bit */ unsigned ATO : 1; /* state of disk ATO bit */
unsigned WCE : 1; /* state of disk WCE bit */ unsigned WCE : 1; /* state of disk WCE bit */
unsigned RCD : 1; /* state of disk RCD bit, unused */ unsigned RCD : 1; /* state of disk RCD bit, unused */
unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ unsigned DPOFUA : 1; /* state of disk DPOFUA bit */
unsigned first_scan : 1; unsigned first_scan : 1;
unsigned thin_provisioning : 1; unsigned lbpme : 1;
unsigned unmap : 1; unsigned lbprz : 1;
unsigned tpws : 1; unsigned lbpu : 1;
unsigned tpu : 1; unsigned lbpws : 1;
unsigned tpvpd : 1; unsigned lbpws10 : 1;
unsigned lbpvpd : 1;
}; };
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment