scsi: target: add emulate_pr backstore attr to toggle PR support
The new emulate_pr backstore attribute allows for Persistent Reservation and SCSI2 RESERVE/RELEASE support to be completely disabled. This can be useful for scenarios such as: - Ensuring ATS (Compare & Write) usage on recent VMware ESXi initiators. - Allowing clustered (e.g. tcm-user) backends to block such requests, avoiding the multi-node reservation state propagation. When explicitly disabled, PR and RESERVE/RELEASE requests receive Invalid Command Operation Code response sense data. Signed-off-by: David Disseldorp <ddiss@suse.de> Reviewed-by: Mike Christie <mchristi@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
8d0bb86e2c
commit
b49d6f7885
5 changed files with 44 additions and 6 deletions
|
@ -532,6 +532,7 @@ DEF_CONFIGFS_ATTRIB_SHOW(emulate_tpu);
|
||||||
DEF_CONFIGFS_ATTRIB_SHOW(emulate_tpws);
|
DEF_CONFIGFS_ATTRIB_SHOW(emulate_tpws);
|
||||||
DEF_CONFIGFS_ATTRIB_SHOW(emulate_caw);
|
DEF_CONFIGFS_ATTRIB_SHOW(emulate_caw);
|
||||||
DEF_CONFIGFS_ATTRIB_SHOW(emulate_3pc);
|
DEF_CONFIGFS_ATTRIB_SHOW(emulate_3pc);
|
||||||
|
DEF_CONFIGFS_ATTRIB_SHOW(emulate_pr);
|
||||||
DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_type);
|
DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_type);
|
||||||
DEF_CONFIGFS_ATTRIB_SHOW(hw_pi_prot_type);
|
DEF_CONFIGFS_ATTRIB_SHOW(hw_pi_prot_type);
|
||||||
DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_format);
|
DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_format);
|
||||||
|
@ -592,6 +593,7 @@ static ssize_t _name##_store(struct config_item *item, const char *page, \
|
||||||
DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_fua_write);
|
DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_fua_write);
|
||||||
DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_caw);
|
DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_caw);
|
||||||
DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_3pc);
|
DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_3pc);
|
||||||
|
DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_pr);
|
||||||
DEF_CONFIGFS_ATTRIB_STORE_BOOL(enforce_pr_isids);
|
DEF_CONFIGFS_ATTRIB_STORE_BOOL(enforce_pr_isids);
|
||||||
DEF_CONFIGFS_ATTRIB_STORE_BOOL(is_nonrot);
|
DEF_CONFIGFS_ATTRIB_STORE_BOOL(is_nonrot);
|
||||||
|
|
||||||
|
@ -1116,6 +1118,7 @@ CONFIGFS_ATTR(, emulate_tpu);
|
||||||
CONFIGFS_ATTR(, emulate_tpws);
|
CONFIGFS_ATTR(, emulate_tpws);
|
||||||
CONFIGFS_ATTR(, emulate_caw);
|
CONFIGFS_ATTR(, emulate_caw);
|
||||||
CONFIGFS_ATTR(, emulate_3pc);
|
CONFIGFS_ATTR(, emulate_3pc);
|
||||||
|
CONFIGFS_ATTR(, emulate_pr);
|
||||||
CONFIGFS_ATTR(, pi_prot_type);
|
CONFIGFS_ATTR(, pi_prot_type);
|
||||||
CONFIGFS_ATTR_RO(, hw_pi_prot_type);
|
CONFIGFS_ATTR_RO(, hw_pi_prot_type);
|
||||||
CONFIGFS_ATTR(, pi_prot_format);
|
CONFIGFS_ATTR(, pi_prot_format);
|
||||||
|
@ -1156,6 +1159,7 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
|
||||||
&attr_emulate_tpws,
|
&attr_emulate_tpws,
|
||||||
&attr_emulate_caw,
|
&attr_emulate_caw,
|
||||||
&attr_emulate_3pc,
|
&attr_emulate_3pc,
|
||||||
|
&attr_emulate_pr,
|
||||||
&attr_pi_prot_type,
|
&attr_pi_prot_type,
|
||||||
&attr_hw_pi_prot_type,
|
&attr_hw_pi_prot_type,
|
||||||
&attr_pi_prot_format,
|
&attr_pi_prot_format,
|
||||||
|
@ -1427,6 +1431,9 @@ static ssize_t target_pr_res_holder_show(struct config_item *item, char *page)
|
||||||
struct se_device *dev = pr_to_dev(item);
|
struct se_device *dev = pr_to_dev(item);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!dev->dev_attrib.emulate_pr)
|
||||||
|
return sprintf(page, "SPC_RESERVATIONS_DISABLED\n");
|
||||||
|
|
||||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||||
return sprintf(page, "Passthrough\n");
|
return sprintf(page, "Passthrough\n");
|
||||||
|
|
||||||
|
@ -1567,12 +1574,14 @@ static ssize_t target_pr_res_type_show(struct config_item *item, char *page)
|
||||||
{
|
{
|
||||||
struct se_device *dev = pr_to_dev(item);
|
struct se_device *dev = pr_to_dev(item);
|
||||||
|
|
||||||
|
if (!dev->dev_attrib.emulate_pr)
|
||||||
|
return sprintf(page, "SPC_RESERVATIONS_DISABLED\n");
|
||||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||||
return sprintf(page, "SPC_PASSTHROUGH\n");
|
return sprintf(page, "SPC_PASSTHROUGH\n");
|
||||||
else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||||
return sprintf(page, "SPC2_RESERVATIONS\n");
|
return sprintf(page, "SPC2_RESERVATIONS\n");
|
||||||
else
|
|
||||||
return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
|
return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t target_pr_res_aptpl_active_show(struct config_item *item,
|
static ssize_t target_pr_res_aptpl_active_show(struct config_item *item,
|
||||||
|
@ -1580,7 +1589,8 @@ static ssize_t target_pr_res_aptpl_active_show(struct config_item *item,
|
||||||
{
|
{
|
||||||
struct se_device *dev = pr_to_dev(item);
|
struct se_device *dev = pr_to_dev(item);
|
||||||
|
|
||||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
if (!dev->dev_attrib.emulate_pr ||
|
||||||
|
(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return sprintf(page, "APTPL Bit Status: %s\n",
|
return sprintf(page, "APTPL Bit Status: %s\n",
|
||||||
|
@ -1592,7 +1602,8 @@ static ssize_t target_pr_res_aptpl_metadata_show(struct config_item *item,
|
||||||
{
|
{
|
||||||
struct se_device *dev = pr_to_dev(item);
|
struct se_device *dev = pr_to_dev(item);
|
||||||
|
|
||||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
if (!dev->dev_attrib.emulate_pr ||
|
||||||
|
(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return sprintf(page, "Ready to process PR APTPL metadata..\n");
|
return sprintf(page, "Ready to process PR APTPL metadata..\n");
|
||||||
|
@ -1638,7 +1649,8 @@ static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item,
|
||||||
u16 tpgt = 0;
|
u16 tpgt = 0;
|
||||||
u8 type = 0;
|
u8 type = 0;
|
||||||
|
|
||||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
if (!dev->dev_attrib.emulate_pr ||
|
||||||
|
(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||||
return count;
|
return count;
|
||||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||||
return count;
|
return count;
|
||||||
|
|
|
@ -805,6 +805,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
||||||
dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS;
|
dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS;
|
||||||
dev->dev_attrib.emulate_caw = DA_EMULATE_CAW;
|
dev->dev_attrib.emulate_caw = DA_EMULATE_CAW;
|
||||||
dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC;
|
dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC;
|
||||||
|
dev->dev_attrib.emulate_pr = DA_EMULATE_PR;
|
||||||
dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE0_PROT;
|
dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE0_PROT;
|
||||||
dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
|
dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
|
||||||
dev->dev_attrib.force_pr_aptpl = DA_FORCE_PR_APTPL;
|
dev->dev_attrib.force_pr_aptpl = DA_FORCE_PR_APTPL;
|
||||||
|
@ -1158,6 +1159,18 @@ passthrough_parse_cdb(struct se_cmd *cmd,
|
||||||
return TCM_NO_SENSE;
|
return TCM_NO_SENSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With emulate_pr disabled, all reservation requests should fail,
|
||||||
|
* regardless of whether or not TRANSPORT_FLAG_PASSTHROUGH_PGR is set.
|
||||||
|
*/
|
||||||
|
if (!dev->dev_attrib.emulate_pr &&
|
||||||
|
((cdb[0] == PERSISTENT_RESERVE_IN) ||
|
||||||
|
(cdb[0] == PERSISTENT_RESERVE_OUT) ||
|
||||||
|
(cdb[0] == RELEASE || cdb[0] == RELEASE_10) ||
|
||||||
|
(cdb[0] == RESERVE || cdb[0] == RESERVE_10))) {
|
||||||
|
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For PERSISTENT RESERVE IN/OUT, RELEASE, and RESERVE we need to
|
* For PERSISTENT RESERVE IN/OUT, RELEASE, and RESERVE we need to
|
||||||
* emulate the response, since tcmu does not have the information
|
* emulate the response, since tcmu does not have the information
|
||||||
|
|
|
@ -4095,6 +4095,8 @@ target_check_reservation(struct se_cmd *cmd)
|
||||||
return 0;
|
return 0;
|
||||||
if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
|
if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (!dev->dev_attrib.emulate_pr)
|
||||||
|
return 0;
|
||||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -1281,6 +1281,14 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct se_device *dev = cmd->se_dev;
|
||||||
unsigned char *cdb = cmd->t_task_cdb;
|
unsigned char *cdb = cmd->t_task_cdb;
|
||||||
|
|
||||||
|
if (!dev->dev_attrib.emulate_pr &&
|
||||||
|
((cdb[0] == PERSISTENT_RESERVE_IN) ||
|
||||||
|
(cdb[0] == PERSISTENT_RESERVE_OUT) ||
|
||||||
|
(cdb[0] == RELEASE || cdb[0] == RELEASE_10) ||
|
||||||
|
(cdb[0] == RESERVE || cdb[0] == RESERVE_10))) {
|
||||||
|
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (cdb[0]) {
|
switch (cdb[0]) {
|
||||||
case MODE_SELECT:
|
case MODE_SELECT:
|
||||||
*size = cdb[4];
|
*size = cdb[4];
|
||||||
|
|
|
@ -87,6 +87,8 @@
|
||||||
#define DA_EMULATE_3PC 1
|
#define DA_EMULATE_3PC 1
|
||||||
/* No Emulation for PSCSI by default */
|
/* No Emulation for PSCSI by default */
|
||||||
#define DA_EMULATE_ALUA 0
|
#define DA_EMULATE_ALUA 0
|
||||||
|
/* Emulate SCSI2 RESERVE/RELEASE and Persistent Reservations by default */
|
||||||
|
#define DA_EMULATE_PR 1
|
||||||
/* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
|
/* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
|
||||||
#define DA_ENFORCE_PR_ISIDS 1
|
#define DA_ENFORCE_PR_ISIDS 1
|
||||||
/* Force SPC-3 PR Activate Persistence across Target Power Loss */
|
/* Force SPC-3 PR Activate Persistence across Target Power Loss */
|
||||||
|
@ -664,6 +666,7 @@ struct se_dev_attrib {
|
||||||
int emulate_tpws;
|
int emulate_tpws;
|
||||||
int emulate_caw;
|
int emulate_caw;
|
||||||
int emulate_3pc;
|
int emulate_3pc;
|
||||||
|
int emulate_pr;
|
||||||
int pi_prot_format;
|
int pi_prot_format;
|
||||||
enum target_prot_type pi_prot_type;
|
enum target_prot_type pi_prot_type;
|
||||||
enum target_prot_type hw_pi_prot_type;
|
enum target_prot_type hw_pi_prot_type;
|
||||||
|
|
Loading…
Add table
Reference in a new issue