Commit cb38b453 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'scsi-target-for-v4.10' of...

Merge branch 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/bvanassche/linux

Pull scsi target fixes from Bart Van Assche:

 - a series of bug fixes for the XCOPY implementation from David
   Disseldorp

 - one bug fix for the ibmvscsis driver, a driver that is used for
   communication between partitions on IBM POWER systems.

* 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/bvanassche/linux:
  ibmvscsis: Fix srp_transfer_data fail return code
  target: support XCOPY requests without parameters
  target: check for XCOPY parameter truncation
  target: use XCOPY segment descriptor CSCD IDs
  target: check XCOPY segment descriptor CSCD IDs
  target: simplify XCOPY wwn->se_dev lookup helper
  target: return UNSUPPORTED TARGET/SEGMENT DESC TYPE CODE sense
  target: bounds check XCOPY total descriptor list length
  target: bounds check XCOPY segment descriptor list
  target: use XCOPY TOO MANY TARGET DESCRIPTORS sense
  target: add XCOPY target/segment desc sense codes
parents 607ae5f2 7c9d8d0c
...@@ -3585,7 +3585,7 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd) ...@@ -3585,7 +3585,7 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd)
1, 1); 1, 1);
if (rc) { if (rc) {
pr_err("srp_transfer_data() failed: %d\n", rc); pr_err("srp_transfer_data() failed: %d\n", rc);
return -EAGAIN; return -EIO;
} }
/* /*
* We now tell TCM to add this WRITE CDB directly into the TCM storage * We now tell TCM to add this WRITE CDB directly into the TCM storage
......
...@@ -1693,6 +1693,10 @@ void transport_generic_request_failure(struct se_cmd *cmd, ...@@ -1693,6 +1693,10 @@ void transport_generic_request_failure(struct se_cmd *cmd,
case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE: case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
case TCM_TOO_MANY_TARGET_DESCS:
case TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE:
case TCM_TOO_MANY_SEGMENT_DESCS:
case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE:
break; break;
case TCM_OUT_OF_RESOURCES: case TCM_OUT_OF_RESOURCES:
sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
...@@ -2808,6 +2812,26 @@ static const struct sense_info sense_info_table[] = { ...@@ -2808,6 +2812,26 @@ static const struct sense_info sense_info_table[] = {
.key = ILLEGAL_REQUEST, .key = ILLEGAL_REQUEST,
.asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */ .asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */
}, },
[TCM_TOO_MANY_TARGET_DESCS] = {
.key = ILLEGAL_REQUEST,
.asc = 0x26,
.ascq = 0x06, /* TOO MANY TARGET DESCRIPTORS */
},
[TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE] = {
.key = ILLEGAL_REQUEST,
.asc = 0x26,
.ascq = 0x07, /* UNSUPPORTED TARGET DESCRIPTOR TYPE CODE */
},
[TCM_TOO_MANY_SEGMENT_DESCS] = {
.key = ILLEGAL_REQUEST,
.asc = 0x26,
.ascq = 0x08, /* TOO MANY SEGMENT DESCRIPTORS */
},
[TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE] = {
.key = ILLEGAL_REQUEST,
.asc = 0x26,
.ascq = 0x09, /* UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE */
},
[TCM_PARAMETER_LIST_LENGTH_ERROR] = { [TCM_PARAMETER_LIST_LENGTH_ERROR] = {
.key = ILLEGAL_REQUEST, .key = ILLEGAL_REQUEST,
.asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */ .asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */
......
...@@ -53,18 +53,13 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf) ...@@ -53,18 +53,13 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
return 0; return 0;
} }
static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
bool src) struct se_device **found_dev)
{ {
struct se_device *se_dev; struct se_device *se_dev;
unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN], *dev_wwn; unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
int rc; int rc;
if (src)
dev_wwn = &xop->dst_tid_wwn[0];
else
dev_wwn = &xop->src_tid_wwn[0];
mutex_lock(&g_device_mutex); mutex_lock(&g_device_mutex);
list_for_each_entry(se_dev, &g_device_list, g_dev_node) { list_for_each_entry(se_dev, &g_device_list, g_dev_node) {
...@@ -78,15 +73,8 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op ...@@ -78,15 +73,8 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
if (rc != 0) if (rc != 0)
continue; continue;
if (src) { *found_dev = se_dev;
xop->dst_dev = se_dev; pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
pr_debug("XCOPY 0xe4: Setting xop->dst_dev: %p from located"
" se_dev\n", xop->dst_dev);
} else {
xop->src_dev = se_dev;
pr_debug("XCOPY 0xe4: Setting xop->src_dev: %p from located"
" se_dev\n", xop->src_dev);
}
rc = target_depend_item(&se_dev->dev_group.cg_item); rc = target_depend_item(&se_dev->dev_group.cg_item);
if (rc != 0) { if (rc != 0) {
...@@ -110,7 +98,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op ...@@ -110,7 +98,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
} }
static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
unsigned char *p, bool src) unsigned char *p, unsigned short cscd_index)
{ {
unsigned char *desc = p; unsigned char *desc = p;
unsigned short ript; unsigned short ript;
...@@ -155,7 +143,13 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op ...@@ -155,7 +143,13 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
return -EINVAL; return -EINVAL;
} }
if (src) { if (cscd_index != xop->stdi && cscd_index != xop->dtdi) {
pr_debug("XCOPY 0xe4: ignoring CSCD entry %d - neither src nor "
"dest\n", cscd_index);
return 0;
}
if (cscd_index == xop->stdi) {
memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
/* /*
* Determine if the source designator matches the local device * Determine if the source designator matches the local device
...@@ -167,10 +161,15 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op ...@@ -167,10 +161,15 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source" pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source"
" received xop\n", xop->src_dev); " received xop\n", xop->src_dev);
} }
} else { }
if (cscd_index == xop->dtdi) {
memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
/* /*
* Determine if the destination designator matches the local device * Determine if the destination designator matches the local
* device. If @cscd_index corresponds to both source (stdi) and
* destination (dtdi), or dtdi comes after stdi, then
* XCOL_DEST_RECV_OP wins.
*/ */
if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0], if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0],
XCOPY_NAA_IEEE_REGEX_LEN)) { XCOPY_NAA_IEEE_REGEX_LEN)) {
...@@ -190,20 +189,23 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, ...@@ -190,20 +189,23 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
{ {
struct se_device *local_dev = se_cmd->se_dev; struct se_device *local_dev = se_cmd->se_dev;
unsigned char *desc = p; unsigned char *desc = p;
int offset = tdll % XCOPY_TARGET_DESC_LEN, rc, ret = 0; int offset = tdll % XCOPY_TARGET_DESC_LEN, rc;
unsigned short cscd_index = 0;
unsigned short start = 0; unsigned short start = 0;
bool src = true;
*sense_ret = TCM_INVALID_PARAMETER_LIST; *sense_ret = TCM_INVALID_PARAMETER_LIST;
if (offset != 0) { if (offset != 0) {
pr_err("XCOPY target descriptor list length is not" pr_err("XCOPY target descriptor list length is not"
" multiple of %d\n", XCOPY_TARGET_DESC_LEN); " multiple of %d\n", XCOPY_TARGET_DESC_LEN);
*sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
return -EINVAL; return -EINVAL;
} }
if (tdll > 64) { if (tdll > RCR_OP_MAX_TARGET_DESC_COUNT * XCOPY_TARGET_DESC_LEN) {
pr_err("XCOPY target descriptor supports a maximum" pr_err("XCOPY target descriptor supports a maximum"
" two src/dest descriptors, tdll: %hu too large..\n", tdll); " two src/dest descriptors, tdll: %hu too large..\n", tdll);
/* spc4r37 6.4.3.4 CSCD DESCRIPTOR LIST LENGTH field */
*sense_ret = TCM_TOO_MANY_TARGET_DESCS;
return -EINVAL; return -EINVAL;
} }
/* /*
...@@ -215,37 +217,43 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, ...@@ -215,37 +217,43 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
while (start < tdll) { while (start < tdll) {
/* /*
* Check target descriptor identification with 0xE4 type with * Check target descriptor identification with 0xE4 type, and
* use VPD 0x83 WWPN matching .. * compare the current index with the CSCD descriptor IDs in
* the segment descriptor. Use VPD 0x83 WWPN matching ..
*/ */
switch (desc[0]) { switch (desc[0]) {
case 0xe4: case 0xe4:
rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop, rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop,
&desc[0], src); &desc[0], cscd_index);
if (rc != 0) if (rc != 0)
goto out; goto out;
/*
* Assume target descriptors are in source -> destination order..
*/
if (src)
src = false;
else
src = true;
start += XCOPY_TARGET_DESC_LEN; start += XCOPY_TARGET_DESC_LEN;
desc += XCOPY_TARGET_DESC_LEN; desc += XCOPY_TARGET_DESC_LEN;
ret++; cscd_index++;
break; break;
default: default:
pr_err("XCOPY unsupported descriptor type code:" pr_err("XCOPY unsupported descriptor type code:"
" 0x%02x\n", desc[0]); " 0x%02x\n", desc[0]);
*sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
goto out; goto out;
} }
} }
if (xop->op_origin == XCOL_SOURCE_RECV_OP) switch (xop->op_origin) {
rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); case XCOL_SOURCE_RECV_OP:
else rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); &xop->dst_dev);
break;
case XCOL_DEST_RECV_OP:
rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
&xop->src_dev);
break;
default:
pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
"stdi: %hu dtdi: %hu\n", xop->stdi, xop->dtdi);
rc = -EINVAL;
break;
}
/* /*
* If a matching IEEE NAA 0x83 descriptor for the requested device * If a matching IEEE NAA 0x83 descriptor for the requested device
* is not located on this node, return COPY_ABORTED with ASQ/ASQC * is not located on this node, return COPY_ABORTED with ASQ/ASQC
...@@ -262,7 +270,7 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, ...@@ -262,7 +270,7 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n", pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n",
xop->dst_dev, &xop->dst_tid_wwn[0]); xop->dst_dev, &xop->dst_tid_wwn[0]);
return ret; return cscd_index;
out: out:
return -EINVAL; return -EINVAL;
...@@ -284,6 +292,14 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op ...@@ -284,6 +292,14 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
xop->stdi = get_unaligned_be16(&desc[4]); xop->stdi = get_unaligned_be16(&desc[4]);
xop->dtdi = get_unaligned_be16(&desc[6]); xop->dtdi = get_unaligned_be16(&desc[6]);
if (xop->stdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX ||
xop->dtdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX) {
pr_err("XCOPY segment desc 0x02: unsupported CSCD ID > 0x%x; stdi: %hu dtdi: %hu\n",
XCOPY_CSCD_DESC_ID_LIST_OFF_MAX, xop->stdi, xop->dtdi);
return -EINVAL;
}
pr_debug("XCOPY seg desc 0x02: desc_len: %hu stdi: %hu dtdi: %hu, DC: %d\n", pr_debug("XCOPY seg desc 0x02: desc_len: %hu stdi: %hu dtdi: %hu, DC: %d\n",
desc_len, xop->stdi, xop->dtdi, dc); desc_len, xop->stdi, xop->dtdi, dc);
...@@ -306,15 +322,25 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op ...@@ -306,15 +322,25 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd, static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
struct xcopy_op *xop, unsigned char *p, struct xcopy_op *xop, unsigned char *p,
unsigned int sdll) unsigned int sdll, sense_reason_t *sense_ret)
{ {
unsigned char *desc = p; unsigned char *desc = p;
unsigned int start = 0; unsigned int start = 0;
int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0; int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0;
*sense_ret = TCM_INVALID_PARAMETER_LIST;
if (offset != 0) { if (offset != 0) {
pr_err("XCOPY segment descriptor list length is not" pr_err("XCOPY segment descriptor list length is not"
" multiple of %d\n", XCOPY_SEGMENT_DESC_LEN); " multiple of %d\n", XCOPY_SEGMENT_DESC_LEN);
*sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
return -EINVAL;
}
if (sdll > RCR_OP_MAX_SG_DESC_COUNT * XCOPY_SEGMENT_DESC_LEN) {
pr_err("XCOPY supports %u segment descriptor(s), sdll: %u too"
" large..\n", RCR_OP_MAX_SG_DESC_COUNT, sdll);
/* spc4r37 6.4.3.5 SEGMENT DESCRIPTOR LIST LENGTH field */
*sense_ret = TCM_TOO_MANY_SEGMENT_DESCS;
return -EINVAL; return -EINVAL;
} }
...@@ -335,6 +361,7 @@ static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd, ...@@ -335,6 +361,7 @@ static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
default: default:
pr_err("XCOPY unsupported segment descriptor" pr_err("XCOPY unsupported segment descriptor"
"type: 0x%02x\n", desc[0]); "type: 0x%02x\n", desc[0]);
*sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
goto out; goto out;
} }
} }
...@@ -861,6 +888,16 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) ...@@ -861,6 +888,16 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
return TCM_UNSUPPORTED_SCSI_OPCODE; return TCM_UNSUPPORTED_SCSI_OPCODE;
} }
if (se_cmd->data_length == 0) {
target_complete_cmd(se_cmd, SAM_STAT_GOOD);
return TCM_NO_SENSE;
}
if (se_cmd->data_length < XCOPY_HDR_LEN) {
pr_err("XCOPY parameter truncation: length %u < hdr_len %u\n",
se_cmd->data_length, XCOPY_HDR_LEN);
return TCM_PARAMETER_LIST_LENGTH_ERROR;
}
xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL); xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL);
if (!xop) { if (!xop) {
pr_err("Unable to allocate xcopy_op\n"); pr_err("Unable to allocate xcopy_op\n");
...@@ -883,6 +920,12 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) ...@@ -883,6 +920,12 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
*/ */
tdll = get_unaligned_be16(&p[2]); tdll = get_unaligned_be16(&p[2]);
sdll = get_unaligned_be32(&p[8]); sdll = get_unaligned_be32(&p[8]);
if (tdll + sdll > RCR_OP_MAX_DESC_LIST_LEN) {
pr_err("XCOPY descriptor list length %u exceeds maximum %u\n",
tdll + sdll, RCR_OP_MAX_DESC_LIST_LEN);
ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
goto out;
}
inline_dl = get_unaligned_be32(&p[12]); inline_dl = get_unaligned_be32(&p[12]);
if (inline_dl != 0) { if (inline_dl != 0) {
...@@ -890,10 +933,32 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) ...@@ -890,10 +933,32 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
goto out; goto out;
} }
if (se_cmd->data_length < (XCOPY_HDR_LEN + tdll + sdll + inline_dl)) {
pr_err("XCOPY parameter truncation: data length %u too small "
"for tdll: %hu sdll: %u inline_dl: %u\n",
se_cmd->data_length, tdll, sdll, inline_dl);
ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
goto out;
}
pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x" pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x"
" tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
tdll, sdll, inline_dl); tdll, sdll, inline_dl);
/*
* skip over the target descriptors until segment descriptors
* have been passed - CSCD ids are needed to determine src and dest.
*/
seg_desc = &p[16] + tdll;
rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc,
sdll, &ret);
if (rc <= 0)
goto out;
pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
rc * XCOPY_SEGMENT_DESC_LEN);
rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret); rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
if (rc <= 0) if (rc <= 0)
goto out; goto out;
...@@ -911,18 +976,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) ...@@ -911,18 +976,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc, pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
rc * XCOPY_TARGET_DESC_LEN); rc * XCOPY_TARGET_DESC_LEN);
seg_desc = &p[16];
seg_desc += (rc * XCOPY_TARGET_DESC_LEN);
rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, sdll);
if (rc <= 0) {
xcopy_pt_undepend_remotedev(xop);
goto out;
}
transport_kunmap_data_sg(se_cmd); transport_kunmap_data_sg(se_cmd);
pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
rc * XCOPY_SEGMENT_DESC_LEN);
INIT_WORK(&xop->xop_work, target_xcopy_do_work); INIT_WORK(&xop->xop_work, target_xcopy_do_work);
queue_work(xcopy_wq, &xop->xop_work); queue_work(xcopy_wq, &xop->xop_work);
return TCM_NO_SENSE; return TCM_NO_SENSE;
......
#include <target/target_core_base.h> #include <target/target_core_base.h>
#define XCOPY_HDR_LEN 16
#define XCOPY_TARGET_DESC_LEN 32 #define XCOPY_TARGET_DESC_LEN 32
#define XCOPY_SEGMENT_DESC_LEN 28 #define XCOPY_SEGMENT_DESC_LEN 28
#define XCOPY_NAA_IEEE_REGEX_LEN 16 #define XCOPY_NAA_IEEE_REGEX_LEN 16
#define XCOPY_MAX_SECTORS 1024 #define XCOPY_MAX_SECTORS 1024
/*
* SPC4r37 6.4.6.1
* Table 150 — CSCD descriptor ID values
*/
#define XCOPY_CSCD_DESC_ID_LIST_OFF_MAX 0x07FF
enum xcopy_origin_list { enum xcopy_origin_list {
XCOL_SOURCE_RECV_OP = 0x01, XCOL_SOURCE_RECV_OP = 0x01,
XCOL_DEST_RECV_OP = 0x02, XCOL_DEST_RECV_OP = 0x02,
......
...@@ -174,6 +174,10 @@ enum tcm_sense_reason_table { ...@@ -174,6 +174,10 @@ enum tcm_sense_reason_table {
TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16),
TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17),
TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18), TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18),
TCM_TOO_MANY_TARGET_DESCS = R(0x19),
TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE = R(0x1a),
TCM_TOO_MANY_SEGMENT_DESCS = R(0x1b),
TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE = R(0x1c),
#undef R #undef R
}; };
......
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