diff options
author | Christoph Hellwig <hch@lst.de> | 2012-11-06 15:24:09 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-11-06 23:55:46 -0500 |
commit | de103c93aff0bed0ae984274e5dc8b95899badab (patch) | |
tree | 7db9bba755fa95772052e8d31285a38ba48f1a84 /drivers/target/target_core_pr.c | |
parent | fecae40abb1ae9218bdbaa8b8e30bfb5ae43f522 (diff) |
target: pass sense_reason as a return value
Pass the sense reason as an explicit return value from the I/O submission
path instead of storing it in struct se_cmd and using negative return
values. This cleans up a lot of the code pathes, and with the sparse
annotations for the new sense_reason_t type allows for much better
error checking.
(nab: Convert spc_emulate_modesense + spc_emulate_modeselect to use
sense_reason_t with Roland's MODE SELECT changes)
Signed-off-by: Christoph Hellwig <hch@lst.de>
Cc: Roland Dreier <roland@purestorage.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/target_core_pr.c')
-rw-r--r-- | drivers/target/target_core_pr.c | 918 |
1 files changed, 411 insertions, 507 deletions
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index f561a08ff8e5..ffbe0ea9bbad 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c | |||
@@ -68,7 +68,8 @@ int core_pr_dump_initiator_port( | |||
68 | static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, | 68 | static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, |
69 | struct t10_pr_registration *, int); | 69 | struct t10_pr_registration *, int); |
70 | 70 | ||
71 | static int target_scsi2_reservation_check(struct se_cmd *cmd) | 71 | static sense_reason_t |
72 | target_scsi2_reservation_check(struct se_cmd *cmd) | ||
72 | { | 73 | { |
73 | struct se_device *dev = cmd->se_dev; | 74 | struct se_device *dev = cmd->se_dev; |
74 | struct se_session *sess = cmd->se_sess; | 75 | struct se_session *sess = cmd->se_sess; |
@@ -86,11 +87,11 @@ static int target_scsi2_reservation_check(struct se_cmd *cmd) | |||
86 | return 0; | 87 | return 0; |
87 | 88 | ||
88 | if (dev->dev_reserved_node_acl != sess->se_node_acl) | 89 | if (dev->dev_reserved_node_acl != sess->se_node_acl) |
89 | return -EBUSY; | 90 | return TCM_RESERVATION_CONFLICT; |
90 | 91 | ||
91 | if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { | 92 | if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { |
92 | if (dev->dev_res_bin_isid != sess->sess_bin_isid) | 93 | if (dev->dev_res_bin_isid != sess->sess_bin_isid) |
93 | return -EBUSY; | 94 | return TCM_RESERVATION_CONFLICT; |
94 | } | 95 | } |
95 | 96 | ||
96 | return 0; | 97 | return 0; |
@@ -165,32 +166,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) | |||
165 | pr_err("Received legacy SPC-2 RESERVE/RELEASE" | 166 | pr_err("Received legacy SPC-2 RESERVE/RELEASE" |
166 | " while active SPC-3 registrations exist," | 167 | " while active SPC-3 registrations exist," |
167 | " returning RESERVATION_CONFLICT\n"); | 168 | " returning RESERVATION_CONFLICT\n"); |
168 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | ||
169 | return -EBUSY; | 169 | return -EBUSY; |
170 | } | 170 | } |
171 | 171 | ||
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
174 | 174 | ||
175 | int target_scsi2_reservation_release(struct se_cmd *cmd) | 175 | sense_reason_t |
176 | target_scsi2_reservation_release(struct se_cmd *cmd) | ||
176 | { | 177 | { |
177 | struct se_device *dev = cmd->se_dev; | 178 | struct se_device *dev = cmd->se_dev; |
178 | struct se_session *sess = cmd->se_sess; | 179 | struct se_session *sess = cmd->se_sess; |
179 | struct se_portal_group *tpg; | 180 | struct se_portal_group *tpg; |
180 | int ret = 0, rc; | 181 | int rc; |
181 | 182 | ||
182 | if (!sess || !sess->se_tpg) | 183 | if (!sess || !sess->se_tpg) |
183 | goto out; | 184 | goto out; |
184 | rc = target_check_scsi2_reservation_conflict(cmd); | 185 | rc = target_check_scsi2_reservation_conflict(cmd); |
185 | if (rc == 1) | 186 | if (rc == 1) |
186 | goto out; | 187 | goto out; |
187 | else if (rc < 0) { | 188 | if (rc < 0) |
188 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 189 | return TCM_RESERVATION_CONFLICT; |
189 | ret = -EINVAL; | ||
190 | goto out; | ||
191 | } | ||
192 | 190 | ||
193 | ret = 0; | ||
194 | spin_lock(&dev->dev_reservation_lock); | 191 | spin_lock(&dev->dev_reservation_lock); |
195 | if (!dev->dev_reserved_node_acl || !sess) | 192 | if (!dev->dev_reserved_node_acl || !sess) |
196 | goto out_unlock; | 193 | goto out_unlock; |
@@ -216,25 +213,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) | |||
216 | out_unlock: | 213 | out_unlock: |
217 | spin_unlock(&dev->dev_reservation_lock); | 214 | spin_unlock(&dev->dev_reservation_lock); |
218 | out: | 215 | out: |
219 | if (!ret) | 216 | target_complete_cmd(cmd, GOOD); |
220 | target_complete_cmd(cmd, GOOD); | 217 | return 0; |
221 | return ret; | ||
222 | } | 218 | } |
223 | 219 | ||
224 | int target_scsi2_reservation_reserve(struct se_cmd *cmd) | 220 | sense_reason_t |
221 | target_scsi2_reservation_reserve(struct se_cmd *cmd) | ||
225 | { | 222 | { |
226 | struct se_device *dev = cmd->se_dev; | 223 | struct se_device *dev = cmd->se_dev; |
227 | struct se_session *sess = cmd->se_sess; | 224 | struct se_session *sess = cmd->se_sess; |
228 | struct se_portal_group *tpg; | 225 | struct se_portal_group *tpg; |
229 | int ret = 0, rc; | 226 | sense_reason_t ret = 0; |
227 | int rc; | ||
230 | 228 | ||
231 | if ((cmd->t_task_cdb[1] & 0x01) && | 229 | if ((cmd->t_task_cdb[1] & 0x01) && |
232 | (cmd->t_task_cdb[1] & 0x02)) { | 230 | (cmd->t_task_cdb[1] & 0x02)) { |
233 | pr_err("LongIO and Obselete Bits set, returning" | 231 | pr_err("LongIO and Obselete Bits set, returning" |
234 | " ILLEGAL_REQUEST\n"); | 232 | " ILLEGAL_REQUEST\n"); |
235 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | 233 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
236 | ret = -EINVAL; | ||
237 | goto out; | ||
238 | } | 234 | } |
239 | /* | 235 | /* |
240 | * This is currently the case for target_core_mod passthrough struct se_cmd | 236 | * This is currently the case for target_core_mod passthrough struct se_cmd |
@@ -245,13 +241,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) | |||
245 | rc = target_check_scsi2_reservation_conflict(cmd); | 241 | rc = target_check_scsi2_reservation_conflict(cmd); |
246 | if (rc == 1) | 242 | if (rc == 1) |
247 | goto out; | 243 | goto out; |
248 | else if (rc < 0) { | ||
249 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | ||
250 | ret = -EINVAL; | ||
251 | goto out; | ||
252 | } | ||
253 | 244 | ||
254 | ret = 0; | 245 | if (rc < 0) |
246 | return TCM_RESERVATION_CONFLICT; | ||
247 | |||
255 | tpg = sess->se_tpg; | 248 | tpg = sess->se_tpg; |
256 | spin_lock(&dev->dev_reservation_lock); | 249 | spin_lock(&dev->dev_reservation_lock); |
257 | if (dev->dev_reserved_node_acl && | 250 | if (dev->dev_reserved_node_acl && |
@@ -265,8 +258,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) | |||
265 | " from %s \n", cmd->se_lun->unpacked_lun, | 258 | " from %s \n", cmd->se_lun->unpacked_lun, |
266 | cmd->se_deve->mapped_lun, | 259 | cmd->se_deve->mapped_lun, |
267 | sess->se_node_acl->initiatorname); | 260 | sess->se_node_acl->initiatorname); |
268 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 261 | ret = TCM_RESERVATION_CONFLICT; |
269 | ret = -EINVAL; | ||
270 | goto out_unlock; | 262 | goto out_unlock; |
271 | } | 263 | } |
272 | 264 | ||
@@ -536,7 +528,8 @@ static int core_scsi3_pr_seq_non_holder( | |||
536 | return 1; /* Conflict by default */ | 528 | return 1; /* Conflict by default */ |
537 | } | 529 | } |
538 | 530 | ||
539 | static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) | 531 | static sense_reason_t |
532 | target_scsi3_pr_reservation_check(struct se_cmd *cmd) | ||
540 | { | 533 | { |
541 | struct se_device *dev = cmd->se_dev; | 534 | struct se_device *dev = cmd->se_dev; |
542 | struct se_session *sess = cmd->se_sess; | 535 | struct se_session *sess = cmd->se_sess; |
@@ -562,7 +555,7 @@ static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) | |||
562 | 555 | ||
563 | check_nonholder: | 556 | check_nonholder: |
564 | if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) | 557 | if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) |
565 | return -EBUSY; | 558 | return TCM_RESERVATION_CONFLICT; |
566 | return 0; | 559 | return 0; |
567 | } | 560 | } |
568 | 561 | ||
@@ -1435,7 +1428,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve) | |||
1435 | smp_mb__after_atomic_dec(); | 1428 | smp_mb__after_atomic_dec(); |
1436 | } | 1429 | } |
1437 | 1430 | ||
1438 | static int core_scsi3_decode_spec_i_port( | 1431 | static sense_reason_t |
1432 | core_scsi3_decode_spec_i_port( | ||
1439 | struct se_cmd *cmd, | 1433 | struct se_cmd *cmd, |
1440 | struct se_portal_group *tpg, | 1434 | struct se_portal_group *tpg, |
1441 | unsigned char *l_isid, | 1435 | unsigned char *l_isid, |
@@ -1457,8 +1451,9 @@ static int core_scsi3_decode_spec_i_port( | |||
1457 | unsigned char *buf; | 1451 | unsigned char *buf; |
1458 | unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; | 1452 | unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; |
1459 | char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; | 1453 | char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; |
1454 | sense_reason_t ret; | ||
1460 | u32 tpdl, tid_len = 0; | 1455 | u32 tpdl, tid_len = 0; |
1461 | int ret, dest_local_nexus, prf_isid; | 1456 | int dest_local_nexus, prf_isid; |
1462 | u32 dest_rtpi = 0; | 1457 | u32 dest_rtpi = 0; |
1463 | 1458 | ||
1464 | memset(dest_iport, 0, 64); | 1459 | memset(dest_iport, 0, 64); |
@@ -1473,8 +1468,7 @@ static int core_scsi3_decode_spec_i_port( | |||
1473 | tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); | 1468 | tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); |
1474 | if (!tidh_new) { | 1469 | if (!tidh_new) { |
1475 | pr_err("Unable to allocate tidh_new\n"); | 1470 | pr_err("Unable to allocate tidh_new\n"); |
1476 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1471 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
1477 | return -EINVAL; | ||
1478 | } | 1472 | } |
1479 | INIT_LIST_HEAD(&tidh_new->dest_list); | 1473 | INIT_LIST_HEAD(&tidh_new->dest_list); |
1480 | tidh_new->dest_tpg = tpg; | 1474 | tidh_new->dest_tpg = tpg; |
@@ -1486,8 +1480,7 @@ static int core_scsi3_decode_spec_i_port( | |||
1486 | sa_res_key, all_tg_pt, aptpl); | 1480 | sa_res_key, all_tg_pt, aptpl); |
1487 | if (!local_pr_reg) { | 1481 | if (!local_pr_reg) { |
1488 | kfree(tidh_new); | 1482 | kfree(tidh_new); |
1489 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1483 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
1490 | return -ENOMEM; | ||
1491 | } | 1484 | } |
1492 | tidh_new->dest_pr_reg = local_pr_reg; | 1485 | tidh_new->dest_pr_reg = local_pr_reg; |
1493 | /* | 1486 | /* |
@@ -1501,12 +1494,16 @@ static int core_scsi3_decode_spec_i_port( | |||
1501 | if (cmd->data_length < 28) { | 1494 | if (cmd->data_length < 28) { |
1502 | pr_warn("SPC-PR: Received PR OUT parameter list" | 1495 | pr_warn("SPC-PR: Received PR OUT parameter list" |
1503 | " length too small: %u\n", cmd->data_length); | 1496 | " length too small: %u\n", cmd->data_length); |
1504 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1497 | ret = TCM_INVALID_PARAMETER_LIST; |
1505 | ret = -EINVAL; | ||
1506 | goto out; | 1498 | goto out; |
1507 | } | 1499 | } |
1508 | 1500 | ||
1509 | buf = transport_kmap_data_sg(cmd); | 1501 | buf = transport_kmap_data_sg(cmd); |
1502 | if (!buf) { | ||
1503 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
1504 | goto out; | ||
1505 | } | ||
1506 | |||
1510 | /* | 1507 | /* |
1511 | * For a PERSISTENT RESERVE OUT specify initiator ports payload, | 1508 | * For a PERSISTENT RESERVE OUT specify initiator ports payload, |
1512 | * first extract TransportID Parameter Data Length, and make sure | 1509 | * first extract TransportID Parameter Data Length, and make sure |
@@ -1521,9 +1518,8 @@ static int core_scsi3_decode_spec_i_port( | |||
1521 | pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" | 1518 | pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" |
1522 | " does not equal CDB data_length: %u\n", tpdl, | 1519 | " does not equal CDB data_length: %u\n", tpdl, |
1523 | cmd->data_length); | 1520 | cmd->data_length); |
1524 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1521 | ret = TCM_INVALID_PARAMETER_LIST; |
1525 | ret = -EINVAL; | 1522 | goto out_unmap; |
1526 | goto out; | ||
1527 | } | 1523 | } |
1528 | /* | 1524 | /* |
1529 | * Start processing the received transport IDs using the | 1525 | * Start processing the received transport IDs using the |
@@ -1566,16 +1562,13 @@ static int core_scsi3_decode_spec_i_port( | |||
1566 | smp_mb__after_atomic_inc(); | 1562 | smp_mb__after_atomic_inc(); |
1567 | spin_unlock(&dev->se_port_lock); | 1563 | spin_unlock(&dev->se_port_lock); |
1568 | 1564 | ||
1569 | ret = core_scsi3_tpg_depend_item(tmp_tpg); | 1565 | if (core_scsi3_tpg_depend_item(tmp_tpg)) { |
1570 | if (ret != 0) { | ||
1571 | pr_err(" core_scsi3_tpg_depend_item()" | 1566 | pr_err(" core_scsi3_tpg_depend_item()" |
1572 | " for tmp_tpg\n"); | 1567 | " for tmp_tpg\n"); |
1573 | atomic_dec(&tmp_tpg->tpg_pr_ref_count); | 1568 | atomic_dec(&tmp_tpg->tpg_pr_ref_count); |
1574 | smp_mb__after_atomic_dec(); | 1569 | smp_mb__after_atomic_dec(); |
1575 | cmd->scsi_sense_reason = | 1570 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
1576 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1571 | goto out_unmap; |
1577 | ret = -EINVAL; | ||
1578 | goto out; | ||
1579 | } | 1572 | } |
1580 | /* | 1573 | /* |
1581 | * Locate the destination initiator ACL to be registered | 1574 | * Locate the destination initiator ACL to be registered |
@@ -1597,17 +1590,14 @@ static int core_scsi3_decode_spec_i_port( | |||
1597 | continue; | 1590 | continue; |
1598 | } | 1591 | } |
1599 | 1592 | ||
1600 | ret = core_scsi3_nodeacl_depend_item(dest_node_acl); | 1593 | if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { |
1601 | if (ret != 0) { | ||
1602 | pr_err("configfs_depend_item() failed" | 1594 | pr_err("configfs_depend_item() failed" |
1603 | " for dest_node_acl->acl_group\n"); | 1595 | " for dest_node_acl->acl_group\n"); |
1604 | atomic_dec(&dest_node_acl->acl_pr_ref_count); | 1596 | atomic_dec(&dest_node_acl->acl_pr_ref_count); |
1605 | smp_mb__after_atomic_dec(); | 1597 | smp_mb__after_atomic_dec(); |
1606 | core_scsi3_tpg_undepend_item(tmp_tpg); | 1598 | core_scsi3_tpg_undepend_item(tmp_tpg); |
1607 | cmd->scsi_sense_reason = | 1599 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
1608 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1600 | goto out_unmap; |
1609 | ret = -EINVAL; | ||
1610 | goto out; | ||
1611 | } | 1601 | } |
1612 | 1602 | ||
1613 | dest_tpg = tmp_tpg; | 1603 | dest_tpg = tmp_tpg; |
@@ -1624,9 +1614,8 @@ static int core_scsi3_decode_spec_i_port( | |||
1624 | if (!dest_tpg) { | 1614 | if (!dest_tpg) { |
1625 | pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" | 1615 | pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" |
1626 | " dest_tpg\n"); | 1616 | " dest_tpg\n"); |
1627 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1617 | ret = TCM_INVALID_PARAMETER_LIST; |
1628 | ret = -EINVAL; | 1618 | goto out_unmap; |
1629 | goto out; | ||
1630 | } | 1619 | } |
1631 | 1620 | ||
1632 | pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u" | 1621 | pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u" |
@@ -1639,9 +1628,8 @@ static int core_scsi3_decode_spec_i_port( | |||
1639 | " %u for Transport ID: %s\n", tid_len, ptr); | 1628 | " %u for Transport ID: %s\n", tid_len, ptr); |
1640 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1629 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
1641 | core_scsi3_tpg_undepend_item(dest_tpg); | 1630 | core_scsi3_tpg_undepend_item(dest_tpg); |
1642 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1631 | ret = TCM_INVALID_PARAMETER_LIST; |
1643 | ret = -EINVAL; | 1632 | goto out_unmap; |
1644 | goto out; | ||
1645 | } | 1633 | } |
1646 | /* | 1634 | /* |
1647 | * Locate the desintation struct se_dev_entry pointer for matching | 1635 | * Locate the desintation struct se_dev_entry pointer for matching |
@@ -1658,23 +1646,19 @@ static int core_scsi3_decode_spec_i_port( | |||
1658 | 1646 | ||
1659 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1647 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
1660 | core_scsi3_tpg_undepend_item(dest_tpg); | 1648 | core_scsi3_tpg_undepend_item(dest_tpg); |
1661 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1649 | ret = TCM_INVALID_PARAMETER_LIST; |
1662 | ret = -EINVAL; | 1650 | goto out_unmap; |
1663 | goto out; | ||
1664 | } | 1651 | } |
1665 | 1652 | ||
1666 | ret = core_scsi3_lunacl_depend_item(dest_se_deve); | 1653 | if (core_scsi3_lunacl_depend_item(dest_se_deve)) { |
1667 | if (ret < 0) { | ||
1668 | pr_err("core_scsi3_lunacl_depend_item()" | 1654 | pr_err("core_scsi3_lunacl_depend_item()" |
1669 | " failed\n"); | 1655 | " failed\n"); |
1670 | atomic_dec(&dest_se_deve->pr_ref_count); | 1656 | atomic_dec(&dest_se_deve->pr_ref_count); |
1671 | smp_mb__after_atomic_dec(); | 1657 | smp_mb__after_atomic_dec(); |
1672 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1658 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
1673 | core_scsi3_tpg_undepend_item(dest_tpg); | 1659 | core_scsi3_tpg_undepend_item(dest_tpg); |
1674 | cmd->scsi_sense_reason = | 1660 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
1675 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1661 | goto out_unmap; |
1676 | ret = -EINVAL; | ||
1677 | goto out; | ||
1678 | } | 1662 | } |
1679 | 1663 | ||
1680 | pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" | 1664 | pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" |
@@ -1710,10 +1694,8 @@ static int core_scsi3_decode_spec_i_port( | |||
1710 | core_scsi3_lunacl_undepend_item(dest_se_deve); | 1694 | core_scsi3_lunacl_undepend_item(dest_se_deve); |
1711 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1695 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
1712 | core_scsi3_tpg_undepend_item(dest_tpg); | 1696 | core_scsi3_tpg_undepend_item(dest_tpg); |
1713 | cmd->scsi_sense_reason = | 1697 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
1714 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 1698 | goto out_unmap; |
1715 | ret = -ENOMEM; | ||
1716 | goto out; | ||
1717 | } | 1699 | } |
1718 | INIT_LIST_HEAD(&tidh_new->dest_list); | 1700 | INIT_LIST_HEAD(&tidh_new->dest_list); |
1719 | tidh_new->dest_tpg = dest_tpg; | 1701 | tidh_new->dest_tpg = dest_tpg; |
@@ -1744,9 +1726,8 @@ static int core_scsi3_decode_spec_i_port( | |||
1744 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 1726 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
1745 | core_scsi3_tpg_undepend_item(dest_tpg); | 1727 | core_scsi3_tpg_undepend_item(dest_tpg); |
1746 | kfree(tidh_new); | 1728 | kfree(tidh_new); |
1747 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 1729 | ret = TCM_INVALID_PARAMETER_LIST; |
1748 | ret = -EINVAL; | 1730 | goto out_unmap; |
1749 | goto out; | ||
1750 | } | 1731 | } |
1751 | tidh_new->dest_pr_reg = dest_pr_reg; | 1732 | tidh_new->dest_pr_reg = dest_pr_reg; |
1752 | list_add_tail(&tidh_new->dest_list, &tid_dest_list); | 1733 | list_add_tail(&tidh_new->dest_list, &tid_dest_list); |
@@ -1804,8 +1785,9 @@ static int core_scsi3_decode_spec_i_port( | |||
1804 | } | 1785 | } |
1805 | 1786 | ||
1806 | return 0; | 1787 | return 0; |
1807 | out: | 1788 | out_unmap: |
1808 | transport_kunmap_data_sg(cmd); | 1789 | transport_kunmap_data_sg(cmd); |
1790 | out: | ||
1809 | /* | 1791 | /* |
1810 | * For the failure case, release everything from tid_dest_list | 1792 | * For the failure case, release everything from tid_dest_list |
1811 | * including *dest_pr_reg and the configfs dependances.. | 1793 | * including *dest_pr_reg and the configfs dependances.. |
@@ -2020,14 +2002,15 @@ static int __core_scsi3_write_aptpl_to_file( | |||
2020 | return 0; | 2002 | return 0; |
2021 | } | 2003 | } |
2022 | 2004 | ||
2023 | static int core_scsi3_update_and_write_aptpl( | 2005 | static int |
2024 | struct se_device *dev, | 2006 | core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, |
2025 | unsigned char *in_buf, | 2007 | u32 in_pr_aptpl_buf_len) |
2026 | u32 in_pr_aptpl_buf_len) | ||
2027 | { | 2008 | { |
2028 | unsigned char null_buf[64], *buf; | 2009 | unsigned char null_buf[64], *buf; |
2029 | u32 pr_aptpl_buf_len; | 2010 | u32 pr_aptpl_buf_len; |
2030 | int ret, clear_aptpl_metadata = 0; | 2011 | int clear_aptpl_metadata = 0; |
2012 | int ret; | ||
2013 | |||
2031 | /* | 2014 | /* |
2032 | * Can be called with a NULL pointer from PROUT service action CLEAR | 2015 | * Can be called with a NULL pointer from PROUT service action CLEAR |
2033 | */ | 2016 | */ |
@@ -2049,25 +2032,17 @@ static int core_scsi3_update_and_write_aptpl( | |||
2049 | clear_aptpl_metadata); | 2032 | clear_aptpl_metadata); |
2050 | if (ret != 0) | 2033 | if (ret != 0) |
2051 | return ret; | 2034 | return ret; |
2035 | |||
2052 | /* | 2036 | /* |
2053 | * __core_scsi3_write_aptpl_to_file() will call strlen() | 2037 | * __core_scsi3_write_aptpl_to_file() will call strlen() |
2054 | * on the passed buf to determine pr_aptpl_buf_len. | 2038 | * on the passed buf to determine pr_aptpl_buf_len. |
2055 | */ | 2039 | */ |
2056 | ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0); | 2040 | return __core_scsi3_write_aptpl_to_file(dev, buf, 0); |
2057 | if (ret != 0) | ||
2058 | return ret; | ||
2059 | |||
2060 | return ret; | ||
2061 | } | 2041 | } |
2062 | 2042 | ||
2063 | static int core_scsi3_emulate_pro_register( | 2043 | static sense_reason_t |
2064 | struct se_cmd *cmd, | 2044 | core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, |
2065 | u64 res_key, | 2045 | int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key) |
2066 | u64 sa_res_key, | ||
2067 | int aptpl, | ||
2068 | int all_tg_pt, | ||
2069 | int spec_i_pt, | ||
2070 | int ignore_key) | ||
2071 | { | 2046 | { |
2072 | struct se_session *se_sess = cmd->se_sess; | 2047 | struct se_session *se_sess = cmd->se_sess; |
2073 | struct se_device *dev = cmd->se_dev; | 2048 | struct se_device *dev = cmd->se_dev; |
@@ -2079,12 +2054,12 @@ static int core_scsi3_emulate_pro_register( | |||
2079 | /* Used for APTPL metadata w/ UNREGISTER */ | 2054 | /* Used for APTPL metadata w/ UNREGISTER */ |
2080 | unsigned char *pr_aptpl_buf = NULL; | 2055 | unsigned char *pr_aptpl_buf = NULL; |
2081 | unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; | 2056 | unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; |
2082 | int pr_holder = 0, ret = 0, type; | 2057 | sense_reason_t ret; |
2058 | int pr_holder = 0, type; | ||
2083 | 2059 | ||
2084 | if (!se_sess || !se_lun) { | 2060 | if (!se_sess || !se_lun) { |
2085 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); | 2061 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); |
2086 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2062 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
2087 | return -EINVAL; | ||
2088 | } | 2063 | } |
2089 | se_tpg = se_sess->se_tpg; | 2064 | se_tpg = se_sess->se_tpg; |
2090 | se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; | 2065 | se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; |
@@ -2103,8 +2078,7 @@ static int core_scsi3_emulate_pro_register( | |||
2103 | if (res_key) { | 2078 | if (res_key) { |
2104 | pr_warn("SPC-3 PR: Reservation Key non-zero" | 2079 | pr_warn("SPC-3 PR: Reservation Key non-zero" |
2105 | " for SA REGISTER, returning CONFLICT\n"); | 2080 | " for SA REGISTER, returning CONFLICT\n"); |
2106 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2081 | return TCM_RESERVATION_CONFLICT; |
2107 | return -EINVAL; | ||
2108 | } | 2082 | } |
2109 | /* | 2083 | /* |
2110 | * Do nothing but return GOOD status. | 2084 | * Do nothing but return GOOD status. |
@@ -2118,15 +2092,13 @@ static int core_scsi3_emulate_pro_register( | |||
2118 | * Port Endpoint that the PRO was received from on the | 2092 | * Port Endpoint that the PRO was received from on the |
2119 | * Logical Unit of the SCSI device server. | 2093 | * Logical Unit of the SCSI device server. |
2120 | */ | 2094 | */ |
2121 | ret = core_scsi3_alloc_registration(cmd->se_dev, | 2095 | if (core_scsi3_alloc_registration(cmd->se_dev, |
2122 | se_sess->se_node_acl, se_deve, isid_ptr, | 2096 | se_sess->se_node_acl, se_deve, isid_ptr, |
2123 | sa_res_key, all_tg_pt, aptpl, | 2097 | sa_res_key, all_tg_pt, aptpl, |
2124 | ignore_key, 0); | 2098 | ignore_key, 0)) { |
2125 | if (ret != 0) { | ||
2126 | pr_err("Unable to allocate" | 2099 | pr_err("Unable to allocate" |
2127 | " struct t10_pr_registration\n"); | 2100 | " struct t10_pr_registration\n"); |
2128 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2101 | return TCM_INVALID_PARAMETER_LIST; |
2129 | return -EINVAL; | ||
2130 | } | 2102 | } |
2131 | } else { | 2103 | } else { |
2132 | /* | 2104 | /* |
@@ -2160,201 +2132,192 @@ static int core_scsi3_emulate_pro_register( | |||
2160 | pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, | 2132 | pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, |
2161 | se_sess->se_node_acl, se_sess); | 2133 | se_sess->se_node_acl, se_sess); |
2162 | 2134 | ||
2163 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 2135 | if (core_scsi3_update_and_write_aptpl(cmd->se_dev, |
2164 | &pr_reg->pr_aptpl_buf[0], | 2136 | &pr_reg->pr_aptpl_buf[0], |
2165 | pr_tmpl->pr_aptpl_buf_len); | 2137 | pr_tmpl->pr_aptpl_buf_len)) { |
2166 | if (!ret) { | ||
2167 | pr_tmpl->pr_aptpl_active = 1; | 2138 | pr_tmpl->pr_aptpl_active = 1; |
2168 | pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); | 2139 | pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); |
2169 | } | 2140 | } |
2170 | 2141 | ||
2171 | core_scsi3_put_pr_reg(pr_reg); | 2142 | goto out_put_pr_reg; |
2172 | return ret; | 2143 | } |
2173 | } else { | 2144 | |
2174 | /* | 2145 | /* |
2175 | * Locate the existing *pr_reg via struct se_node_acl pointers | 2146 | * Locate the existing *pr_reg via struct se_node_acl pointers |
2176 | */ | 2147 | */ |
2177 | pr_reg = pr_reg_e; | 2148 | pr_reg = pr_reg_e; |
2178 | type = pr_reg->pr_res_type; | 2149 | type = pr_reg->pr_res_type; |
2179 | 2150 | ||
2180 | if (!ignore_key) { | 2151 | if (!ignore_key) { |
2181 | if (res_key != pr_reg->pr_res_key) { | 2152 | if (res_key != pr_reg->pr_res_key) { |
2182 | pr_err("SPC-3 PR REGISTER: Received" | 2153 | pr_err("SPC-3 PR REGISTER: Received" |
2183 | " res_key: 0x%016Lx does not match" | 2154 | " res_key: 0x%016Lx does not match" |
2184 | " existing SA REGISTER res_key:" | 2155 | " existing SA REGISTER res_key:" |
2185 | " 0x%016Lx\n", res_key, | 2156 | " 0x%016Lx\n", res_key, |
2186 | pr_reg->pr_res_key); | 2157 | pr_reg->pr_res_key); |
2187 | core_scsi3_put_pr_reg(pr_reg); | 2158 | ret = TCM_RESERVATION_CONFLICT; |
2188 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2159 | goto out_put_pr_reg; |
2189 | return -EINVAL; | ||
2190 | } | ||
2191 | } | 2160 | } |
2192 | if (spec_i_pt) { | 2161 | } |
2193 | pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" | 2162 | |
2194 | " set while sa_res_key=0\n"); | 2163 | if (spec_i_pt) { |
2195 | core_scsi3_put_pr_reg(pr_reg); | 2164 | pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" |
2196 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2165 | " set while sa_res_key=0\n"); |
2197 | return -EINVAL; | 2166 | ret = TCM_INVALID_PARAMETER_LIST; |
2167 | goto out_put_pr_reg; | ||
2168 | } | ||
2169 | |||
2170 | /* | ||
2171 | * An existing ALL_TG_PT=1 registration being released | ||
2172 | * must also set ALL_TG_PT=1 in the incoming PROUT. | ||
2173 | */ | ||
2174 | if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { | ||
2175 | pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" | ||
2176 | " registration exists, but ALL_TG_PT=1 bit not" | ||
2177 | " present in received PROUT\n"); | ||
2178 | ret = TCM_INVALID_CDB_FIELD; | ||
2179 | goto out_put_pr_reg; | ||
2180 | } | ||
2181 | |||
2182 | /* | ||
2183 | * Allocate APTPL metadata buffer used for UNREGISTER ops | ||
2184 | */ | ||
2185 | if (aptpl) { | ||
2186 | pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, | ||
2187 | GFP_KERNEL); | ||
2188 | if (!pr_aptpl_buf) { | ||
2189 | pr_err("Unable to allocate" | ||
2190 | " pr_aptpl_buf\n"); | ||
2191 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
2192 | goto out_put_pr_reg; | ||
2198 | } | 2193 | } |
2199 | /* | 2194 | } |
2200 | * An existing ALL_TG_PT=1 registration being released | 2195 | |
2201 | * must also set ALL_TG_PT=1 in the incoming PROUT. | 2196 | /* |
2202 | */ | 2197 | * sa_res_key=0 Unregister Reservation Key for registered I_T |
2203 | if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { | 2198 | * Nexus sa_res_key=1 Change Reservation Key for registered I_T |
2204 | pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" | 2199 | * Nexus. |
2205 | " registration exists, but ALL_TG_PT=1 bit not" | 2200 | */ |
2206 | " present in received PROUT\n"); | 2201 | if (!sa_res_key) { |
2207 | core_scsi3_put_pr_reg(pr_reg); | 2202 | pr_holder = core_scsi3_check_implict_release( |
2208 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 2203 | cmd->se_dev, pr_reg); |
2209 | return -EINVAL; | 2204 | if (pr_holder < 0) { |
2205 | kfree(pr_aptpl_buf); | ||
2206 | ret = TCM_RESERVATION_CONFLICT; | ||
2207 | goto out_put_pr_reg; | ||
2210 | } | 2208 | } |
2209 | |||
2210 | spin_lock(&pr_tmpl->registration_lock); | ||
2211 | /* | 2211 | /* |
2212 | * Allocate APTPL metadata buffer used for UNREGISTER ops | 2212 | * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port |
2213 | * and matching pr_res_key. | ||
2213 | */ | 2214 | */ |
2214 | if (aptpl) { | 2215 | if (pr_reg->pr_reg_all_tg_pt) { |
2215 | pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, | 2216 | list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, |
2216 | GFP_KERNEL); | 2217 | &pr_tmpl->registration_list, |
2217 | if (!pr_aptpl_buf) { | 2218 | pr_reg_list) { |
2218 | pr_err("Unable to allocate" | 2219 | |
2219 | " pr_aptpl_buf\n"); | 2220 | if (!pr_reg_p->pr_reg_all_tg_pt) |
2220 | core_scsi3_put_pr_reg(pr_reg); | 2221 | continue; |
2221 | cmd->scsi_sense_reason = | 2222 | if (pr_reg_p->pr_res_key != res_key) |
2222 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2223 | continue; |
2223 | return -EINVAL; | 2224 | if (pr_reg == pr_reg_p) |
2225 | continue; | ||
2226 | if (strcmp(pr_reg->pr_reg_nacl->initiatorname, | ||
2227 | pr_reg_p->pr_reg_nacl->initiatorname)) | ||
2228 | continue; | ||
2229 | |||
2230 | __core_scsi3_free_registration(dev, | ||
2231 | pr_reg_p, NULL, 0); | ||
2224 | } | 2232 | } |
2225 | } | 2233 | } |
2234 | |||
2226 | /* | 2235 | /* |
2227 | * sa_res_key=0 Unregister Reservation Key for registered I_T | 2236 | * Release the calling I_T Nexus registration now.. |
2228 | * Nexus sa_res_key=1 Change Reservation Key for registered I_T | ||
2229 | * Nexus. | ||
2230 | */ | 2237 | */ |
2231 | if (!sa_res_key) { | 2238 | __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1); |
2232 | pr_holder = core_scsi3_check_implict_release( | ||
2233 | cmd->se_dev, pr_reg); | ||
2234 | if (pr_holder < 0) { | ||
2235 | kfree(pr_aptpl_buf); | ||
2236 | core_scsi3_put_pr_reg(pr_reg); | ||
2237 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | ||
2238 | return -EINVAL; | ||
2239 | } | ||
2240 | |||
2241 | spin_lock(&pr_tmpl->registration_lock); | ||
2242 | /* | ||
2243 | * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port | ||
2244 | * and matching pr_res_key. | ||
2245 | */ | ||
2246 | if (pr_reg->pr_reg_all_tg_pt) { | ||
2247 | list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, | ||
2248 | &pr_tmpl->registration_list, | ||
2249 | pr_reg_list) { | ||
2250 | |||
2251 | if (!pr_reg_p->pr_reg_all_tg_pt) | ||
2252 | continue; | ||
2253 | 2239 | ||
2254 | if (pr_reg_p->pr_res_key != res_key) | 2240 | /* |
2255 | continue; | 2241 | * From spc4r17, section 5.7.11.3 Unregistering |
2256 | 2242 | * | |
2257 | if (pr_reg == pr_reg_p) | 2243 | * If the persistent reservation is a registrants only |
2258 | continue; | 2244 | * type, the device server shall establish a unit |
2259 | 2245 | * attention condition for the initiator port associated | |
2260 | if (strcmp(pr_reg->pr_reg_nacl->initiatorname, | 2246 | * with every registered I_T nexus except for the I_T |
2261 | pr_reg_p->pr_reg_nacl->initiatorname)) | 2247 | * nexus on which the PERSISTENT RESERVE OUT command was |
2262 | continue; | 2248 | * received, with the additional sense code set to |
2263 | 2249 | * RESERVATIONS RELEASED. | |
2264 | __core_scsi3_free_registration(dev, | 2250 | */ |
2265 | pr_reg_p, NULL, 0); | 2251 | if (pr_holder && |
2266 | } | 2252 | (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || |
2267 | } | 2253 | type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { |
2268 | /* | 2254 | list_for_each_entry(pr_reg_p, |
2269 | * Release the calling I_T Nexus registration now.. | 2255 | &pr_tmpl->registration_list, |
2270 | */ | 2256 | pr_reg_list) { |
2271 | __core_scsi3_free_registration(cmd->se_dev, pr_reg, | 2257 | |
2272 | NULL, 1); | 2258 | core_scsi3_ua_allocate( |
2273 | /* | 2259 | pr_reg_p->pr_reg_nacl, |
2274 | * From spc4r17, section 5.7.11.3 Unregistering | 2260 | pr_reg_p->pr_res_mapped_lun, |
2275 | * | 2261 | 0x2A, |
2276 | * If the persistent reservation is a registrants only | 2262 | ASCQ_2AH_RESERVATIONS_RELEASED); |
2277 | * type, the device server shall establish a unit | ||
2278 | * attention condition for the initiator port associated | ||
2279 | * with every registered I_T nexus except for the I_T | ||
2280 | * nexus on which the PERSISTENT RESERVE OUT command was | ||
2281 | * received, with the additional sense code set to | ||
2282 | * RESERVATIONS RELEASED. | ||
2283 | */ | ||
2284 | if (pr_holder && | ||
2285 | ((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) || | ||
2286 | (type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) { | ||
2287 | list_for_each_entry(pr_reg_p, | ||
2288 | &pr_tmpl->registration_list, | ||
2289 | pr_reg_list) { | ||
2290 | |||
2291 | core_scsi3_ua_allocate( | ||
2292 | pr_reg_p->pr_reg_nacl, | ||
2293 | pr_reg_p->pr_res_mapped_lun, | ||
2294 | 0x2A, | ||
2295 | ASCQ_2AH_RESERVATIONS_RELEASED); | ||
2296 | } | ||
2297 | } | 2263 | } |
2298 | spin_unlock(&pr_tmpl->registration_lock); | 2264 | } |
2265 | spin_unlock(&pr_tmpl->registration_lock); | ||
2299 | 2266 | ||
2300 | if (!aptpl) { | 2267 | if (!aptpl) { |
2301 | pr_tmpl->pr_aptpl_active = 0; | 2268 | pr_tmpl->pr_aptpl_active = 0; |
2302 | core_scsi3_update_and_write_aptpl(dev, NULL, 0); | 2269 | core_scsi3_update_and_write_aptpl(dev, NULL, 0); |
2303 | pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" | 2270 | pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" |
2304 | " for UNREGISTER\n"); | 2271 | " for UNREGISTER\n"); |
2305 | return 0; | 2272 | return 0; |
2306 | } | 2273 | } |
2307 | 2274 | ||
2308 | ret = core_scsi3_update_and_write_aptpl(dev, | 2275 | if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], |
2309 | &pr_aptpl_buf[0], | 2276 | pr_tmpl->pr_aptpl_buf_len)) { |
2310 | pr_tmpl->pr_aptpl_buf_len); | 2277 | pr_tmpl->pr_aptpl_active = 1; |
2311 | if (!ret) { | 2278 | pr_debug("SPC-3 PR: Set APTPL Bit Activated" |
2312 | pr_tmpl->pr_aptpl_active = 1; | 2279 | " for UNREGISTER\n"); |
2313 | pr_debug("SPC-3 PR: Set APTPL Bit Activated" | 2280 | } |
2314 | " for UNREGISTER\n"); | ||
2315 | } | ||
2316 | 2281 | ||
2317 | kfree(pr_aptpl_buf); | 2282 | goto out_free_aptpl_buf; |
2318 | return ret; | 2283 | } |
2319 | } else { | ||
2320 | /* | ||
2321 | * Increment PRgeneration counter for struct se_device" | ||
2322 | * upon a successful REGISTER, see spc4r17 section 6.3.2 | ||
2323 | * READ_KEYS service action. | ||
2324 | */ | ||
2325 | pr_reg->pr_res_generation = core_scsi3_pr_generation( | ||
2326 | cmd->se_dev); | ||
2327 | pr_reg->pr_res_key = sa_res_key; | ||
2328 | pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" | ||
2329 | " Key for %s to: 0x%016Lx PRgeneration:" | ||
2330 | " 0x%08x\n", cmd->se_tfo->get_fabric_name(), | ||
2331 | (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", | ||
2332 | pr_reg->pr_reg_nacl->initiatorname, | ||
2333 | pr_reg->pr_res_key, pr_reg->pr_res_generation); | ||
2334 | |||
2335 | if (!aptpl) { | ||
2336 | pr_tmpl->pr_aptpl_active = 0; | ||
2337 | core_scsi3_update_and_write_aptpl(dev, NULL, 0); | ||
2338 | core_scsi3_put_pr_reg(pr_reg); | ||
2339 | pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" | ||
2340 | " for REGISTER\n"); | ||
2341 | return 0; | ||
2342 | } | ||
2343 | 2284 | ||
2344 | ret = core_scsi3_update_and_write_aptpl(dev, | 2285 | /* |
2345 | &pr_aptpl_buf[0], | 2286 | * Increment PRgeneration counter for struct se_device" |
2346 | pr_tmpl->pr_aptpl_buf_len); | 2287 | * upon a successful REGISTER, see spc4r17 section 6.3.2 |
2347 | if (!ret) { | 2288 | * READ_KEYS service action. |
2348 | pr_tmpl->pr_aptpl_active = 1; | 2289 | */ |
2349 | pr_debug("SPC-3 PR: Set APTPL Bit Activated" | 2290 | pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev); |
2350 | " for REGISTER\n"); | 2291 | pr_reg->pr_res_key = sa_res_key; |
2351 | } | 2292 | pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" |
2293 | " Key for %s to: 0x%016Lx PRgeneration:" | ||
2294 | " 0x%08x\n", cmd->se_tfo->get_fabric_name(), | ||
2295 | (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", | ||
2296 | pr_reg->pr_reg_nacl->initiatorname, | ||
2297 | pr_reg->pr_res_key, pr_reg->pr_res_generation); | ||
2352 | 2298 | ||
2353 | kfree(pr_aptpl_buf); | 2299 | if (!aptpl) { |
2354 | core_scsi3_put_pr_reg(pr_reg); | 2300 | pr_tmpl->pr_aptpl_active = 0; |
2355 | } | 2301 | core_scsi3_update_and_write_aptpl(dev, NULL, 0); |
2302 | pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" | ||
2303 | " for REGISTER\n"); | ||
2304 | ret = 0; | ||
2305 | goto out_put_pr_reg; | ||
2356 | } | 2306 | } |
2357 | return 0; | 2307 | |
2308 | if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], | ||
2309 | pr_tmpl->pr_aptpl_buf_len)) { | ||
2310 | pr_tmpl->pr_aptpl_active = 1; | ||
2311 | pr_debug("SPC-3 PR: Set APTPL Bit Activated" | ||
2312 | " for REGISTER\n"); | ||
2313 | } | ||
2314 | |||
2315 | out_free_aptpl_buf: | ||
2316 | kfree(pr_aptpl_buf); | ||
2317 | ret = 0; | ||
2318 | out_put_pr_reg: | ||
2319 | core_scsi3_put_pr_reg(pr_reg); | ||
2320 | return ret; | ||
2358 | } | 2321 | } |
2359 | 2322 | ||
2360 | unsigned char *core_scsi3_pr_dump_type(int type) | 2323 | unsigned char *core_scsi3_pr_dump_type(int type) |
@@ -2379,26 +2342,23 @@ unsigned char *core_scsi3_pr_dump_type(int type) | |||
2379 | return "Unknown SPC-3 PR Type"; | 2342 | return "Unknown SPC-3 PR Type"; |
2380 | } | 2343 | } |
2381 | 2344 | ||
2382 | static int core_scsi3_pro_reserve( | 2345 | static sense_reason_t |
2383 | struct se_cmd *cmd, | 2346 | core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) |
2384 | struct se_device *dev, | ||
2385 | int type, | ||
2386 | int scope, | ||
2387 | u64 res_key) | ||
2388 | { | 2347 | { |
2348 | struct se_device *dev = cmd->se_dev; | ||
2389 | struct se_session *se_sess = cmd->se_sess; | 2349 | struct se_session *se_sess = cmd->se_sess; |
2390 | struct se_lun *se_lun = cmd->se_lun; | 2350 | struct se_lun *se_lun = cmd->se_lun; |
2391 | struct t10_pr_registration *pr_reg, *pr_res_holder; | 2351 | struct t10_pr_registration *pr_reg, *pr_res_holder; |
2392 | struct t10_reservation *pr_tmpl = &dev->t10_pr; | 2352 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
2393 | char i_buf[PR_REG_ISID_ID_LEN]; | 2353 | char i_buf[PR_REG_ISID_ID_LEN]; |
2394 | int ret, prf_isid; | 2354 | sense_reason_t ret; |
2355 | int prf_isid; | ||
2395 | 2356 | ||
2396 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); | 2357 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); |
2397 | 2358 | ||
2398 | if (!se_sess || !se_lun) { | 2359 | if (!se_sess || !se_lun) { |
2399 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); | 2360 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); |
2400 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2361 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
2401 | return -EINVAL; | ||
2402 | } | 2362 | } |
2403 | /* | 2363 | /* |
2404 | * Locate the existing *pr_reg via struct se_node_acl pointers | 2364 | * Locate the existing *pr_reg via struct se_node_acl pointers |
@@ -2408,8 +2368,7 @@ static int core_scsi3_pro_reserve( | |||
2408 | if (!pr_reg) { | 2368 | if (!pr_reg) { |
2409 | pr_err("SPC-3 PR: Unable to locate" | 2369 | pr_err("SPC-3 PR: Unable to locate" |
2410 | " PR_REGISTERED *pr_reg for RESERVE\n"); | 2370 | " PR_REGISTERED *pr_reg for RESERVE\n"); |
2411 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2371 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
2412 | return -EINVAL; | ||
2413 | } | 2372 | } |
2414 | /* | 2373 | /* |
2415 | * From spc4r17 Section 5.7.9: Reserving: | 2374 | * From spc4r17 Section 5.7.9: Reserving: |
@@ -2424,9 +2383,8 @@ static int core_scsi3_pro_reserve( | |||
2424 | pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx" | 2383 | pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx" |
2425 | " does not match existing SA REGISTER res_key:" | 2384 | " does not match existing SA REGISTER res_key:" |
2426 | " 0x%016Lx\n", res_key, pr_reg->pr_res_key); | 2385 | " 0x%016Lx\n", res_key, pr_reg->pr_res_key); |
2427 | core_scsi3_put_pr_reg(pr_reg); | 2386 | ret = TCM_RESERVATION_CONFLICT; |
2428 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2387 | goto out_put_pr_reg; |
2429 | return -EINVAL; | ||
2430 | } | 2388 | } |
2431 | /* | 2389 | /* |
2432 | * From spc4r17 Section 5.7.9: Reserving: | 2390 | * From spc4r17 Section 5.7.9: Reserving: |
@@ -2440,9 +2398,8 @@ static int core_scsi3_pro_reserve( | |||
2440 | */ | 2398 | */ |
2441 | if (scope != PR_SCOPE_LU_SCOPE) { | 2399 | if (scope != PR_SCOPE_LU_SCOPE) { |
2442 | pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); | 2400 | pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); |
2443 | core_scsi3_put_pr_reg(pr_reg); | 2401 | ret = TCM_INVALID_PARAMETER_LIST; |
2444 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2402 | goto out_put_pr_reg; |
2445 | return -EINVAL; | ||
2446 | } | 2403 | } |
2447 | /* | 2404 | /* |
2448 | * See if we have an existing PR reservation holder pointer at | 2405 | * See if we have an existing PR reservation holder pointer at |
@@ -2473,9 +2430,8 @@ static int core_scsi3_pro_reserve( | |||
2473 | pr_res_holder->pr_reg_nacl->initiatorname); | 2430 | pr_res_holder->pr_reg_nacl->initiatorname); |
2474 | 2431 | ||
2475 | spin_unlock(&dev->dev_reservation_lock); | 2432 | spin_unlock(&dev->dev_reservation_lock); |
2476 | core_scsi3_put_pr_reg(pr_reg); | 2433 | ret = TCM_RESERVATION_CONFLICT; |
2477 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2434 | goto out_put_pr_reg; |
2478 | return -EINVAL; | ||
2479 | } | 2435 | } |
2480 | /* | 2436 | /* |
2481 | * From spc4r17 Section 5.7.9: Reserving: | 2437 | * From spc4r17 Section 5.7.9: Reserving: |
@@ -2497,9 +2453,8 @@ static int core_scsi3_pro_reserve( | |||
2497 | pr_res_holder->pr_reg_nacl->initiatorname); | 2453 | pr_res_holder->pr_reg_nacl->initiatorname); |
2498 | 2454 | ||
2499 | spin_unlock(&dev->dev_reservation_lock); | 2455 | spin_unlock(&dev->dev_reservation_lock); |
2500 | core_scsi3_put_pr_reg(pr_reg); | 2456 | ret = TCM_RESERVATION_CONFLICT; |
2501 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2457 | goto out_put_pr_reg; |
2502 | return -EINVAL; | ||
2503 | } | 2458 | } |
2504 | /* | 2459 | /* |
2505 | * From spc4r17 Section 5.7.9: Reserving: | 2460 | * From spc4r17 Section 5.7.9: Reserving: |
@@ -2512,8 +2467,8 @@ static int core_scsi3_pro_reserve( | |||
2512 | * shall completethe command with GOOD status. | 2467 | * shall completethe command with GOOD status. |
2513 | */ | 2468 | */ |
2514 | spin_unlock(&dev->dev_reservation_lock); | 2469 | spin_unlock(&dev->dev_reservation_lock); |
2515 | core_scsi3_put_pr_reg(pr_reg); | 2470 | ret = 0; |
2516 | return 0; | 2471 | goto out_put_pr_reg; |
2517 | } | 2472 | } |
2518 | /* | 2473 | /* |
2519 | * Otherwise, our *pr_reg becomes the PR reservation holder for said | 2474 | * Otherwise, our *pr_reg becomes the PR reservation holder for said |
@@ -2537,27 +2492,24 @@ static int core_scsi3_pro_reserve( | |||
2537 | spin_unlock(&dev->dev_reservation_lock); | 2492 | spin_unlock(&dev->dev_reservation_lock); |
2538 | 2493 | ||
2539 | if (pr_tmpl->pr_aptpl_active) { | 2494 | if (pr_tmpl->pr_aptpl_active) { |
2540 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 2495 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
2541 | &pr_reg->pr_aptpl_buf[0], | 2496 | &pr_reg->pr_aptpl_buf[0], |
2542 | pr_tmpl->pr_aptpl_buf_len); | 2497 | pr_tmpl->pr_aptpl_buf_len)) { |
2543 | if (!ret) | ||
2544 | pr_debug("SPC-3 PR: Updated APTPL metadata" | 2498 | pr_debug("SPC-3 PR: Updated APTPL metadata" |
2545 | " for RESERVE\n"); | 2499 | " for RESERVE\n"); |
2500 | } | ||
2546 | } | 2501 | } |
2547 | 2502 | ||
2503 | ret = 0; | ||
2504 | out_put_pr_reg: | ||
2548 | core_scsi3_put_pr_reg(pr_reg); | 2505 | core_scsi3_put_pr_reg(pr_reg); |
2549 | return 0; | 2506 | return ret; |
2550 | } | 2507 | } |
2551 | 2508 | ||
2552 | static int core_scsi3_emulate_pro_reserve( | 2509 | static sense_reason_t |
2553 | struct se_cmd *cmd, | 2510 | core_scsi3_emulate_pro_reserve(struct se_cmd *cmd, int type, int scope, |
2554 | int type, | 2511 | u64 res_key) |
2555 | int scope, | ||
2556 | u64 res_key) | ||
2557 | { | 2512 | { |
2558 | struct se_device *dev = cmd->se_dev; | ||
2559 | int ret = 0; | ||
2560 | |||
2561 | switch (type) { | 2513 | switch (type) { |
2562 | case PR_TYPE_WRITE_EXCLUSIVE: | 2514 | case PR_TYPE_WRITE_EXCLUSIVE: |
2563 | case PR_TYPE_EXCLUSIVE_ACCESS: | 2515 | case PR_TYPE_EXCLUSIVE_ACCESS: |
@@ -2565,16 +2517,12 @@ static int core_scsi3_emulate_pro_reserve( | |||
2565 | case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: | 2517 | case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: |
2566 | case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: | 2518 | case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: |
2567 | case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: | 2519 | case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: |
2568 | ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key); | 2520 | return core_scsi3_pro_reserve(cmd, type, scope, res_key); |
2569 | break; | ||
2570 | default: | 2521 | default: |
2571 | pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" | 2522 | pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" |
2572 | " 0x%02x\n", type); | 2523 | " 0x%02x\n", type); |
2573 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 2524 | return TCM_INVALID_CDB_FIELD; |
2574 | return -EINVAL; | ||
2575 | } | 2525 | } |
2576 | |||
2577 | return ret; | ||
2578 | } | 2526 | } |
2579 | 2527 | ||
2580 | /* | 2528 | /* |
@@ -2612,23 +2560,21 @@ static void __core_scsi3_complete_pro_release( | |||
2612 | pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0; | 2560 | pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0; |
2613 | } | 2561 | } |
2614 | 2562 | ||
2615 | static int core_scsi3_emulate_pro_release( | 2563 | static sense_reason_t |
2616 | struct se_cmd *cmd, | 2564 | core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, |
2617 | int type, | 2565 | u64 res_key) |
2618 | int scope, | ||
2619 | u64 res_key) | ||
2620 | { | 2566 | { |
2621 | struct se_device *dev = cmd->se_dev; | 2567 | struct se_device *dev = cmd->se_dev; |
2622 | struct se_session *se_sess = cmd->se_sess; | 2568 | struct se_session *se_sess = cmd->se_sess; |
2623 | struct se_lun *se_lun = cmd->se_lun; | 2569 | struct se_lun *se_lun = cmd->se_lun; |
2624 | struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; | 2570 | struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; |
2625 | struct t10_reservation *pr_tmpl = &dev->t10_pr; | 2571 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
2626 | int ret, all_reg = 0; | 2572 | int all_reg = 0; |
2573 | sense_reason_t ret = 0; | ||
2627 | 2574 | ||
2628 | if (!se_sess || !se_lun) { | 2575 | if (!se_sess || !se_lun) { |
2629 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); | 2576 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); |
2630 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2577 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
2631 | return -EINVAL; | ||
2632 | } | 2578 | } |
2633 | /* | 2579 | /* |
2634 | * Locate the existing *pr_reg via struct se_node_acl pointers | 2580 | * Locate the existing *pr_reg via struct se_node_acl pointers |
@@ -2637,8 +2583,7 @@ static int core_scsi3_emulate_pro_release( | |||
2637 | if (!pr_reg) { | 2583 | if (!pr_reg) { |
2638 | pr_err("SPC-3 PR: Unable to locate" | 2584 | pr_err("SPC-3 PR: Unable to locate" |
2639 | " PR_REGISTERED *pr_reg for RELEASE\n"); | 2585 | " PR_REGISTERED *pr_reg for RELEASE\n"); |
2640 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2586 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
2641 | return -EINVAL; | ||
2642 | } | 2587 | } |
2643 | /* | 2588 | /* |
2644 | * From spc4r17 Section 5.7.11.2 Releasing: | 2589 | * From spc4r17 Section 5.7.11.2 Releasing: |
@@ -2659,7 +2604,6 @@ static int core_scsi3_emulate_pro_release( | |||
2659 | * No persistent reservation, return GOOD status. | 2604 | * No persistent reservation, return GOOD status. |
2660 | */ | 2605 | */ |
2661 | spin_unlock(&dev->dev_reservation_lock); | 2606 | spin_unlock(&dev->dev_reservation_lock); |
2662 | core_scsi3_put_pr_reg(pr_reg); | ||
2663 | return 0; | 2607 | return 0; |
2664 | } | 2608 | } |
2665 | if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || | 2609 | if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || |
@@ -2673,9 +2617,9 @@ static int core_scsi3_emulate_pro_release( | |||
2673 | * persistent reservation holder. return GOOD status. | 2617 | * persistent reservation holder. return GOOD status. |
2674 | */ | 2618 | */ |
2675 | spin_unlock(&dev->dev_reservation_lock); | 2619 | spin_unlock(&dev->dev_reservation_lock); |
2676 | core_scsi3_put_pr_reg(pr_reg); | 2620 | goto out_put_pr_reg; |
2677 | return 0; | ||
2678 | } | 2621 | } |
2622 | |||
2679 | /* | 2623 | /* |
2680 | * From spc4r17 Section 5.7.11.2 Releasing: | 2624 | * From spc4r17 Section 5.7.11.2 Releasing: |
2681 | * | 2625 | * |
@@ -2695,9 +2639,8 @@ static int core_scsi3_emulate_pro_release( | |||
2695 | " does not match existing SA REGISTER res_key:" | 2639 | " does not match existing SA REGISTER res_key:" |
2696 | " 0x%016Lx\n", res_key, pr_reg->pr_res_key); | 2640 | " 0x%016Lx\n", res_key, pr_reg->pr_res_key); |
2697 | spin_unlock(&dev->dev_reservation_lock); | 2641 | spin_unlock(&dev->dev_reservation_lock); |
2698 | core_scsi3_put_pr_reg(pr_reg); | 2642 | ret = TCM_RESERVATION_CONFLICT; |
2699 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2643 | goto out_put_pr_reg; |
2700 | return -EINVAL; | ||
2701 | } | 2644 | } |
2702 | /* | 2645 | /* |
2703 | * From spc4r17 Section 5.7.11.2 Releasing and above: | 2646 | * From spc4r17 Section 5.7.11.2 Releasing and above: |
@@ -2718,9 +2661,8 @@ static int core_scsi3_emulate_pro_release( | |||
2718 | pr_res_holder->pr_reg_nacl->initiatorname); | 2661 | pr_res_holder->pr_reg_nacl->initiatorname); |
2719 | 2662 | ||
2720 | spin_unlock(&dev->dev_reservation_lock); | 2663 | spin_unlock(&dev->dev_reservation_lock); |
2721 | core_scsi3_put_pr_reg(pr_reg); | 2664 | ret = TCM_RESERVATION_CONFLICT; |
2722 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2665 | goto out_put_pr_reg; |
2723 | return -EINVAL; | ||
2724 | } | 2666 | } |
2725 | /* | 2667 | /* |
2726 | * In response to a persistent reservation release request from the | 2668 | * In response to a persistent reservation release request from the |
@@ -2773,20 +2715,18 @@ static int core_scsi3_emulate_pro_release( | |||
2773 | 2715 | ||
2774 | write_aptpl: | 2716 | write_aptpl: |
2775 | if (pr_tmpl->pr_aptpl_active) { | 2717 | if (pr_tmpl->pr_aptpl_active) { |
2776 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 2718 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
2777 | &pr_reg->pr_aptpl_buf[0], | 2719 | &pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) { |
2778 | pr_tmpl->pr_aptpl_buf_len); | ||
2779 | if (!ret) | ||
2780 | pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); | 2720 | pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); |
2721 | } | ||
2781 | } | 2722 | } |
2782 | 2723 | out_put_pr_reg: | |
2783 | core_scsi3_put_pr_reg(pr_reg); | 2724 | core_scsi3_put_pr_reg(pr_reg); |
2784 | return 0; | 2725 | return ret; |
2785 | } | 2726 | } |
2786 | 2727 | ||
2787 | static int core_scsi3_emulate_pro_clear( | 2728 | static sense_reason_t |
2788 | struct se_cmd *cmd, | 2729 | core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) |
2789 | u64 res_key) | ||
2790 | { | 2730 | { |
2791 | struct se_device *dev = cmd->se_dev; | 2731 | struct se_device *dev = cmd->se_dev; |
2792 | struct se_node_acl *pr_reg_nacl; | 2732 | struct se_node_acl *pr_reg_nacl; |
@@ -2803,8 +2743,7 @@ static int core_scsi3_emulate_pro_clear( | |||
2803 | if (!pr_reg_n) { | 2743 | if (!pr_reg_n) { |
2804 | pr_err("SPC-3 PR: Unable to locate" | 2744 | pr_err("SPC-3 PR: Unable to locate" |
2805 | " PR_REGISTERED *pr_reg for CLEAR\n"); | 2745 | " PR_REGISTERED *pr_reg for CLEAR\n"); |
2806 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2746 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
2807 | return -EINVAL; | ||
2808 | } | 2747 | } |
2809 | /* | 2748 | /* |
2810 | * From spc4r17 section 5.7.11.6, Clearing: | 2749 | * From spc4r17 section 5.7.11.6, Clearing: |
@@ -2823,8 +2762,7 @@ static int core_scsi3_emulate_pro_clear( | |||
2823 | " existing SA REGISTER res_key:" | 2762 | " existing SA REGISTER res_key:" |
2824 | " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); | 2763 | " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); |
2825 | core_scsi3_put_pr_reg(pr_reg_n); | 2764 | core_scsi3_put_pr_reg(pr_reg_n); |
2826 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2765 | return TCM_RESERVATION_CONFLICT; |
2827 | return -EINVAL; | ||
2828 | } | 2766 | } |
2829 | /* | 2767 | /* |
2830 | * a) Release the persistent reservation, if any; | 2768 | * a) Release the persistent reservation, if any; |
@@ -2948,13 +2886,9 @@ static void core_scsi3_release_preempt_and_abort( | |||
2948 | } | 2886 | } |
2949 | } | 2887 | } |
2950 | 2888 | ||
2951 | static int core_scsi3_pro_preempt( | 2889 | static sense_reason_t |
2952 | struct se_cmd *cmd, | 2890 | core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, |
2953 | int type, | 2891 | u64 sa_res_key, int abort) |
2954 | int scope, | ||
2955 | u64 res_key, | ||
2956 | u64 sa_res_key, | ||
2957 | int abort) | ||
2958 | { | 2892 | { |
2959 | struct se_device *dev = cmd->se_dev; | 2893 | struct se_device *dev = cmd->se_dev; |
2960 | struct se_node_acl *pr_reg_nacl; | 2894 | struct se_node_acl *pr_reg_nacl; |
@@ -2964,12 +2898,10 @@ static int core_scsi3_pro_preempt( | |||
2964 | struct t10_reservation *pr_tmpl = &dev->t10_pr; | 2898 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
2965 | u32 pr_res_mapped_lun = 0; | 2899 | u32 pr_res_mapped_lun = 0; |
2966 | int all_reg = 0, calling_it_nexus = 0, released_regs = 0; | 2900 | int all_reg = 0, calling_it_nexus = 0, released_regs = 0; |
2967 | int prh_type = 0, prh_scope = 0, ret; | 2901 | int prh_type = 0, prh_scope = 0; |
2968 | 2902 | ||
2969 | if (!se_sess) { | 2903 | if (!se_sess) |
2970 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 2904 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
2971 | return -EINVAL; | ||
2972 | } | ||
2973 | 2905 | ||
2974 | pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, | 2906 | pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, |
2975 | se_sess); | 2907 | se_sess); |
@@ -2977,19 +2909,16 @@ static int core_scsi3_pro_preempt( | |||
2977 | pr_err("SPC-3 PR: Unable to locate" | 2909 | pr_err("SPC-3 PR: Unable to locate" |
2978 | " PR_REGISTERED *pr_reg for PREEMPT%s\n", | 2910 | " PR_REGISTERED *pr_reg for PREEMPT%s\n", |
2979 | (abort) ? "_AND_ABORT" : ""); | 2911 | (abort) ? "_AND_ABORT" : ""); |
2980 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2912 | return TCM_RESERVATION_CONFLICT; |
2981 | return -EINVAL; | ||
2982 | } | 2913 | } |
2983 | if (pr_reg_n->pr_res_key != res_key) { | 2914 | if (pr_reg_n->pr_res_key != res_key) { |
2984 | core_scsi3_put_pr_reg(pr_reg_n); | 2915 | core_scsi3_put_pr_reg(pr_reg_n); |
2985 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 2916 | return TCM_RESERVATION_CONFLICT; |
2986 | return -EINVAL; | ||
2987 | } | 2917 | } |
2988 | if (scope != PR_SCOPE_LU_SCOPE) { | 2918 | if (scope != PR_SCOPE_LU_SCOPE) { |
2989 | pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); | 2919 | pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); |
2990 | core_scsi3_put_pr_reg(pr_reg_n); | 2920 | core_scsi3_put_pr_reg(pr_reg_n); |
2991 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2921 | return TCM_INVALID_PARAMETER_LIST; |
2992 | return -EINVAL; | ||
2993 | } | 2922 | } |
2994 | 2923 | ||
2995 | spin_lock(&dev->dev_reservation_lock); | 2924 | spin_lock(&dev->dev_reservation_lock); |
@@ -3002,8 +2931,7 @@ static int core_scsi3_pro_preempt( | |||
3002 | if (!all_reg && !sa_res_key) { | 2931 | if (!all_reg && !sa_res_key) { |
3003 | spin_unlock(&dev->dev_reservation_lock); | 2932 | spin_unlock(&dev->dev_reservation_lock); |
3004 | core_scsi3_put_pr_reg(pr_reg_n); | 2933 | core_scsi3_put_pr_reg(pr_reg_n); |
3005 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 2934 | return TCM_INVALID_PARAMETER_LIST; |
3006 | return -EINVAL; | ||
3007 | } | 2935 | } |
3008 | /* | 2936 | /* |
3009 | * From spc4r17, section 5.7.11.4.4 Removing Registrations: | 2937 | * From spc4r17, section 5.7.11.4.4 Removing Registrations: |
@@ -3097,8 +3025,7 @@ static int core_scsi3_pro_preempt( | |||
3097 | if (!released_regs) { | 3025 | if (!released_regs) { |
3098 | spin_unlock(&dev->dev_reservation_lock); | 3026 | spin_unlock(&dev->dev_reservation_lock); |
3099 | core_scsi3_put_pr_reg(pr_reg_n); | 3027 | core_scsi3_put_pr_reg(pr_reg_n); |
3100 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3028 | return TCM_RESERVATION_CONFLICT; |
3101 | return -EINVAL; | ||
3102 | } | 3029 | } |
3103 | /* | 3030 | /* |
3104 | * For an existing all registrants type reservation | 3031 | * For an existing all registrants type reservation |
@@ -3117,13 +3044,13 @@ static int core_scsi3_pro_preempt( | |||
3117 | spin_unlock(&dev->dev_reservation_lock); | 3044 | spin_unlock(&dev->dev_reservation_lock); |
3118 | 3045 | ||
3119 | if (pr_tmpl->pr_aptpl_active) { | 3046 | if (pr_tmpl->pr_aptpl_active) { |
3120 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 3047 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
3121 | &pr_reg_n->pr_aptpl_buf[0], | 3048 | &pr_reg_n->pr_aptpl_buf[0], |
3122 | pr_tmpl->pr_aptpl_buf_len); | 3049 | pr_tmpl->pr_aptpl_buf_len)) { |
3123 | if (!ret) | ||
3124 | pr_debug("SPC-3 PR: Updated APTPL" | 3050 | pr_debug("SPC-3 PR: Updated APTPL" |
3125 | " metadata for PREEMPT%s\n", (abort) ? | 3051 | " metadata for PREEMPT%s\n", (abort) ? |
3126 | "_AND_ABORT" : ""); | 3052 | "_AND_ABORT" : ""); |
3053 | } | ||
3127 | } | 3054 | } |
3128 | 3055 | ||
3129 | core_scsi3_put_pr_reg(pr_reg_n); | 3056 | core_scsi3_put_pr_reg(pr_reg_n); |
@@ -3253,12 +3180,12 @@ static int core_scsi3_pro_preempt( | |||
3253 | } | 3180 | } |
3254 | 3181 | ||
3255 | if (pr_tmpl->pr_aptpl_active) { | 3182 | if (pr_tmpl->pr_aptpl_active) { |
3256 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 3183 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
3257 | &pr_reg_n->pr_aptpl_buf[0], | 3184 | &pr_reg_n->pr_aptpl_buf[0], |
3258 | pr_tmpl->pr_aptpl_buf_len); | 3185 | pr_tmpl->pr_aptpl_buf_len)) { |
3259 | if (!ret) | ||
3260 | pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" | 3186 | pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" |
3261 | "%s\n", (abort) ? "_AND_ABORT" : ""); | 3187 | "%s\n", abort ? "_AND_ABORT" : ""); |
3188 | } | ||
3262 | } | 3189 | } |
3263 | 3190 | ||
3264 | core_scsi3_put_pr_reg(pr_reg_n); | 3191 | core_scsi3_put_pr_reg(pr_reg_n); |
@@ -3266,16 +3193,10 @@ static int core_scsi3_pro_preempt( | |||
3266 | return 0; | 3193 | return 0; |
3267 | } | 3194 | } |
3268 | 3195 | ||
3269 | static int core_scsi3_emulate_pro_preempt( | 3196 | static sense_reason_t |
3270 | struct se_cmd *cmd, | 3197 | core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope, |
3271 | int type, | 3198 | u64 res_key, u64 sa_res_key, int abort) |
3272 | int scope, | ||
3273 | u64 res_key, | ||
3274 | u64 sa_res_key, | ||
3275 | int abort) | ||
3276 | { | 3199 | { |
3277 | int ret = 0; | ||
3278 | |||
3279 | switch (type) { | 3200 | switch (type) { |
3280 | case PR_TYPE_WRITE_EXCLUSIVE: | 3201 | case PR_TYPE_WRITE_EXCLUSIVE: |
3281 | case PR_TYPE_EXCLUSIVE_ACCESS: | 3202 | case PR_TYPE_EXCLUSIVE_ACCESS: |
@@ -3283,26 +3204,19 @@ static int core_scsi3_emulate_pro_preempt( | |||
3283 | case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: | 3204 | case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: |
3284 | case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: | 3205 | case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: |
3285 | case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: | 3206 | case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: |
3286 | ret = core_scsi3_pro_preempt(cmd, type, scope, | 3207 | return core_scsi3_pro_preempt(cmd, type, scope, res_key, |
3287 | res_key, sa_res_key, abort); | 3208 | sa_res_key, abort); |
3288 | break; | ||
3289 | default: | 3209 | default: |
3290 | pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" | 3210 | pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" |
3291 | " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); | 3211 | " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); |
3292 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3212 | return TCM_INVALID_CDB_FIELD; |
3293 | return -EINVAL; | ||
3294 | } | 3213 | } |
3295 | |||
3296 | return ret; | ||
3297 | } | 3214 | } |
3298 | 3215 | ||
3299 | 3216 | ||
3300 | static int core_scsi3_emulate_pro_register_and_move( | 3217 | static sense_reason_t |
3301 | struct se_cmd *cmd, | 3218 | core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, |
3302 | u64 res_key, | 3219 | u64 sa_res_key, int aptpl, int unreg) |
3303 | u64 sa_res_key, | ||
3304 | int aptpl, | ||
3305 | int unreg) | ||
3306 | { | 3220 | { |
3307 | struct se_session *se_sess = cmd->se_sess; | 3221 | struct se_session *se_sess = cmd->se_sess; |
3308 | struct se_device *dev = cmd->se_dev; | 3222 | struct se_device *dev = cmd->se_dev; |
@@ -3318,15 +3232,16 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3318 | unsigned char *initiator_str; | 3232 | unsigned char *initiator_str; |
3319 | char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; | 3233 | char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; |
3320 | u32 tid_len, tmp_tid_len; | 3234 | u32 tid_len, tmp_tid_len; |
3321 | int new_reg = 0, type, scope, ret, matching_iname, prf_isid; | 3235 | int new_reg = 0, type, scope, matching_iname, prf_isid; |
3236 | sense_reason_t ret; | ||
3322 | unsigned short rtpi; | 3237 | unsigned short rtpi; |
3323 | unsigned char proto_ident; | 3238 | unsigned char proto_ident; |
3324 | 3239 | ||
3325 | if (!se_sess || !se_lun) { | 3240 | if (!se_sess || !se_lun) { |
3326 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); | 3241 | pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); |
3327 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3242 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
3328 | return -EINVAL; | ||
3329 | } | 3243 | } |
3244 | |||
3330 | memset(dest_iport, 0, 64); | 3245 | memset(dest_iport, 0, 64); |
3331 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); | 3246 | memset(i_buf, 0, PR_REG_ISID_ID_LEN); |
3332 | se_tpg = se_sess->se_tpg; | 3247 | se_tpg = se_sess->se_tpg; |
@@ -3342,8 +3257,7 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3342 | if (!pr_reg) { | 3257 | if (!pr_reg) { |
3343 | pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" | 3258 | pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" |
3344 | " *pr_reg for REGISTER_AND_MOVE\n"); | 3259 | " *pr_reg for REGISTER_AND_MOVE\n"); |
3345 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3260 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
3346 | return -EINVAL; | ||
3347 | } | 3261 | } |
3348 | /* | 3262 | /* |
3349 | * The provided reservation key much match the existing reservation key | 3263 | * The provided reservation key much match the existing reservation key |
@@ -3353,9 +3267,8 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3353 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received" | 3267 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received" |
3354 | " res_key: 0x%016Lx does not match existing SA REGISTER" | 3268 | " res_key: 0x%016Lx does not match existing SA REGISTER" |
3355 | " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); | 3269 | " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); |
3356 | core_scsi3_put_pr_reg(pr_reg); | 3270 | ret = TCM_RESERVATION_CONFLICT; |
3357 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3271 | goto out_put_pr_reg; |
3358 | return -EINVAL; | ||
3359 | } | 3272 | } |
3360 | /* | 3273 | /* |
3361 | * The service active reservation key needs to be non zero | 3274 | * The service active reservation key needs to be non zero |
@@ -3363,9 +3276,8 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3363 | if (!sa_res_key) { | 3276 | if (!sa_res_key) { |
3364 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" | 3277 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" |
3365 | " sa_res_key\n"); | 3278 | " sa_res_key\n"); |
3366 | core_scsi3_put_pr_reg(pr_reg); | 3279 | ret = TCM_INVALID_PARAMETER_LIST; |
3367 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3280 | goto out_put_pr_reg; |
3368 | return -EINVAL; | ||
3369 | } | 3281 | } |
3370 | 3282 | ||
3371 | /* | 3283 | /* |
@@ -3374,6 +3286,11 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3374 | * information. | 3286 | * information. |
3375 | */ | 3287 | */ |
3376 | buf = transport_kmap_data_sg(cmd); | 3288 | buf = transport_kmap_data_sg(cmd); |
3289 | if (!buf) { | ||
3290 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
3291 | goto out_put_pr_reg; | ||
3292 | } | ||
3293 | |||
3377 | rtpi = (buf[18] & 0xff) << 8; | 3294 | rtpi = (buf[18] & 0xff) << 8; |
3378 | rtpi |= buf[19] & 0xff; | 3295 | rtpi |= buf[19] & 0xff; |
3379 | tid_len = (buf[20] & 0xff) << 24; | 3296 | tid_len = (buf[20] & 0xff) << 24; |
@@ -3387,9 +3304,8 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3387 | pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header" | 3304 | pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header" |
3388 | " does not equal CDB data_length: %u\n", tid_len, | 3305 | " does not equal CDB data_length: %u\n", tid_len, |
3389 | cmd->data_length); | 3306 | cmd->data_length); |
3390 | core_scsi3_put_pr_reg(pr_reg); | 3307 | ret = TCM_INVALID_PARAMETER_LIST; |
3391 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3308 | goto out_put_pr_reg; |
3392 | return -EINVAL; | ||
3393 | } | 3309 | } |
3394 | 3310 | ||
3395 | spin_lock(&dev->se_port_lock); | 3311 | spin_lock(&dev->se_port_lock); |
@@ -3407,15 +3323,13 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3407 | smp_mb__after_atomic_inc(); | 3323 | smp_mb__after_atomic_inc(); |
3408 | spin_unlock(&dev->se_port_lock); | 3324 | spin_unlock(&dev->se_port_lock); |
3409 | 3325 | ||
3410 | ret = core_scsi3_tpg_depend_item(dest_se_tpg); | 3326 | if (core_scsi3_tpg_depend_item(dest_se_tpg)) { |
3411 | if (ret != 0) { | ||
3412 | pr_err("core_scsi3_tpg_depend_item() failed" | 3327 | pr_err("core_scsi3_tpg_depend_item() failed" |
3413 | " for dest_se_tpg\n"); | 3328 | " for dest_se_tpg\n"); |
3414 | atomic_dec(&dest_se_tpg->tpg_pr_ref_count); | 3329 | atomic_dec(&dest_se_tpg->tpg_pr_ref_count); |
3415 | smp_mb__after_atomic_dec(); | 3330 | smp_mb__after_atomic_dec(); |
3416 | core_scsi3_put_pr_reg(pr_reg); | 3331 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
3417 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3332 | goto out_put_pr_reg; |
3418 | return -EINVAL; | ||
3419 | } | 3333 | } |
3420 | 3334 | ||
3421 | spin_lock(&dev->se_port_lock); | 3335 | spin_lock(&dev->se_port_lock); |
@@ -3427,12 +3341,15 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3427 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" | 3341 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" |
3428 | " fabric ops from Relative Target Port Identifier:" | 3342 | " fabric ops from Relative Target Port Identifier:" |
3429 | " %hu\n", rtpi); | 3343 | " %hu\n", rtpi); |
3430 | core_scsi3_put_pr_reg(pr_reg); | 3344 | ret = TCM_INVALID_PARAMETER_LIST; |
3431 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3345 | goto out_put_pr_reg; |
3432 | return -EINVAL; | ||
3433 | } | 3346 | } |
3434 | 3347 | ||
3435 | buf = transport_kmap_data_sg(cmd); | 3348 | buf = transport_kmap_data_sg(cmd); |
3349 | if (!buf) { | ||
3350 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
3351 | goto out_put_pr_reg; | ||
3352 | } | ||
3436 | proto_ident = (buf[24] & 0x0f); | 3353 | proto_ident = (buf[24] & 0x0f); |
3437 | 3354 | ||
3438 | pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" | 3355 | pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" |
@@ -3444,16 +3361,14 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3444 | " from fabric: %s\n", proto_ident, | 3361 | " from fabric: %s\n", proto_ident, |
3445 | dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), | 3362 | dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), |
3446 | dest_tf_ops->get_fabric_name()); | 3363 | dest_tf_ops->get_fabric_name()); |
3447 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3364 | ret = TCM_INVALID_PARAMETER_LIST; |
3448 | ret = -EINVAL; | ||
3449 | goto out; | 3365 | goto out; |
3450 | } | 3366 | } |
3451 | if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { | 3367 | if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { |
3452 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" | 3368 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" |
3453 | " containg a valid tpg_parse_pr_out_transport_id" | 3369 | " containg a valid tpg_parse_pr_out_transport_id" |
3454 | " function pointer\n"); | 3370 | " function pointer\n"); |
3455 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3371 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
3456 | ret = -EINVAL; | ||
3457 | goto out; | 3372 | goto out; |
3458 | } | 3373 | } |
3459 | initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, | 3374 | initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, |
@@ -3461,8 +3376,7 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3461 | if (!initiator_str) { | 3376 | if (!initiator_str) { |
3462 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" | 3377 | pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" |
3463 | " initiator_str from Transport ID\n"); | 3378 | " initiator_str from Transport ID\n"); |
3464 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3379 | ret = TCM_INVALID_PARAMETER_LIST; |
3465 | ret = -EINVAL; | ||
3466 | goto out; | 3380 | goto out; |
3467 | } | 3381 | } |
3468 | 3382 | ||
@@ -3491,8 +3405,7 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3491 | pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" | 3405 | pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" |
3492 | " matches: %s on received I_T Nexus\n", initiator_str, | 3406 | " matches: %s on received I_T Nexus\n", initiator_str, |
3493 | pr_reg_nacl->initiatorname); | 3407 | pr_reg_nacl->initiatorname); |
3494 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3408 | ret = TCM_INVALID_PARAMETER_LIST; |
3495 | ret = -EINVAL; | ||
3496 | goto out; | 3409 | goto out; |
3497 | } | 3410 | } |
3498 | if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { | 3411 | if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { |
@@ -3500,8 +3413,7 @@ static int core_scsi3_emulate_pro_register_and_move( | |||
3500 | " matches: %s %s on received I_T Nexus\n", | 3413 | " matches: %s %s on received I_T Nexus\n", |
3501 | initiator_str, iport_ptr, pr_reg_nacl->initiatorname, | 3414 | initiator_str, iport_ptr, pr_reg_nacl->initiatorname, |
3502 | pr_reg->pr_reg_isid); | 3415 | pr_reg->pr_reg_isid); |
3503 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3416 | ret = TCM_INVALID_PARAMETER_LIST; |
3504 | ret = -EINVAL; | ||
3505 | goto out; | 3417 | goto out; |
3506 | } | 3418 | } |
3507 | after_iport_check: | 3419 | after_iport_check: |
@@ -3521,19 +3433,17 @@ after_iport_check: | |||
3521 | pr_err("Unable to locate %s dest_node_acl for" | 3433 | pr_err("Unable to locate %s dest_node_acl for" |
3522 | " TransportID%s\n", dest_tf_ops->get_fabric_name(), | 3434 | " TransportID%s\n", dest_tf_ops->get_fabric_name(), |
3523 | initiator_str); | 3435 | initiator_str); |
3524 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3436 | ret = TCM_INVALID_PARAMETER_LIST; |
3525 | ret = -EINVAL; | ||
3526 | goto out; | 3437 | goto out; |
3527 | } | 3438 | } |
3528 | ret = core_scsi3_nodeacl_depend_item(dest_node_acl); | 3439 | |
3529 | if (ret != 0) { | 3440 | if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { |
3530 | pr_err("core_scsi3_nodeacl_depend_item() for" | 3441 | pr_err("core_scsi3_nodeacl_depend_item() for" |
3531 | " dest_node_acl\n"); | 3442 | " dest_node_acl\n"); |
3532 | atomic_dec(&dest_node_acl->acl_pr_ref_count); | 3443 | atomic_dec(&dest_node_acl->acl_pr_ref_count); |
3533 | smp_mb__after_atomic_dec(); | 3444 | smp_mb__after_atomic_dec(); |
3534 | dest_node_acl = NULL; | 3445 | dest_node_acl = NULL; |
3535 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3446 | ret = TCM_INVALID_PARAMETER_LIST; |
3536 | ret = -EINVAL; | ||
3537 | goto out; | 3447 | goto out; |
3538 | } | 3448 | } |
3539 | 3449 | ||
@@ -3549,19 +3459,16 @@ after_iport_check: | |||
3549 | if (!dest_se_deve) { | 3459 | if (!dest_se_deve) { |
3550 | pr_err("Unable to locate %s dest_se_deve from RTPI:" | 3460 | pr_err("Unable to locate %s dest_se_deve from RTPI:" |
3551 | " %hu\n", dest_tf_ops->get_fabric_name(), rtpi); | 3461 | " %hu\n", dest_tf_ops->get_fabric_name(), rtpi); |
3552 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3462 | ret = TCM_INVALID_PARAMETER_LIST; |
3553 | ret = -EINVAL; | ||
3554 | goto out; | 3463 | goto out; |
3555 | } | 3464 | } |
3556 | 3465 | ||
3557 | ret = core_scsi3_lunacl_depend_item(dest_se_deve); | 3466 | if (core_scsi3_lunacl_depend_item(dest_se_deve)) { |
3558 | if (ret < 0) { | ||
3559 | pr_err("core_scsi3_lunacl_depend_item() failed\n"); | 3467 | pr_err("core_scsi3_lunacl_depend_item() failed\n"); |
3560 | atomic_dec(&dest_se_deve->pr_ref_count); | 3468 | atomic_dec(&dest_se_deve->pr_ref_count); |
3561 | smp_mb__after_atomic_dec(); | 3469 | smp_mb__after_atomic_dec(); |
3562 | dest_se_deve = NULL; | 3470 | dest_se_deve = NULL; |
3563 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3471 | ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
3564 | ret = -EINVAL; | ||
3565 | goto out; | 3472 | goto out; |
3566 | } | 3473 | } |
3567 | 3474 | ||
@@ -3580,8 +3487,7 @@ after_iport_check: | |||
3580 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" | 3487 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" |
3581 | " currently held\n"); | 3488 | " currently held\n"); |
3582 | spin_unlock(&dev->dev_reservation_lock); | 3489 | spin_unlock(&dev->dev_reservation_lock); |
3583 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3490 | ret = TCM_INVALID_CDB_FIELD; |
3584 | ret = -EINVAL; | ||
3585 | goto out; | 3491 | goto out; |
3586 | } | 3492 | } |
3587 | /* | 3493 | /* |
@@ -3594,8 +3500,7 @@ after_iport_check: | |||
3594 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" | 3500 | pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" |
3595 | " Nexus is not reservation holder\n"); | 3501 | " Nexus is not reservation holder\n"); |
3596 | spin_unlock(&dev->dev_reservation_lock); | 3502 | spin_unlock(&dev->dev_reservation_lock); |
3597 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3503 | ret = TCM_RESERVATION_CONFLICT; |
3598 | ret = -EINVAL; | ||
3599 | goto out; | 3504 | goto out; |
3600 | } | 3505 | } |
3601 | /* | 3506 | /* |
@@ -3613,8 +3518,7 @@ after_iport_check: | |||
3613 | " reservation for type: %s\n", | 3518 | " reservation for type: %s\n", |
3614 | core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); | 3519 | core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); |
3615 | spin_unlock(&dev->dev_reservation_lock); | 3520 | spin_unlock(&dev->dev_reservation_lock); |
3616 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3521 | ret = TCM_RESERVATION_CONFLICT; |
3617 | ret = -EINVAL; | ||
3618 | goto out; | 3522 | goto out; |
3619 | } | 3523 | } |
3620 | pr_res_nacl = pr_res_holder->pr_reg_nacl; | 3524 | pr_res_nacl = pr_res_holder->pr_reg_nacl; |
@@ -3646,13 +3550,11 @@ after_iport_check: | |||
3646 | dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, | 3550 | dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, |
3647 | iport_ptr); | 3551 | iport_ptr); |
3648 | if (!dest_pr_reg) { | 3552 | if (!dest_pr_reg) { |
3649 | ret = core_scsi3_alloc_registration(cmd->se_dev, | 3553 | if (core_scsi3_alloc_registration(cmd->se_dev, |
3650 | dest_node_acl, dest_se_deve, iport_ptr, | 3554 | dest_node_acl, dest_se_deve, iport_ptr, |
3651 | sa_res_key, 0, aptpl, 2, 1); | 3555 | sa_res_key, 0, aptpl, 2, 1)) { |
3652 | if (ret != 0) { | ||
3653 | spin_unlock(&dev->dev_reservation_lock); | 3556 | spin_unlock(&dev->dev_reservation_lock); |
3654 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3557 | ret = TCM_INVALID_PARAMETER_LIST; |
3655 | ret = -EINVAL; | ||
3656 | goto out; | 3558 | goto out; |
3657 | } | 3559 | } |
3658 | dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, | 3560 | dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, |
@@ -3723,12 +3625,12 @@ after_iport_check: | |||
3723 | " REGISTER_AND_MOVE\n"); | 3625 | " REGISTER_AND_MOVE\n"); |
3724 | } else { | 3626 | } else { |
3725 | pr_tmpl->pr_aptpl_active = 1; | 3627 | pr_tmpl->pr_aptpl_active = 1; |
3726 | ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, | 3628 | if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, |
3727 | &dest_pr_reg->pr_aptpl_buf[0], | 3629 | &dest_pr_reg->pr_aptpl_buf[0], |
3728 | pr_tmpl->pr_aptpl_buf_len); | 3630 | pr_tmpl->pr_aptpl_buf_len)) { |
3729 | if (!ret) | ||
3730 | pr_debug("SPC-3 PR: Set APTPL Bit Activated for" | 3631 | pr_debug("SPC-3 PR: Set APTPL Bit Activated for" |
3731 | " REGISTER_AND_MOVE\n"); | 3632 | " REGISTER_AND_MOVE\n"); |
3633 | } | ||
3732 | } | 3634 | } |
3733 | 3635 | ||
3734 | transport_kunmap_data_sg(cmd); | 3636 | transport_kunmap_data_sg(cmd); |
@@ -3743,6 +3645,8 @@ out: | |||
3743 | if (dest_node_acl) | 3645 | if (dest_node_acl) |
3744 | core_scsi3_nodeacl_undepend_item(dest_node_acl); | 3646 | core_scsi3_nodeacl_undepend_item(dest_node_acl); |
3745 | core_scsi3_tpg_undepend_item(dest_se_tpg); | 3647 | core_scsi3_tpg_undepend_item(dest_se_tpg); |
3648 | |||
3649 | out_put_pr_reg: | ||
3746 | core_scsi3_put_pr_reg(pr_reg); | 3650 | core_scsi3_put_pr_reg(pr_reg); |
3747 | return ret; | 3651 | return ret; |
3748 | } | 3652 | } |
@@ -3760,14 +3664,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb) | |||
3760 | /* | 3664 | /* |
3761 | * See spc4r17 section 6.14 Table 170 | 3665 | * See spc4r17 section 6.14 Table 170 |
3762 | */ | 3666 | */ |
3763 | int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | 3667 | sense_reason_t |
3668 | target_scsi3_emulate_pr_out(struct se_cmd *cmd) | ||
3764 | { | 3669 | { |
3765 | unsigned char *cdb = &cmd->t_task_cdb[0]; | 3670 | unsigned char *cdb = &cmd->t_task_cdb[0]; |
3766 | unsigned char *buf; | 3671 | unsigned char *buf; |
3767 | u64 res_key, sa_res_key; | 3672 | u64 res_key, sa_res_key; |
3768 | int sa, scope, type, aptpl; | 3673 | int sa, scope, type, aptpl; |
3769 | int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; | 3674 | int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; |
3770 | int ret; | 3675 | sense_reason_t ret; |
3771 | 3676 | ||
3772 | /* | 3677 | /* |
3773 | * Following spc2r20 5.5.1 Reservations overview: | 3678 | * Following spc2r20 5.5.1 Reservations overview: |
@@ -3782,28 +3687,22 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
3782 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" | 3687 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" |
3783 | " SPC-2 reservation is held, returning" | 3688 | " SPC-2 reservation is held, returning" |
3784 | " RESERVATION_CONFLICT\n"); | 3689 | " RESERVATION_CONFLICT\n"); |
3785 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 3690 | return TCM_RESERVATION_CONFLICT; |
3786 | ret = -EINVAL; | ||
3787 | goto out; | ||
3788 | } | 3691 | } |
3789 | 3692 | ||
3790 | /* | 3693 | /* |
3791 | * FIXME: A NULL struct se_session pointer means an this is not coming from | 3694 | * FIXME: A NULL struct se_session pointer means an this is not coming from |
3792 | * a $FABRIC_MOD's nexus, but from internal passthrough ops. | 3695 | * a $FABRIC_MOD's nexus, but from internal passthrough ops. |
3793 | */ | 3696 | */ |
3794 | if (!cmd->se_sess) { | 3697 | if (!cmd->se_sess) |
3795 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3698 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
3796 | ret = -EINVAL; | ||
3797 | goto out; | ||
3798 | } | ||
3799 | 3699 | ||
3800 | if (cmd->data_length < 24) { | 3700 | if (cmd->data_length < 24) { |
3801 | pr_warn("SPC-PR: Received PR OUT parameter list" | 3701 | pr_warn("SPC-PR: Received PR OUT parameter list" |
3802 | " length too small: %u\n", cmd->data_length); | 3702 | " length too small: %u\n", cmd->data_length); |
3803 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3703 | return TCM_INVALID_PARAMETER_LIST; |
3804 | ret = -EINVAL; | ||
3805 | goto out; | ||
3806 | } | 3704 | } |
3705 | |||
3807 | /* | 3706 | /* |
3808 | * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) | 3707 | * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) |
3809 | */ | 3708 | */ |
@@ -3812,6 +3711,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
3812 | type = (cdb[2] & 0x0f); | 3711 | type = (cdb[2] & 0x0f); |
3813 | 3712 | ||
3814 | buf = transport_kmap_data_sg(cmd); | 3713 | buf = transport_kmap_data_sg(cmd); |
3714 | if (!buf) | ||
3715 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
3716 | |||
3815 | /* | 3717 | /* |
3816 | * From PERSISTENT_RESERVE_OUT parameter list (payload) | 3718 | * From PERSISTENT_RESERVE_OUT parameter list (payload) |
3817 | */ | 3719 | */ |
@@ -3835,11 +3737,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
3835 | /* | 3737 | /* |
3836 | * SPEC_I_PT=1 is only valid for Service action: REGISTER | 3738 | * SPEC_I_PT=1 is only valid for Service action: REGISTER |
3837 | */ | 3739 | */ |
3838 | if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) { | 3740 | if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) |
3839 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3741 | return TCM_INVALID_PARAMETER_LIST; |
3840 | ret = -EINVAL; | ||
3841 | goto out; | ||
3842 | } | ||
3843 | 3742 | ||
3844 | /* | 3743 | /* |
3845 | * From spc4r17 section 6.14: | 3744 | * From spc4r17 section 6.14: |
@@ -3854,10 +3753,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
3854 | (cmd->data_length != 24)) { | 3753 | (cmd->data_length != 24)) { |
3855 | pr_warn("SPC-PR: Received PR OUT illegal parameter" | 3754 | pr_warn("SPC-PR: Received PR OUT illegal parameter" |
3856 | " list length: %u\n", cmd->data_length); | 3755 | " list length: %u\n", cmd->data_length); |
3857 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 3756 | return TCM_INVALID_PARAMETER_LIST; |
3858 | ret = -EINVAL; | ||
3859 | goto out; | ||
3860 | } | 3757 | } |
3758 | |||
3861 | /* | 3759 | /* |
3862 | * (core_scsi3_emulate_pro_* function parameters | 3760 | * (core_scsi3_emulate_pro_* function parameters |
3863 | * are defined by spc4r17 Table 174: | 3761 | * are defined by spc4r17 Table 174: |
@@ -3896,12 +3794,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) | |||
3896 | default: | 3794 | default: |
3897 | pr_err("Unknown PERSISTENT_RESERVE_OUT service" | 3795 | pr_err("Unknown PERSISTENT_RESERVE_OUT service" |
3898 | " action: 0x%02x\n", cdb[1] & 0x1f); | 3796 | " action: 0x%02x\n", cdb[1] & 0x1f); |
3899 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3797 | return TCM_INVALID_CDB_FIELD; |
3900 | ret = -EINVAL; | ||
3901 | break; | ||
3902 | } | 3798 | } |
3903 | 3799 | ||
3904 | out: | ||
3905 | if (!ret) | 3800 | if (!ret) |
3906 | target_complete_cmd(cmd, GOOD); | 3801 | target_complete_cmd(cmd, GOOD); |
3907 | return ret; | 3802 | return ret; |
@@ -3912,7 +3807,8 @@ out: | |||
3912 | * | 3807 | * |
3913 | * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160 | 3808 | * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160 |
3914 | */ | 3809 | */ |
3915 | static int core_scsi3_pri_read_keys(struct se_cmd *cmd) | 3810 | static sense_reason_t |
3811 | core_scsi3_pri_read_keys(struct se_cmd *cmd) | ||
3916 | { | 3812 | { |
3917 | struct se_device *dev = cmd->se_dev; | 3813 | struct se_device *dev = cmd->se_dev; |
3918 | struct t10_pr_registration *pr_reg; | 3814 | struct t10_pr_registration *pr_reg; |
@@ -3922,11 +3818,13 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) | |||
3922 | if (cmd->data_length < 8) { | 3818 | if (cmd->data_length < 8) { |
3923 | pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" | 3819 | pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" |
3924 | " too small\n", cmd->data_length); | 3820 | " too small\n", cmd->data_length); |
3925 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3821 | return TCM_INVALID_CDB_FIELD; |
3926 | return -EINVAL; | ||
3927 | } | 3822 | } |
3928 | 3823 | ||
3929 | buf = transport_kmap_data_sg(cmd); | 3824 | buf = transport_kmap_data_sg(cmd); |
3825 | if (!buf) | ||
3826 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
3827 | |||
3930 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); | 3828 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); |
3931 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); | 3829 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); |
3932 | buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); | 3830 | buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); |
@@ -3970,7 +3868,8 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) | |||
3970 | * | 3868 | * |
3971 | * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162 | 3869 | * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162 |
3972 | */ | 3870 | */ |
3973 | static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) | 3871 | static sense_reason_t |
3872 | core_scsi3_pri_read_reservation(struct se_cmd *cmd) | ||
3974 | { | 3873 | { |
3975 | struct se_device *dev = cmd->se_dev; | 3874 | struct se_device *dev = cmd->se_dev; |
3976 | struct t10_pr_registration *pr_reg; | 3875 | struct t10_pr_registration *pr_reg; |
@@ -3981,11 +3880,13 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) | |||
3981 | if (cmd->data_length < 8) { | 3880 | if (cmd->data_length < 8) { |
3982 | pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" | 3881 | pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" |
3983 | " too small\n", cmd->data_length); | 3882 | " too small\n", cmd->data_length); |
3984 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3883 | return TCM_INVALID_CDB_FIELD; |
3985 | return -EINVAL; | ||
3986 | } | 3884 | } |
3987 | 3885 | ||
3988 | buf = transport_kmap_data_sg(cmd); | 3886 | buf = transport_kmap_data_sg(cmd); |
3887 | if (!buf) | ||
3888 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
3889 | |||
3989 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); | 3890 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); |
3990 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); | 3891 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); |
3991 | buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); | 3892 | buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); |
@@ -4054,7 +3955,8 @@ err: | |||
4054 | * | 3955 | * |
4055 | * See spc4r17 section 6.13.4 Table 165 | 3956 | * See spc4r17 section 6.13.4 Table 165 |
4056 | */ | 3957 | */ |
4057 | static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) | 3958 | static sense_reason_t |
3959 | core_scsi3_pri_report_capabilities(struct se_cmd *cmd) | ||
4058 | { | 3960 | { |
4059 | struct se_device *dev = cmd->se_dev; | 3961 | struct se_device *dev = cmd->se_dev; |
4060 | struct t10_reservation *pr_tmpl = &dev->t10_pr; | 3962 | struct t10_reservation *pr_tmpl = &dev->t10_pr; |
@@ -4064,11 +3966,12 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) | |||
4064 | if (cmd->data_length < 6) { | 3966 | if (cmd->data_length < 6) { |
4065 | pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" | 3967 | pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" |
4066 | " %u too small\n", cmd->data_length); | 3968 | " %u too small\n", cmd->data_length); |
4067 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 3969 | return TCM_INVALID_CDB_FIELD; |
4068 | return -EINVAL; | ||
4069 | } | 3970 | } |
4070 | 3971 | ||
4071 | buf = transport_kmap_data_sg(cmd); | 3972 | buf = transport_kmap_data_sg(cmd); |
3973 | if (!buf) | ||
3974 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
4072 | 3975 | ||
4073 | buf[0] = ((add_len << 8) & 0xff); | 3976 | buf[0] = ((add_len << 8) & 0xff); |
4074 | buf[1] = (add_len & 0xff); | 3977 | buf[1] = (add_len & 0xff); |
@@ -4110,7 +4013,8 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) | |||
4110 | * | 4013 | * |
4111 | * See spc4r17 section 6.13.5 Table 168 and 169 | 4014 | * See spc4r17 section 6.13.5 Table 168 and 169 |
4112 | */ | 4015 | */ |
4113 | static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) | 4016 | static sense_reason_t |
4017 | core_scsi3_pri_read_full_status(struct se_cmd *cmd) | ||
4114 | { | 4018 | { |
4115 | struct se_device *dev = cmd->se_dev; | 4019 | struct se_device *dev = cmd->se_dev; |
4116 | struct se_node_acl *se_nacl; | 4020 | struct se_node_acl *se_nacl; |
@@ -4125,11 +4029,12 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) | |||
4125 | if (cmd->data_length < 8) { | 4029 | if (cmd->data_length < 8) { |
4126 | pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" | 4030 | pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" |
4127 | " too small\n", cmd->data_length); | 4031 | " too small\n", cmd->data_length); |
4128 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 4032 | return TCM_INVALID_CDB_FIELD; |
4129 | return -EINVAL; | ||
4130 | } | 4033 | } |
4131 | 4034 | ||
4132 | buf = transport_kmap_data_sg(cmd); | 4035 | buf = transport_kmap_data_sg(cmd); |
4036 | if (!buf) | ||
4037 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
4133 | 4038 | ||
4134 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); | 4039 | buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); |
4135 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); | 4040 | buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); |
@@ -4255,9 +4160,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) | |||
4255 | return 0; | 4160 | return 0; |
4256 | } | 4161 | } |
4257 | 4162 | ||
4258 | int target_scsi3_emulate_pr_in(struct se_cmd *cmd) | 4163 | sense_reason_t |
4164 | target_scsi3_emulate_pr_in(struct se_cmd *cmd) | ||
4259 | { | 4165 | { |
4260 | int ret; | 4166 | sense_reason_t ret; |
4261 | 4167 | ||
4262 | /* | 4168 | /* |
4263 | * Following spc2r20 5.5.1 Reservations overview: | 4169 | * Following spc2r20 5.5.1 Reservations overview: |
@@ -4272,8 +4178,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) | |||
4272 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" | 4178 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" |
4273 | " SPC-2 reservation is held, returning" | 4179 | " SPC-2 reservation is held, returning" |
4274 | " RESERVATION_CONFLICT\n"); | 4180 | " RESERVATION_CONFLICT\n"); |
4275 | cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; | 4181 | return TCM_RESERVATION_CONFLICT; |
4276 | return -EINVAL; | ||
4277 | } | 4182 | } |
4278 | 4183 | ||
4279 | switch (cmd->t_task_cdb[1] & 0x1f) { | 4184 | switch (cmd->t_task_cdb[1] & 0x1f) { |
@@ -4292,9 +4197,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) | |||
4292 | default: | 4197 | default: |
4293 | pr_err("Unknown PERSISTENT_RESERVE_IN service" | 4198 | pr_err("Unknown PERSISTENT_RESERVE_IN service" |
4294 | " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); | 4199 | " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); |
4295 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | 4200 | return TCM_INVALID_CDB_FIELD; |
4296 | ret = -EINVAL; | ||
4297 | break; | ||
4298 | } | 4201 | } |
4299 | 4202 | ||
4300 | if (!ret) | 4203 | if (!ret) |
@@ -4302,10 +4205,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) | |||
4302 | return ret; | 4205 | return ret; |
4303 | } | 4206 | } |
4304 | 4207 | ||
4305 | int target_check_reservation(struct se_cmd *cmd) | 4208 | sense_reason_t |
4209 | target_check_reservation(struct se_cmd *cmd) | ||
4306 | { | 4210 | { |
4307 | struct se_device *dev = cmd->se_dev; | 4211 | struct se_device *dev = cmd->se_dev; |
4308 | int ret; | 4212 | sense_reason_t ret; |
4309 | 4213 | ||
4310 | if (!cmd->se_sess) | 4214 | if (!cmd->se_sess) |
4311 | return 0; | 4215 | return 0; |