diff options
Diffstat (limited to 'drivers/target/target_core_pr.c')
-rw-r--r-- | drivers/target/target_core_pr.c | 1225 |
1 files changed, 524 insertions, 701 deletions
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 8c323a98c4a..8e0290b38e4 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -4,8 +4,7 @@ * This file contains SPC-3 compliant persistent reservations and * legacy SPC-2 reservations with compatible reservation handling (CRH=1) * - * Copyright (c) 2009, 2010 Rising Tide Systems - * Copyright (c) 2009, 2010 Linux-iSCSI.org + * (c) Copyright 2009-2012 RisingTide Systems LLC. * * Nicholas A. Bellinger <nab@kernel.org> * @@ -68,49 +67,33 @@ int core_pr_dump_initiator_port( static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, struct t10_pr_registration *, int); -static int core_scsi2_reservation_seq_non_holder( - struct se_cmd *cmd, - unsigned char *cdb, - u32 pr_reg_type) +static sense_reason_t +target_scsi2_reservation_check(struct se_cmd *cmd) { - switch (cdb[0]) { + struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; + + switch (cmd->t_task_cdb[0]) { case INQUIRY: case RELEASE: case RELEASE_10: return 0; default: - return 1; + break; } - return 1; -} - -static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type) -{ - struct se_device *dev = cmd->se_dev; - struct se_session *sess = cmd->se_sess; - int ret; - - if (!sess) + if (!dev->dev_reserved_node_acl || !sess) return 0; - spin_lock(&dev->dev_reservation_lock); - if (!dev->dev_reserved_node_acl || !sess) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - if (dev->dev_reserved_node_acl != sess->se_node_acl) { - spin_unlock(&dev->dev_reservation_lock); - return -EINVAL; - } - if (!(dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID)) { - spin_unlock(&dev->dev_reservation_lock); - return 0; + if (dev->dev_reserved_node_acl != sess->se_node_acl) + return TCM_RESERVATION_CONFLICT; + + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { + if (dev->dev_res_bin_isid != sess->sess_bin_isid) + return TCM_RESERVATION_CONFLICT; } - ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -EINVAL; - spin_unlock(&dev->dev_reservation_lock); - return ret; + return 0; } static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *, @@ -120,15 +103,11 @@ static void core_scsi3_put_pr_reg(struct t10_pr_registration *); static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) { struct se_session *se_sess = cmd->se_sess; - struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; + struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; - struct t10_reservation *pr_tmpl = &su_dev->t10_pr; - int crh = (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS); + struct t10_reservation *pr_tmpl = &dev->t10_pr; int conflict = 0; - if (!crh) - return -EINVAL; - pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); if (pr_reg) { @@ -186,32 +165,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) pr_err("Received legacy SPC-2 RESERVE/RELEASE" " while active SPC-3 registrations exist," " returning RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return -EBUSY; } return 0; } -int target_scsi2_reservation_release(struct se_cmd *cmd) +sense_reason_t +target_scsi2_reservation_release(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg; - int ret = 0, rc; + int rc; if (!sess || !sess->se_tpg) goto out; rc = target_check_scsi2_reservation_conflict(cmd); if (rc == 1) goto out; - else if (rc < 0) { - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; - } + if (rc < 0) + return TCM_RESERVATION_CONFLICT; - ret = 0; spin_lock(&dev->dev_reservation_lock); if (!dev->dev_reserved_node_acl || !sess) goto out_unlock; @@ -223,10 +198,10 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) goto out_unlock; dev->dev_reserved_node_acl = NULL; - dev->dev_flags &= ~DF_SPC2_RESERVATIONS; - if (dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID) { + dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS; + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { dev->dev_res_bin_isid = 0; - dev->dev_flags &= ~DF_SPC2_RESERVATIONS_WITH_ISID; + dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID; } tpg = sess->se_tpg; pr_debug("SCSI-2 Released reservation for %s LUN: %u ->" @@ -237,25 +212,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) out_unlock: spin_unlock(&dev->dev_reservation_lock); out: - if (!ret) - target_complete_cmd(cmd, GOOD); - return ret; + target_complete_cmd(cmd, GOOD); + return 0; } -int target_scsi2_reservation_reserve(struct se_cmd *cmd) +sense_reason_t +target_scsi2_reservation_reserve(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg; - int ret = 0, rc; + sense_reason_t ret = 0; + int rc; if ((cmd->t_task_cdb[1] & 0x01) && (cmd->t_task_cdb[1] & 0x02)) { pr_err("LongIO and Obselete Bits set, returning" " ILLEGAL_REQUEST\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - ret = -EINVAL; - goto out; + return TCM_UNSUPPORTED_SCSI_OPCODE; } /* * This is currently the case for target_core_mod passthrough struct se_cmd @@ -266,13 +240,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) rc = target_check_scsi2_reservation_conflict(cmd); if (rc == 1) goto out; - else if (rc < 0) { - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; - } - ret = 0; + if (rc < 0) + return TCM_RESERVATION_CONFLICT; + tpg = sess->se_tpg; spin_lock(&dev->dev_reservation_lock); if (dev->dev_reserved_node_acl && @@ -286,16 +257,15 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) " from %s \n", cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, sess->se_node_acl->initiatorname); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out_unlock; } dev->dev_reserved_node_acl = sess->se_node_acl; - dev->dev_flags |= DF_SPC2_RESERVATIONS; + dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS; if (sess->sess_bin_isid != 0) { dev->dev_res_bin_isid = sess->sess_bin_isid; - dev->dev_flags |= DF_SPC2_RESERVATIONS_WITH_ISID; + dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID; } pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u" " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), @@ -319,9 +289,9 @@ out: */ static int core_scsi3_pr_seq_non_holder( struct se_cmd *cmd, - unsigned char *cdb, u32 pr_reg_type) { + unsigned char *cdb = cmd->t_task_cdb; struct se_dev_entry *se_deve; struct se_session *se_sess = cmd->se_sess; int other_cdb = 0, ignore_reg; @@ -330,17 +300,11 @@ static int core_scsi3_pr_seq_non_holder( int we = 0; /* Write Exclusive */ int legacy = 0; /* Act like a legacy device and return * RESERVATION CONFLICT on some CDBs */ - /* - * A legacy SPC-2 reservation is being held. - */ - if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) - return core_scsi2_reservation_seq_non_holder(cmd, - cdb, pr_reg_type); se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; /* * Determine if the registration should be ignored due to - * non-matching ISIDs in core_scsi3_pr_reservation_check(). + * non-matching ISIDs in target_scsi3_pr_reservation_check(). */ ignore_reg = (pr_reg_type & 0x80000000); if (ignore_reg) @@ -563,10 +527,41 @@ static int core_scsi3_pr_seq_non_holder( return 1; /* Conflict by default */ } +static sense_reason_t +target_scsi3_pr_reservation_check(struct se_cmd *cmd) +{ + struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; + u32 pr_reg_type; + + if (!dev->dev_pr_res_holder) + return 0; + + pr_reg_type = dev->dev_pr_res_holder->pr_res_type; + cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key; + if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) + goto check_nonholder; + + if (dev->dev_pr_res_holder->isid_present_at_reg) { + if (dev->dev_pr_res_holder->pr_reg_bin_isid != + sess->sess_bin_isid) { + pr_reg_type |= 0x80000000; + goto check_nonholder; + } + } + + return 0; + +check_nonholder: + if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) + return TCM_RESERVATION_CONFLICT; + return 0; +} + static u32 core_scsi3_pr_generation(struct se_device *dev) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; u32 prg; + /* * PRGeneration field shall contain the value of a 32-bit wrapping * counter mainted by the device server. @@ -577,56 +572,12 @@ static u32 core_scsi3_pr_generation(struct se_device *dev) * See spc4r17 section 6.3.12 READ_KEYS service action */ spin_lock(&dev->dev_reservation_lock); - prg = su_dev->t10_pr.pr_generation++; + prg = dev->t10_pr.pr_generation++; spin_unlock(&dev->dev_reservation_lock); return prg; } -static int core_scsi3_pr_reservation_check( - struct se_cmd *cmd, - u32 *pr_reg_type) -{ - struct se_device *dev = cmd->se_dev; - struct se_session *sess = cmd->se_sess; - int ret; - - if (!sess) - return 0; - /* - * A legacy SPC-2 reservation is being held. - */ - if (dev->dev_flags & DF_SPC2_RESERVATIONS) - return core_scsi2_reservation_check(cmd, pr_reg_type); - - spin_lock(&dev->dev_reservation_lock); - if (!dev->dev_pr_res_holder) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - *pr_reg_type = dev->dev_pr_res_holder->pr_res_type; - cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key; - if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) { - spin_unlock(&dev->dev_reservation_lock); - return -EINVAL; - } - if (!dev->dev_pr_res_holder->isid_present_at_reg) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - ret = (dev->dev_pr_res_holder->pr_reg_bin_isid == - sess->sess_bin_isid) ? 0 : -EINVAL; - /* - * Use bit in *pr_reg_type to notify ISID mismatch in - * core_scsi3_pr_seq_non_holder(). - */ - if (ret != 0) - *pr_reg_type |= 0x80000000; - spin_unlock(&dev->dev_reservation_lock); - - return ret; -} - static struct t10_pr_registration *__core_scsi3_do_alloc_registration( struct se_device *dev, struct se_node_acl *nacl, @@ -636,7 +587,6 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( int all_tg_pt, int aptpl) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct t10_pr_registration *pr_reg; pr_reg = kmem_cache_zalloc(t10_pr_reg_cache, GFP_ATOMIC); @@ -645,7 +595,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( return NULL; } - pr_reg->pr_aptpl_buf = kzalloc(su_dev->t10_pr.pr_aptpl_buf_len, + pr_reg->pr_aptpl_buf = kzalloc(dev->t10_pr.pr_aptpl_buf_len, GFP_ATOMIC); if (!pr_reg->pr_aptpl_buf) { pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n"); @@ -929,7 +879,7 @@ static int __core_scsi3_check_aptpl_registration( struct se_dev_entry *deve) { struct t10_pr_registration *pr_reg, *pr_reg_tmp; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char i_port[PR_APTPL_MAX_IPORT_LEN]; unsigned char t_port[PR_APTPL_MAX_TPORT_LEN]; u16 tpgt; @@ -996,11 +946,10 @@ int core_scsi3_check_aptpl_registration( struct se_lun *lun, struct se_lun_acl *lun_acl) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct se_node_acl *nacl = lun_acl->se_lun_nacl; struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun]; - if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) return 0; return __core_scsi3_check_aptpl_registration(dev, tpg, lun, @@ -1051,10 +1000,9 @@ static void __core_scsi3_add_registration( int register_type, int register_move) { - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; /* * Increment PRgeneration counter for struct se_device upon a successful @@ -1066,7 +1014,7 @@ static void __core_scsi3_add_registration( * for the REGISTER. */ pr_reg->pr_res_generation = (register_move) ? - su_dev->t10_pr.pr_generation++ : + dev->t10_pr.pr_generation++ : core_scsi3_pr_generation(dev); spin_lock(&pr_tmpl->registration_lock); @@ -1135,7 +1083,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg( struct se_node_acl *nacl, unsigned char *isid) { - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp; struct se_portal_group *tpg; @@ -1160,7 +1108,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg( * for fabric modules (iSCSI) requiring them. */ if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) { - if (dev->se_sub_dev->se_dev_attrib.enforce_pr_isids) + if (dev->dev_attrib.enforce_pr_isids) continue; } atomic_inc(&pr_reg->pr_res_holders); @@ -1274,7 +1222,7 @@ static void __core_scsi3_free_registration( { struct target_core_fabric_ops *tfo = pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; char i_buf[PR_REG_ISID_ID_LEN]; int prf_isid; @@ -1335,7 +1283,7 @@ void core_scsi3_free_pr_reg_from_nacl( struct se_device *dev, struct se_node_acl *nacl) { - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; /* * If the passed se_node_acl matches the reservation holder, @@ -1365,7 +1313,7 @@ void core_scsi3_free_pr_reg_from_nacl( void core_scsi3_free_all_registrations( struct se_device *dev) { - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; spin_lock(&dev->dev_reservation_lock); @@ -1479,7 +1427,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve) smp_mb__after_atomic_dec(); } -static int core_scsi3_decode_spec_i_port( +static sense_reason_t +core_scsi3_decode_spec_i_port( struct se_cmd *cmd, struct se_portal_group *tpg, unsigned char *l_isid, @@ -1501,8 +1450,9 @@ static int core_scsi3_decode_spec_i_port( unsigned char *buf; unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; + sense_reason_t ret; u32 tpdl, tid_len = 0; - int ret, dest_local_nexus, prf_isid; + int dest_local_nexus, prf_isid; u32 dest_rtpi = 0; memset(dest_iport, 0, 64); @@ -1517,8 +1467,7 @@ static int core_scsi3_decode_spec_i_port( tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); if (!tidh_new) { pr_err("Unable to allocate tidh_new\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } INIT_LIST_HEAD(&tidh_new->dest_list); tidh_new->dest_tpg = tpg; @@ -1530,8 +1479,7 @@ static int core_scsi3_decode_spec_i_port( sa_res_key, all_tg_pt, aptpl); if (!local_pr_reg) { kfree(tidh_new); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } tidh_new->dest_pr_reg = local_pr_reg; /* @@ -1545,12 +1493,16 @@ static int core_scsi3_decode_spec_i_port( if (cmd->data_length < 28) { pr_warn("SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out; + } + /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, * first extract TransportID Parameter Data Length, and make sure @@ -1565,9 +1517,8 @@ static int core_scsi3_decode_spec_i_port( pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" " does not equal CDB data_length: %u\n", tpdl, cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } /* * Start processing the received transport IDs using the @@ -1610,16 +1561,13 @@ static int core_scsi3_decode_spec_i_port( smp_mb__after_atomic_inc(); spin_unlock(&dev->se_port_lock); - ret = core_scsi3_tpg_depend_item(tmp_tpg); - if (ret != 0) { + if (core_scsi3_tpg_depend_item(tmp_tpg)) { pr_err(" core_scsi3_tpg_depend_item()" " for tmp_tpg\n"); atomic_dec(&tmp_tpg->tpg_pr_ref_count); smp_mb__after_atomic_dec(); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } /* * Locate the destination initiator ACL to be registered @@ -1641,17 +1589,14 @@ static int core_scsi3_decode_spec_i_port( continue; } - ret = core_scsi3_nodeacl_depend_item(dest_node_acl); - if (ret != 0) { + if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { pr_err("configfs_depend_item() failed" " for dest_node_acl->acl_group\n"); atomic_dec(&dest_node_acl->acl_pr_ref_count); smp_mb__after_atomic_dec(); core_scsi3_tpg_undepend_item(tmp_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } dest_tpg = tmp_tpg; @@ -1668,9 +1613,8 @@ static int core_scsi3_decode_spec_i_port( if (!dest_tpg) { pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" " dest_tpg\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u" @@ -1683,9 +1627,8 @@ static int core_scsi3_decode_spec_i_port( " %u for Transport ID: %s\n", tid_len, ptr); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } /* * Locate the desintation struct se_dev_entry pointer for matching @@ -1702,23 +1645,19 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } - ret = core_scsi3_lunacl_depend_item(dest_se_deve); - if (ret < 0) { + if (core_scsi3_lunacl_depend_item(dest_se_deve)) { pr_err("core_scsi3_lunacl_depend_item()" " failed\n"); atomic_dec(&dest_se_deve->pr_ref_count); smp_mb__after_atomic_dec(); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" @@ -1754,10 +1693,8 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -ENOMEM; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } INIT_LIST_HEAD(&tidh_new->dest_list); tidh_new->dest_tpg = dest_tpg; @@ -1788,9 +1725,8 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); kfree(tidh_new); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } tidh_new->dest_pr_reg = dest_pr_reg; list_add_tail(&tidh_new->dest_list, &tid_dest_list); @@ -1848,8 +1784,9 @@ static int core_scsi3_decode_spec_i_port( } return 0; -out: +out_unmap: transport_kunmap_data_sg(cmd); +out: /* * For the failure case, release everything from tid_dest_list * including *dest_pr_reg and the configfs dependances.. @@ -1899,7 +1836,6 @@ static int __core_scsi3_update_aptpl_buf( { struct se_lun *lun; struct se_portal_group *tpg; - struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct t10_pr_registration *pr_reg; unsigned char tmp[512], isid_buf[32]; ssize_t len = 0; @@ -1917,8 +1853,8 @@ static int __core_scsi3_update_aptpl_buf( /* * Walk the registration list.. */ - spin_lock(&su_dev->t10_pr.registration_lock); - list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, + spin_lock(&dev->t10_pr.registration_lock); + list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, pr_reg_list) { tmp[0] = '\0'; @@ -1963,7 +1899,7 @@ static int __core_scsi3_update_aptpl_buf( if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { pr_err("Unable to update renaming" " APTPL metadata\n"); - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); return -EMSGSIZE; } len += sprintf(buf+len, "%s", tmp); @@ -1981,13 +1917,13 @@ static int __core_scsi3_update_aptpl_buf( if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { pr_err("Unable to update renaming" " APTPL metadata\n"); - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); return -EMSGSIZE; } len += sprintf(buf+len, "%s", tmp); reg_count++; } - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); if (!reg_count) len += sprintf(buf+len, "No Registrations or Reservations"); @@ -2019,7 +1955,7 @@ static int __core_scsi3_write_aptpl_to_file( unsigned char *buf, u32 pr_aptpl_buf_len) { - struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn; + struct t10_wwn *wwn = &dev->t10_wwn; struct file *file; struct iovec iov[1]; mm_segment_t old_fs; @@ -2065,14 +2001,15 @@ static int __core_scsi3_write_aptpl_to_file( return 0; } -static int core_scsi3_update_and_write_aptpl( - struct se_device *dev, - unsigned char *in_buf, - u32 in_pr_aptpl_buf_len) +static int +core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, + u32 in_pr_aptpl_buf_len) { unsigned char null_buf[64], *buf; u32 pr_aptpl_buf_len; - int ret, clear_aptpl_metadata = 0; + int clear_aptpl_metadata = 0; + int ret; + /* * Can be called with a NULL pointer from PROUT service action CLEAR */ @@ -2094,25 +2031,17 @@ static int core_scsi3_update_and_write_aptpl( clear_aptpl_metadata); if (ret != 0) return ret; + /* * __core_scsi3_write_aptpl_to_file() will call strlen() * on the passed buf to determine pr_aptpl_buf_len. */ - ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0); - if (ret != 0) - return ret; - - return ret; + return __core_scsi3_write_aptpl_to_file(dev, buf, 0); } -static int core_scsi3_emulate_pro_register( - struct se_cmd *cmd, - u64 res_key, - u64 sa_res_key, - int aptpl, - int all_tg_pt, - int spec_i_pt, - int ignore_key) +static sense_reason_t +core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, + int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key) { struct se_session *se_sess = cmd->se_sess; struct se_device *dev = cmd->se_dev; @@ -2120,16 +2049,16 @@ static int core_scsi3_emulate_pro_register( struct se_lun *se_lun = cmd->se_lun; struct se_portal_group *se_tpg; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; /* Used for APTPL metadata w/ UNREGISTER */ unsigned char *pr_aptpl_buf = NULL; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; - int pr_holder = 0, ret = 0, type; + sense_reason_t ret = TCM_NO_SENSE; + int pr_holder = 0, type; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } se_tpg = se_sess->se_tpg; se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; @@ -2148,8 +2077,7 @@ static int core_scsi3_emulate_pro_register( if (res_key) { pr_warn("SPC-3 PR: Reservation Key non-zero" " for SA REGISTER, returning CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * Do nothing but return GOOD status. @@ -2163,15 +2091,13 @@ static int core_scsi3_emulate_pro_register( * Port Endpoint that the PRO was received from on the * Logical Unit of the SCSI device server. */ - ret = core_scsi3_alloc_registration(cmd->se_dev, + if (core_scsi3_alloc_registration(cmd->se_dev, se_sess->se_node_acl, se_deve, isid_ptr, sa_res_key, all_tg_pt, aptpl, - ignore_key, 0); - if (ret != 0) { + ignore_key, 0)) { pr_err("Unable to allocate" " struct t10_pr_registration\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } } else { /* @@ -2205,201 +2131,192 @@ static int core_scsi3_emulate_pro_register( pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { + pr_tmpl->pr_aptpl_buf_len)) { pr_tmpl->pr_aptpl_active = 1; pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); } - core_scsi3_put_pr_reg(pr_reg); - return ret; - } else { - /* - * Locate the existing *pr_reg via struct se_node_acl pointers - */ - pr_reg = pr_reg_e; - type = pr_reg->pr_res_type; - - if (!ignore_key) { - if (res_key != pr_reg->pr_res_key) { - pr_err("SPC-3 PR REGISTER: Received" - " res_key: 0x%016Lx does not match" - " existing SA REGISTER res_key:" - " 0x%016Lx\n", res_key, - pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; - } + goto out_put_pr_reg; + } + + /* + * Locate the existing *pr_reg via struct se_node_acl pointers + */ + pr_reg = pr_reg_e; + type = pr_reg->pr_res_type; + + if (!ignore_key) { + if (res_key != pr_reg->pr_res_key) { + pr_err("SPC-3 PR REGISTER: Received" + " res_key: 0x%016Lx does not match" + " existing SA REGISTER res_key:" + " 0x%016Lx\n", res_key, + pr_reg->pr_res_key); + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } - if (spec_i_pt) { - pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" - " set while sa_res_key=0\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + } + + if (spec_i_pt) { + pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" + " set while sa_res_key=0\n"); + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; + } + + /* + * An existing ALL_TG_PT=1 registration being released + * must also set ALL_TG_PT=1 in the incoming PROUT. + */ + if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { + pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" + " registration exists, but ALL_TG_PT=1 bit not" + " present in received PROUT\n"); + ret = TCM_INVALID_CDB_FIELD; + goto out_put_pr_reg; + } + + /* + * Allocate APTPL metadata buffer used for UNREGISTER ops + */ + if (aptpl) { + pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, + GFP_KERNEL); + if (!pr_aptpl_buf) { + pr_err("Unable to allocate" + " pr_aptpl_buf\n"); + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; } - /* - * An existing ALL_TG_PT=1 registration being released - * must also set ALL_TG_PT=1 in the incoming PROUT. - */ - if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { - pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" - " registration exists, but ALL_TG_PT=1 bit not" - " present in received PROUT\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + } + + /* + * sa_res_key=0 Unregister Reservation Key for registered I_T + * Nexus sa_res_key=1 Change Reservation Key for registered I_T + * Nexus. + */ + if (!sa_res_key) { + pr_holder = core_scsi3_check_implict_release( + cmd->se_dev, pr_reg); + if (pr_holder < 0) { + kfree(pr_aptpl_buf); + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } + + spin_lock(&pr_tmpl->registration_lock); /* - * Allocate APTPL metadata buffer used for UNREGISTER ops + * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port + * and matching pr_res_key. */ - if (aptpl) { - pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, - GFP_KERNEL); - if (!pr_aptpl_buf) { - pr_err("Unable to allocate" - " pr_aptpl_buf\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + if (pr_reg->pr_reg_all_tg_pt) { + list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, + &pr_tmpl->registration_list, + pr_reg_list) { + + if (!pr_reg_p->pr_reg_all_tg_pt) + continue; + if (pr_reg_p->pr_res_key != res_key) + continue; + if (pr_reg == pr_reg_p) + continue; + if (strcmp(pr_reg->pr_reg_nacl->initiatorname, + pr_reg_p->pr_reg_nacl->initiatorname)) + continue; + + __core_scsi3_free_registration(dev, + pr_reg_p, NULL, 0); } } + /* - * sa_res_key=0 Unregister Reservation Key for registered I_T - * Nexus sa_res_key=1 Change Reservation Key for registered I_T - * Nexus. + * Release the calling I_T Nexus registration now.. */ - if (!sa_res_key) { - pr_holder = core_scsi3_check_implict_release( - cmd->se_dev, pr_reg); - if (pr_holder < 0) { - kfree(pr_aptpl_buf); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; - } - - spin_lock(&pr_tmpl->registration_lock); - /* - * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port - * and matching pr_res_key. - */ - if (pr_reg->pr_reg_all_tg_pt) { - list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, - &pr_tmpl->registration_list, - pr_reg_list) { - - if (!pr_reg_p->pr_reg_all_tg_pt) - continue; + __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1); - if (pr_reg_p->pr_res_key != res_key) - continue; - - if (pr_reg == pr_reg_p) - continue; - - if (strcmp(pr_reg->pr_reg_nacl->initiatorname, - pr_reg_p->pr_reg_nacl->initiatorname)) - continue; - - __core_scsi3_free_registration(dev, - pr_reg_p, NULL, 0); - } - } - /* - * Release the calling I_T Nexus registration now.. - */ - __core_scsi3_free_registration(cmd->se_dev, pr_reg, - NULL, 1); - /* - * From spc4r17, section 5.7.11.3 Unregistering - * - * If the persistent reservation is a registrants only - * type, the device server shall establish a unit - * attention condition for the initiator port associated - * with every registered I_T nexus except for the I_T - * nexus on which the PERSISTENT RESERVE OUT command was - * received, with the additional sense code set to - * RESERVATIONS RELEASED. - */ - if (pr_holder && - ((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) || - (type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) { - list_for_each_entry(pr_reg_p, - &pr_tmpl->registration_list, - pr_reg_list) { - - core_scsi3_ua_allocate( - pr_reg_p->pr_reg_nacl, - pr_reg_p->pr_res_mapped_lun, - 0x2A, - ASCQ_2AH_RESERVATIONS_RELEASED); - } + /* + * From spc4r17, section 5.7.11.3 Unregistering + * + * If the persistent reservation is a registrants only + * type, the device server shall establish a unit + * attention condition for the initiator port associated + * with every registered I_T nexus except for the I_T + * nexus on which the PERSISTENT RESERVE OUT command was + * received, with the additional sense code set to + * RESERVATIONS RELEASED. + */ + if (pr_holder && + (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || + type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { + list_for_each_entry(pr_reg_p, + &pr_tmpl->registration_list, + pr_reg_list) { + + core_scsi3_ua_allocate( + pr_reg_p->pr_reg_nacl, + pr_reg_p->pr_res_mapped_lun, + 0x2A, + ASCQ_2AH_RESERVATIONS_RELEASED); } - spin_unlock(&pr_tmpl->registration_lock); + } + spin_unlock(&pr_tmpl->registration_lock); - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(dev, NULL, 0); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" - " for UNREGISTER\n"); - return 0; - } + if (!aptpl) { + pr_tmpl->pr_aptpl_active = 0; + core_scsi3_update_and_write_aptpl(dev, NULL, 0); + pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" + " for UNREGISTER\n"); + return 0; + } - ret = core_scsi3_update_and_write_aptpl(dev, - &pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated" - " for UNREGISTER\n"); - } + if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], + pr_tmpl->pr_aptpl_buf_len)) { + pr_tmpl->pr_aptpl_active = 1; + pr_debug("SPC-3 PR: Set APTPL Bit Activated" + " for UNREGISTER\n"); + } - kfree(pr_aptpl_buf); - return ret; - } else { - /* - * Increment PRgeneration counter for struct se_device" - * upon a successful REGISTER, see spc4r17 section 6.3.2 - * READ_KEYS service action. - */ - pr_reg->pr_res_generation = core_scsi3_pr_generation( - cmd->se_dev); - pr_reg->pr_res_key = sa_res_key; - pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" - " Key for %s to: 0x%016Lx PRgeneration:" - " 0x%08x\n", cmd->se_tfo->get_fabric_name(), - (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", - pr_reg->pr_reg_nacl->initiatorname, - pr_reg->pr_res_key, pr_reg->pr_res_generation); - - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(dev, NULL, 0); - core_scsi3_put_pr_reg(pr_reg); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" - " for REGISTER\n"); - return 0; - } + goto out_free_aptpl_buf; + } - ret = core_scsi3_update_and_write_aptpl(dev, - &pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated" - " for REGISTER\n"); - } + /* + * Increment PRgeneration counter for struct se_device" + * upon a successful REGISTER, see spc4r17 section 6.3.2 + * READ_KEYS service action. + */ + pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev); + pr_reg->pr_res_key = sa_res_key; + pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" + " Key for %s to: 0x%016Lx PRgeneration:" + " 0x%08x\n", cmd->se_tfo->get_fabric_name(), + (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", + pr_reg->pr_reg_nacl->initiatorname, + pr_reg->pr_res_key, pr_reg->pr_res_generation); - kfree(pr_aptpl_buf); - core_scsi3_put_pr_reg(pr_reg); - } + if (!aptpl) { + pr_tmpl->pr_aptpl_active = 0; + core_scsi3_update_and_write_aptpl(dev, NULL, 0); + pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" + " for REGISTER\n"); + ret = 0; + goto out_put_pr_reg; } - return 0; + + if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], + pr_tmpl->pr_aptpl_buf_len)) { + pr_tmpl->pr_aptpl_active = 1; + pr_debug("SPC-3 PR: Set APTPL Bit Activated" + " for REGISTER\n"); + } + +out_free_aptpl_buf: + kfree(pr_aptpl_buf); + ret = 0; +out_put_pr_reg: + core_scsi3_put_pr_reg(pr_reg); + return ret; } unsigned char *core_scsi3_pr_dump_type(int type) @@ -2424,26 +2341,23 @@ unsigned char *core_scsi3_pr_dump_type(int type) return "Unknown SPC-3 PR Type"; } -static int core_scsi3_pro_reserve( - struct se_cmd *cmd, - struct se_device *dev, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) { + struct se_device *dev = cmd->se_dev; struct se_session *se_sess = cmd->se_sess; struct se_lun *se_lun = cmd->se_lun; struct t10_pr_registration *pr_reg, *pr_res_holder; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; char i_buf[PR_REG_ISID_ID_LEN]; - int ret, prf_isid; + sense_reason_t ret; + int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * Locate the existing *pr_reg via struct se_node_acl pointers @@ -2453,8 +2367,7 @@ static int core_scsi3_pro_reserve( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for RESERVE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2469,9 +2382,8 @@ static int core_scsi3_pro_reserve( pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx" " does not match existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2485,9 +2397,8 @@ static int core_scsi3_pro_reserve( */ if (scope != PR_SCOPE_LU_SCOPE) { pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } /* * See if we have an existing PR reservation holder pointer at @@ -2518,9 +2429,8 @@ static int core_scsi3_pro_reserve( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2542,9 +2452,8 @@ static int core_scsi3_pro_reserve( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2557,8 +2466,8 @@ static int core_scsi3_pro_reserve( * shall completethe command with GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - return 0; + ret = 0; + goto out_put_pr_reg; } /* * Otherwise, our *pr_reg becomes the PR reservation holder for said @@ -2582,27 +2491,24 @@ static int core_scsi3_pro_reserve( spin_unlock(&dev->dev_reservation_lock); if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata" " for RESERVE\n"); + } } + ret = 0; +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); - return 0; + return ret; } -static int core_scsi3_emulate_pro_reserve( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_reserve(struct se_cmd *cmd, int type, int scope, + u64 res_key) { - struct se_device *dev = cmd->se_dev; - int ret = 0; - switch (type) { case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_EXCLUSIVE_ACCESS: @@ -2610,16 +2516,12 @@ static int core_scsi3_emulate_pro_reserve( case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: - ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key); - break; + return core_scsi3_pro_reserve(cmd, type, scope, res_key); default: pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" " 0x%02x\n", type); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } - - return ret; } /* @@ -2657,23 +2559,21 @@ static void __core_scsi3_complete_pro_release( pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0; } -static int core_scsi3_emulate_pro_release( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, + u64 res_key) { struct se_device *dev = cmd->se_dev; struct se_session *se_sess = cmd->se_sess; struct se_lun *se_lun = cmd->se_lun; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; - int ret, all_reg = 0; + struct t10_reservation *pr_tmpl = &dev->t10_pr; + int all_reg = 0; + sense_reason_t ret = 0; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * Locate the existing *pr_reg via struct se_node_acl pointers @@ -2682,8 +2582,7 @@ static int core_scsi3_emulate_pro_release( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for RELEASE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 Section 5.7.11.2 Releasing: @@ -2704,8 +2603,7 @@ static int core_scsi3_emulate_pro_release( * No persistent reservation, return GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - return 0; + goto out_put_pr_reg; } if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) @@ -2718,9 +2616,9 @@ static int core_scsi3_emulate_pro_release( * persistent reservation holder. return GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - return 0; + goto out_put_pr_reg; } + /* * From spc4r17 Section 5.7.11.2 Releasing: * @@ -2740,9 +2638,8 @@ static int core_scsi3_emulate_pro_release( " does not match existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg->pr_res_key); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.11.2 Releasing and above: @@ -2763,9 +2660,8 @@ static int core_scsi3_emulate_pro_release( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * In response to a persistent reservation release request from the @@ -2818,25 +2714,23 @@ static int core_scsi3_emulate_pro_release( write_aptpl: if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, - &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, + &pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); + } } - +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); - return 0; + return ret; } -static int core_scsi3_emulate_pro_clear( - struct se_cmd *cmd, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) { struct se_device *dev = cmd->se_dev; struct se_node_acl *pr_reg_nacl; struct se_session *se_sess = cmd->se_sess; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; u32 pr_res_mapped_lun = 0; int calling_it_nexus = 0; @@ -2848,8 +2742,7 @@ static int core_scsi3_emulate_pro_clear( if (!pr_reg_n) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for CLEAR\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 section 5.7.11.6, Clearing: @@ -2868,8 +2761,7 @@ static int core_scsi3_emulate_pro_clear( " existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * a) Release the persistent reservation, if any; @@ -2993,28 +2885,22 @@ static void core_scsi3_release_preempt_and_abort( } } -static int core_scsi3_pro_preempt( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key, - u64 sa_res_key, - int abort) +static sense_reason_t +core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, + u64 sa_res_key, int abort) { struct se_device *dev = cmd->se_dev; struct se_node_acl *pr_reg_nacl; struct se_session *se_sess = cmd->se_sess; LIST_HEAD(preempt_and_abort_list); struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; u32 pr_res_mapped_lun = 0; int all_reg = 0, calling_it_nexus = 0, released_regs = 0; - int prh_type = 0, prh_scope = 0, ret; + int prh_type = 0, prh_scope = 0; - if (!se_sess) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; - } + if (!se_sess) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); @@ -3022,19 +2908,16 @@ static int core_scsi3_pro_preempt( pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for PREEMPT%s\n", (abort) ? "_AND_ABORT" : ""); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } if (pr_reg_n->pr_res_key != res_key) { core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } if (scope != PR_SCOPE_LU_SCOPE) { pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } spin_lock(&dev->dev_reservation_lock); @@ -3047,8 +2930,7 @@ static int core_scsi3_pro_preempt( if (!all_reg && !sa_res_key) { spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } /* * From spc4r17, section 5.7.11.4.4 Removing Registrations: @@ -3142,8 +3024,7 @@ static int core_scsi3_pro_preempt( if (!released_regs) { spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * For an existing all registrants type reservation @@ -3162,13 +3043,13 @@ static int core_scsi3_pro_preempt( spin_unlock(&dev->dev_reservation_lock); if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg_n->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL" " metadata for PREEMPT%s\n", (abort) ? "_AND_ABORT" : ""); + } } core_scsi3_put_pr_reg(pr_reg_n); @@ -3298,12 +3179,12 @@ static int core_scsi3_pro_preempt( } if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg_n->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" - "%s\n", (abort) ? "_AND_ABORT" : ""); + "%s\n", abort ? "_AND_ABORT" : ""); + } } core_scsi3_put_pr_reg(pr_reg_n); @@ -3311,16 +3192,10 @@ static int core_scsi3_pro_preempt( return 0; } -static int core_scsi3_emulate_pro_preempt( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key, - u64 sa_res_key, - int abort) +static sense_reason_t +core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope, + u64 res_key, u64 sa_res_key, int abort) { - int ret = 0; - switch (type) { case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_EXCLUSIVE_ACCESS: @@ -3328,26 +3203,19 @@ static int core_scsi3_emulate_pro_preempt( case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: - ret = core_scsi3_pro_preempt(cmd, type, scope, - res_key, sa_res_key, abort); - break; + return core_scsi3_pro_preempt(cmd, type, scope, res_key, + sa_res_key, abort); default: pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } - - return ret; } -static int core_scsi3_emulate_pro_register_and_move( - struct se_cmd *cmd, - u64 res_key, - u64 sa_res_key, - int aptpl, - int unreg) +static sense_reason_t +core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, + u64 sa_res_key, int aptpl, int unreg) { struct se_session *se_sess = cmd->se_sess; struct se_device *dev = cmd->se_dev; @@ -3358,20 +3226,21 @@ static int core_scsi3_emulate_pro_register_and_move( struct se_portal_group *se_tpg, *dest_se_tpg = NULL; struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops; struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; unsigned char *initiator_str; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; u32 tid_len, tmp_tid_len; - int new_reg = 0, type, scope, ret, matching_iname, prf_isid; + int new_reg = 0, type, scope, matching_iname, prf_isid; + sense_reason_t ret; unsigned short rtpi; unsigned char proto_ident; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } + memset(dest_iport, 0, 64); memset(i_buf, 0, PR_REG_ISID_ID_LEN); se_tpg = se_sess->se_tpg; @@ -3387,8 +3256,7 @@ static int core_scsi3_emulate_pro_register_and_move( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" " *pr_reg for REGISTER_AND_MOVE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * The provided reservation key much match the existing reservation key @@ -3398,9 +3266,8 @@ static int core_scsi3_emulate_pro_register_and_move( pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received" " res_key: 0x%016Lx does not match existing SA REGISTER" " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * The service active reservation key needs to be non zero @@ -3408,9 +3275,8 @@ static int core_scsi3_emulate_pro_register_and_move( if (!sa_res_key) { pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" " sa_res_key\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } /* @@ -3419,6 +3285,11 @@ static int core_scsi3_emulate_pro_register_and_move( * information. */ buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; + } + rtpi = (buf[18] & 0xff) << 8; rtpi |= buf[19] & 0xff; tid_len = (buf[20] & 0xff) << 24; @@ -3432,9 +3303,8 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header" " does not equal CDB data_length: %u\n", tid_len, cmd->data_length); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } spin_lock(&dev->se_port_lock); @@ -3452,15 +3322,13 @@ static int core_scsi3_emulate_pro_register_and_move( smp_mb__after_atomic_inc(); spin_unlock(&dev->se_port_lock); - ret = core_scsi3_tpg_depend_item(dest_se_tpg); - if (ret != 0) { + if (core_scsi3_tpg_depend_item(dest_se_tpg)) { pr_err("core_scsi3_tpg_depend_item() failed" " for dest_se_tpg\n"); atomic_dec(&dest_se_tpg->tpg_pr_ref_count); smp_mb__after_atomic_dec(); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; } spin_lock(&dev->se_port_lock); @@ -3472,12 +3340,15 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" " fabric ops from Relative Target Port Identifier:" " %hu\n", rtpi); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; + } proto_ident = (buf[24] & 0x0f); pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" @@ -3489,16 +3360,14 @@ static int core_scsi3_emulate_pro_register_and_move( " from fabric: %s\n", proto_ident, dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), dest_tf_ops->get_fabric_name()); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" " containg a valid tpg_parse_pr_out_transport_id" " function pointer\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out; } initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, @@ -3506,8 +3375,7 @@ static int core_scsi3_emulate_pro_register_and_move( if (!initiator_str) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" " initiator_str from Transport ID\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } @@ -3536,8 +3404,7 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" " matches: %s on received I_T Nexus\n", initiator_str, pr_reg_nacl->initiatorname); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { @@ -3545,8 +3412,7 @@ static int core_scsi3_emulate_pro_register_and_move( " matches: %s %s on received I_T Nexus\n", initiator_str, iport_ptr, pr_reg_nacl->initiatorname, pr_reg->pr_reg_isid); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } after_iport_check: @@ -3566,19 +3432,17 @@ after_iport_check: pr_err("Unable to locate %s dest_node_acl for" " TransportID%s\n", dest_tf_ops->get_fabric_name(), initiator_str); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } - ret = core_scsi3_nodeacl_depend_item(dest_node_acl); - if (ret != 0) { + + if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { pr_err("core_scsi3_nodeacl_depend_item() for" " dest_node_acl\n"); atomic_dec(&dest_node_acl->acl_pr_ref_count); smp_mb__after_atomic_dec(); dest_node_acl = NULL; - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } @@ -3594,19 +3458,16 @@ after_iport_check: if (!dest_se_deve) { pr_err("Unable to locate %s dest_se_deve from RTPI:" " %hu\n", dest_tf_ops->get_fabric_name(), rtpi); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } - ret = core_scsi3_lunacl_depend_item(dest_se_deve); - if (ret < 0) { + if (core_scsi3_lunacl_depend_item(dest_se_deve)) { pr_err("core_scsi3_lunacl_depend_item() failed\n"); atomic_dec(&dest_se_deve->pr_ref_count); smp_mb__after_atomic_dec(); dest_se_deve = NULL; - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out; } @@ -3625,8 +3486,7 @@ after_iport_check: pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" " currently held\n"); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; goto out; } /* @@ -3639,8 +3499,7 @@ after_iport_check: pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" " Nexus is not reservation holder\n"); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out; } /* @@ -3658,8 +3517,7 @@ after_iport_check: " reservation for type: %s\n", core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out; } pr_res_nacl = pr_res_holder->pr_reg_nacl; @@ -3691,13 +3549,11 @@ after_iport_check: dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, iport_ptr); if (!dest_pr_reg) { - ret = core_scsi3_alloc_registration(cmd->se_dev, + if (core_scsi3_alloc_registration(cmd->se_dev, dest_node_acl, dest_se_deve, iport_ptr, - sa_res_key, 0, aptpl, 2, 1); - if (ret != 0) { + sa_res_key, 0, aptpl, 2, 1)) { spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, @@ -3768,12 +3624,12 @@ after_iport_check: " REGISTER_AND_MOVE\n"); } else { pr_tmpl->pr_aptpl_active = 1; - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &dest_pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Set APTPL Bit Activated for" " REGISTER_AND_MOVE\n"); + } } transport_kunmap_data_sg(cmd); @@ -3788,6 +3644,8 @@ out: if (dest_node_acl) core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_se_tpg); + +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); return ret; } @@ -3805,14 +3663,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb) /* * See spc4r17 section 6.14 Table 170 */ -int target_scsi3_emulate_pr_out(struct se_cmd *cmd) +sense_reason_t +target_scsi3_emulate_pr_out(struct se_cmd *cmd) { unsigned char *cdb = &cmd->t_task_cdb[0]; unsigned char *buf; u64 res_key, sa_res_key; int sa, scope, type, aptpl; int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; - int ret; + sense_reason_t ret; /* * Following spc2r20 5.5.1 Reservations overview: @@ -3823,32 +3682,26 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) * initiator or service action and shall terminate with a RESERVATION * CONFLICT status. */ - if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) { + if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) { pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; + return TCM_RESERVATION_CONFLICT; } /* * FIXME: A NULL struct se_session pointer means an this is not coming from * a $FABRIC_MOD's nexus, but from internal passthrough ops. */ - if (!cmd->se_sess) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; - } + if (!cmd->se_sess) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; if (cmd->data_length < 24) { pr_warn("SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + return TCM_INVALID_PARAMETER_LIST; } + /* * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) */ @@ -3857,6 +3710,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) type = (cdb[2] & 0x0f); buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + /* * From PERSISTENT_RESERVE_OUT parameter list (payload) */ @@ -3880,11 +3736,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) /* * SPEC_I_PT=1 is only valid for Service action: REGISTER */ - if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; - } + if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) + return TCM_INVALID_PARAMETER_LIST; /* * From spc4r17 section 6.14: @@ -3899,10 +3752,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) (cmd->data_length != 24)) { pr_warn("SPC-PR: Received PR OUT illegal parameter" " list length: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + return TCM_INVALID_PARAMETER_LIST; } + /* * (core_scsi3_emulate_pro_* function parameters * are defined by spc4r17 Table 174: @@ -3941,12 +3793,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) default: pr_err("Unknown PERSISTENT_RESERVE_OUT service" " action: 0x%02x\n", cdb[1] & 0x1f); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } -out: if (!ret) target_complete_cmd(cmd, GOOD); return ret; @@ -3957,10 +3806,10 @@ out: * * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160 */ -static int core_scsi3_pri_read_keys(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_keys(struct se_cmd *cmd) { - struct se_device *se_dev = cmd->se_dev; - struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; + struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; unsigned char *buf; u32 add_len = 0, off = 8; @@ -3968,18 +3817,20 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); - buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); - buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); - buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); - buf[3] = (su_dev->t10_pr.pr_generation & 0xff); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - spin_lock(&su_dev->t10_pr.registration_lock); - list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); + buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); + + spin_lock(&dev->t10_pr.registration_lock); + list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, pr_reg_list) { /* * Check for overflow of 8byte PRI READ_KEYS payload and @@ -3999,7 +3850,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) add_len += 8; } - spin_unlock(&su_dev->t10_pr.registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); buf[4] = ((add_len >> 24) & 0xff); buf[5] = ((add_len >> 16) & 0xff); @@ -4016,10 +3867,10 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) * * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162 */ -static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_reservation(struct se_cmd *cmd) { - struct se_device *se_dev = cmd->se_dev; - struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; + struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; unsigned char *buf; u64 pr_res_key; @@ -4028,18 +3879,20 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); - buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); - buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); - buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); - buf[3] = (su_dev->t10_pr.pr_generation & 0xff); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - spin_lock(&se_dev->dev_reservation_lock); - pr_reg = se_dev->dev_pr_res_holder; + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); + buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); + + spin_lock(&dev->dev_reservation_lock); + pr_reg = dev->dev_pr_res_holder; if (pr_reg) { /* * Set the hardcoded Additional Length @@ -4090,7 +3943,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) } err: - spin_unlock(&se_dev->dev_reservation_lock); + spin_unlock(&dev->dev_reservation_lock); transport_kunmap_data_sg(cmd); return 0; @@ -4101,21 +3954,23 @@ err: * * See spc4r17 section 6.13.4 Table 165 */ -static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_report_capabilities(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; u16 add_len = 8; /* Hardcoded to 8. */ if (cmd->data_length < 6) { pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" " %u too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((add_len << 8) & 0xff); buf[1] = (add_len & 0xff); @@ -4157,14 +4012,14 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) * * See spc4r17 section 6.13.5 Table 168 and 169 */ -static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_full_status(struct se_cmd *cmd) { - struct se_device *se_dev = cmd->se_dev; + struct se_device *dev = cmd->se_dev; struct se_node_acl *se_nacl; - struct se_subsystem_dev *su_dev = se_dev->se_sub_dev; struct se_portal_group *se_tpg; struct t10_pr_registration *pr_reg, *pr_reg_tmp; - struct t10_reservation *pr_tmpl = &se_dev->se_sub_dev->t10_pr; + struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; u32 off = 8; /* off into first Full Status descriptor */ @@ -4173,16 +4028,17 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); - buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); - buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); - buf[3] = (su_dev->t10_pr.pr_generation & 0xff); + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); + buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); spin_lock(&pr_tmpl->registration_lock); list_for_each_entry_safe(pr_reg, pr_reg_tmp, @@ -4303,9 +4159,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) return 0; } -int target_scsi3_emulate_pr_in(struct se_cmd *cmd) +sense_reason_t +target_scsi3_emulate_pr_in(struct se_cmd *cmd) { - int ret; + sense_reason_t ret; /* * Following spc2r20 5.5.1 Reservations overview: @@ -4316,12 +4173,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) * initiator or service action and shall terminate with a RESERVATION * CONFLICT status. */ - if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) { + if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) { pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } switch (cmd->t_task_cdb[1] & 0x1f) { @@ -4340,9 +4196,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) default: pr_err("Unknown PERSISTENT_RESERVE_IN service" " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } if (!ret) @@ -4350,56 +4204,25 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) return ret; } -static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type) -{ - return 0; -} - -static int core_pt_seq_non_holder( - struct se_cmd *cmd, - unsigned char *cdb, - u32 pr_reg_type) +sense_reason_t +target_check_reservation(struct se_cmd *cmd) { - return 0; -} + struct se_device *dev = cmd->se_dev; + sense_reason_t ret; -int core_setup_reservations(struct se_device *dev, int force_pt) -{ - struct se_subsystem_dev *su_dev = dev->se_sub_dev; - struct t10_reservation *rest = &su_dev->t10_pr; - /* - * If this device is from Target_Core_Mod/pSCSI, use the reservations - * of the Underlying SCSI hardware. In Linux/SCSI terms, this can - * cause a problem because libata and some SATA RAID HBAs appear - * under Linux/SCSI, but to emulate reservations themselves. - */ - if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) && - !(dev->se_sub_dev->se_dev_attrib.emulate_reservations)) || force_pt) { - rest->res_type = SPC_PASSTHROUGH; - rest->pr_ops.t10_reservation_check = &core_pt_reservation_check; - rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder; - pr_debug("%s: Using SPC_PASSTHROUGH, no reservation" - " emulation\n", dev->transport->name); + if (!cmd->se_sess) + return 0; + if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) + return 0; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; - } - /* - * If SPC-3 or above is reported by real or emulated struct se_device, - * use emulated Persistent Reservations. - */ - if (dev->transport->get_device_rev(dev) >= SCSI_3) { - rest->res_type = SPC3_PERSISTENT_RESERVATIONS; - rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check; - rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder; - pr_debug("%s: Using SPC3_PERSISTENT_RESERVATIONS" - " emulation\n", dev->transport->name); - } else { - rest->res_type = SPC2_RESERVATIONS; - rest->pr_ops.t10_reservation_check = &core_scsi2_reservation_check; - rest->pr_ops.t10_seq_non_holder = - &core_scsi2_reservation_seq_non_holder; - pr_debug("%s: Using SPC2_RESERVATIONS emulation\n", - dev->transport->name); - } - return 0; + spin_lock(&dev->dev_reservation_lock); + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + ret = target_scsi2_reservation_check(cmd); + else + ret = target_scsi3_pr_reservation_check(cmd); + spin_unlock(&dev->dev_reservation_lock); + + return ret; } |