Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target updates from Nicholas Bellinger:
"The highlights this round include:

- Add support for T10 PI pass-through between vhost-scsi +
virtio-scsi (MST + Paolo + MKP + nab)
- Add support for T10 PI in qla2xxx target mode (Quinn + MKP + hch +
nab, merged through scsi.git)
- Add support for percpu-ida pre-allocation in qla2xxx target code
(Quinn + nab)
- A number of iser-target fixes related to hardening the network
portal shutdown path (Sagi + Slava)
- Fix response length residual handling for a number of control CDBs
(Roland + Christophe V.)
- Various iscsi RFC conformance fixes in the CHAP authentication path
(Tejas and Calsoft folks + nab)
- Return TASK_SET_FULL status for tcm_fc(FCoE) DataIn + Response
failures (Vasu + Jun + nab)
- Fix long-standing ABORT_TASK + session reset hang (nab)
- Convert iser-initiator + iser-target to include T10 bytes into EDTL
(Sagi + Or + MKP + Mike Christie)
- Fix NULL pointer dereference regression related to XCOPY introduced
in v3.15 + CC'ed to v3.12.y (nab)"

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (34 commits)
target: Fix NULL pointer dereference for XCOPY in target_put_sess_cmd
vhost-scsi: Include prot_bytes into expected data transfer length
TARGET/sbc,loopback: Adjust command data length in case pi exists on the wire
libiscsi, iser: Adjust data_length to include protection information
scsi_cmnd: Introduce scsi_transfer_length helper
target: Report correct response length for some commands
target/sbc: Check that the LBA and number of blocks are correct in VERIFY
target/sbc: Remove sbc_check_valid_sectors()
Target/iscsi: Fix sendtargets response pdu for iser transport
Target/iser: Fix a wrong dereference in case discovery session is over iser
iscsi-target: Fix ABORT_TASK + connection reset iscsi_queue_req memory leak
target: Use complete_all for se_cmd->t_transport_stop_comp
target: Set CMD_T_ACTIVE bit for Task Management Requests
target: cleanup some boolean tests
target/spc: Simplify INQUIRY EVPD=0x80
tcm_fc: Generate TASK_SET_FULL status for response failures
tcm_fc: Generate TASK_SET_FULL status for DataIN failures
iscsi-target: Reject mutual authentication with reflected CHAP_C
iscsi-target: Remove no-op from iscsit_tpg_del_portal_group
iscsi-target: Fix CHAP_A parameter list handling
...

+732 -368
+10 -24
drivers/infiniband/ulp/iser/iser_initiator.c
··· 41 41 #include "iscsi_iser.h" 42 42 43 43 /* Register user buffer memory and initialize passive rdma 44 - * dto descriptor. Total data size is stored in 45 - * iser_task->data[ISER_DIR_IN].data_len 44 + * dto descriptor. Data size is stored in 45 + * task->data[ISER_DIR_IN].data_len, Protection size 46 + * os stored in task->prot[ISER_DIR_IN].data_len 46 47 */ 47 - static int iser_prepare_read_cmd(struct iscsi_task *task, 48 - unsigned int edtl) 48 + static int iser_prepare_read_cmd(struct iscsi_task *task) 49 49 50 50 { 51 51 struct iscsi_iser_task *iser_task = task->dd_data; ··· 73 73 return err; 74 74 } 75 75 76 - if (edtl > iser_task->data[ISER_DIR_IN].data_len) { 77 - iser_err("Total data length: %ld, less than EDTL: " 78 - "%d, in READ cmd BHS itt: %d, conn: 0x%p\n", 79 - iser_task->data[ISER_DIR_IN].data_len, edtl, 80 - task->itt, iser_task->ib_conn); 81 - return -EINVAL; 82 - } 83 - 84 76 err = device->iser_reg_rdma_mem(iser_task, ISER_DIR_IN); 85 77 if (err) { 86 78 iser_err("Failed to set up Data-IN RDMA\n"); ··· 92 100 } 93 101 94 102 /* Register user buffer memory and initialize passive rdma 95 - * dto descriptor. Total data size is stored in 96 - * task->data[ISER_DIR_OUT].data_len 103 + * dto descriptor. Data size is stored in 104 + * task->data[ISER_DIR_OUT].data_len, Protection size 105 + * is stored at task->prot[ISER_DIR_OUT].data_len 97 106 */ 98 107 static int 99 108 iser_prepare_write_cmd(struct iscsi_task *task, ··· 126 133 DMA_TO_DEVICE); 127 134 if (err) 128 135 return err; 129 - } 130 - 131 - if (edtl > iser_task->data[ISER_DIR_OUT].data_len) { 132 - iser_err("Total data length: %ld, less than EDTL: %d, " 133 - "in WRITE cmd BHS itt: %d, conn: 0x%p\n", 134 - iser_task->data[ISER_DIR_OUT].data_len, 135 - edtl, task->itt, task->conn); 136 - return -EINVAL; 137 136 } 138 137 139 138 err = device->iser_reg_rdma_mem(iser_task, ISER_DIR_OUT); ··· 402 417 if (scsi_prot_sg_count(sc)) { 403 418 prot_buf->buf = scsi_prot_sglist(sc); 404 419 prot_buf->size = scsi_prot_sg_count(sc); 405 - prot_buf->data_len = sc->prot_sdb->length; 420 + prot_buf->data_len = data_buf->data_len >> 421 + ilog2(sc->device->sector_size) * 8; 406 422 } 407 423 408 424 if (hdr->flags & ISCSI_FLAG_CMD_READ) { 409 - err = iser_prepare_read_cmd(task, edtl); 425 + err = iser_prepare_read_cmd(task); 410 426 if (err) 411 427 goto send_command_error; 412 428 }
+35 -35
drivers/infiniband/ulp/isert/ib_isert.c
··· 663 663 664 664 pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi; 665 665 if (pi_support && !device->pi_capable) { 666 - pr_err("Protection information requested but not supported\n"); 667 - ret = -EINVAL; 666 + pr_err("Protection information requested but not supported, " 667 + "rejecting connect request\n"); 668 + ret = rdma_reject(cma_id, NULL, 0); 668 669 goto out_mr; 669 670 } 670 671 ··· 788 787 isert_put_conn(isert_conn); 789 788 return; 790 789 } 791 - if (!isert_conn->logout_posted) { 792 - pr_debug("Calling rdma_disconnect for !logout_posted from" 793 - " isert_disconnect_work\n"); 790 + 791 + if (isert_conn->disconnect) { 792 + /* Send DREQ/DREP towards our initiator */ 794 793 rdma_disconnect(isert_conn->conn_cm_id); 795 - mutex_unlock(&isert_conn->conn_mutex); 796 - iscsit_cause_connection_reinstatement(isert_conn->conn, 0); 797 - goto wake_up; 798 794 } 795 + 799 796 mutex_unlock(&isert_conn->conn_mutex); 800 797 801 798 wake_up: ··· 802 803 } 803 804 804 805 static void 805 - isert_disconnected_handler(struct rdma_cm_id *cma_id) 806 + isert_disconnected_handler(struct rdma_cm_id *cma_id, bool disconnect) 806 807 { 807 808 struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context; 808 809 810 + isert_conn->disconnect = disconnect; 809 811 INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work); 810 812 schedule_work(&isert_conn->conn_logout_work); 811 813 } ··· 815 815 isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) 816 816 { 817 817 int ret = 0; 818 + bool disconnect = false; 818 819 819 820 pr_debug("isert_cma_handler: event %d status %d conn %p id %p\n", 820 821 event->event, event->status, cma_id->context, cma_id); 821 822 822 823 switch (event->event) { 823 824 case RDMA_CM_EVENT_CONNECT_REQUEST: 824 - pr_debug("RDMA_CM_EVENT_CONNECT_REQUEST: >>>>>>>>>>>>>>>\n"); 825 825 ret = isert_connect_request(cma_id, event); 826 826 break; 827 827 case RDMA_CM_EVENT_ESTABLISHED: 828 - pr_debug("RDMA_CM_EVENT_ESTABLISHED >>>>>>>>>>>>>>\n"); 829 828 isert_connected_handler(cma_id); 830 829 break; 831 - case RDMA_CM_EVENT_DISCONNECTED: 832 - pr_debug("RDMA_CM_EVENT_DISCONNECTED: >>>>>>>>>>>>>>\n"); 833 - isert_disconnected_handler(cma_id); 834 - break; 835 - case RDMA_CM_EVENT_DEVICE_REMOVAL: 836 - case RDMA_CM_EVENT_ADDR_CHANGE: 830 + case RDMA_CM_EVENT_ADDR_CHANGE: /* FALLTHRU */ 831 + case RDMA_CM_EVENT_DISCONNECTED: /* FALLTHRU */ 832 + case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */ 833 + disconnect = true; 834 + case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */ 835 + isert_disconnected_handler(cma_id, disconnect); 837 836 break; 838 837 case RDMA_CM_EVENT_CONNECT_ERROR: 839 838 default: 840 - pr_err("Unknown RDMA CMA event: %d\n", event->event); 839 + pr_err("Unhandled RDMA CMA event: %d\n", event->event); 841 840 break; 842 841 } 843 842 ··· 1053 1054 } 1054 1055 if (!login->login_failed) { 1055 1056 if (login->login_complete) { 1056 - if (isert_conn->conn_device->use_fastreg) { 1057 + if (!conn->sess->sess_ops->SessionType && 1058 + isert_conn->conn_device->use_fastreg) { 1059 + /* Normal Session and fastreg is used */ 1057 1060 u8 pi_support = login->np->tpg_np->tpg->tpg_attrib.t10_pi; 1058 1061 1059 1062 ret = isert_conn_create_fastreg_pool(isert_conn, ··· 1825 1824 break; 1826 1825 case ISTATE_SEND_LOGOUTRSP: 1827 1826 pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); 1828 - /* 1829 - * Call atomic_dec(&isert_conn->post_send_buf_count) 1830 - * from isert_wait_conn() 1831 - */ 1832 - isert_conn->logout_posted = true; 1827 + 1828 + atomic_dec(&isert_conn->post_send_buf_count); 1833 1829 iscsit_logout_post_handler(cmd, cmd->conn); 1834 1830 break; 1835 1831 case ISTATE_SEND_TEXTRSP: ··· 2031 2033 mutex_lock(&isert_conn->conn_mutex); 2032 2034 isert_conn->state = ISER_CONN_DOWN; 2033 2035 mutex_unlock(&isert_conn->conn_mutex); 2036 + 2037 + iscsit_cause_connection_reinstatement(isert_conn->conn, 0); 2034 2038 2035 2039 complete(&isert_conn->conn_wait_comp_err); 2036 2040 } ··· 2320 2320 int rc; 2321 2321 2322 2322 isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); 2323 - rc = iscsit_build_text_rsp(cmd, conn, hdr); 2323 + rc = iscsit_build_text_rsp(cmd, conn, hdr, ISCSI_INFINIBAND); 2324 2324 if (rc < 0) 2325 2325 return rc; 2326 2326 ··· 3156 3156 return -ENODEV; 3157 3157 3158 3158 spin_lock_bh(&np->np_thread_lock); 3159 - if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { 3159 + if (np->np_thread_state >= ISCSI_NP_THREAD_RESET) { 3160 3160 spin_unlock_bh(&np->np_thread_lock); 3161 - pr_debug("ISCSI_NP_THREAD_RESET for isert_accept_np\n"); 3161 + pr_debug("np_thread_state %d for isert_accept_np\n", 3162 + np->np_thread_state); 3163 + /** 3164 + * No point in stalling here when np_thread 3165 + * is in state RESET/SHUTDOWN/EXIT - bail 3166 + **/ 3162 3167 return -ENODEV; 3163 3168 } 3164 3169 spin_unlock_bh(&np->np_thread_lock); ··· 3213 3208 struct isert_conn *isert_conn = conn->context; 3214 3209 3215 3210 pr_debug("isert_wait_conn: Starting \n"); 3216 - /* 3217 - * Decrement post_send_buf_count for special case when called 3218 - * from isert_do_control_comp() -> iscsit_logout_post_handler() 3219 - */ 3220 - mutex_lock(&isert_conn->conn_mutex); 3221 - if (isert_conn->logout_posted) 3222 - atomic_dec(&isert_conn->post_send_buf_count); 3223 3211 3224 - if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) { 3212 + mutex_lock(&isert_conn->conn_mutex); 3213 + if (isert_conn->conn_cm_id) { 3225 3214 pr_debug("Calling rdma_disconnect from isert_wait_conn\n"); 3226 3215 rdma_disconnect(isert_conn->conn_cm_id); 3227 3216 } ··· 3292 3293 3293 3294 static void __exit isert_exit(void) 3294 3295 { 3296 + flush_scheduled_work(); 3295 3297 destroy_workqueue(isert_comp_wq); 3296 3298 destroy_workqueue(isert_rx_wq); 3297 3299 iscsit_unregister_transport(&iser_target_transport);
+1 -1
drivers/infiniband/ulp/isert/ib_isert.h
··· 116 116 117 117 struct isert_conn { 118 118 enum iser_conn_state state; 119 - bool logout_posted; 120 119 int post_recv_buf_count; 121 120 atomic_t post_send_buf_count; 122 121 u32 responder_resources; ··· 150 151 #define ISERT_COMP_BATCH_COUNT 8 151 152 int conn_comp_batch; 152 153 struct llist_head conn_comp_llist; 154 + bool disconnect; 153 155 }; 154 156 155 157 #define ISERT_MAX_CQ 64
+1
drivers/scsi/Kconfig
··· 1773 1773 config SCSI_VIRTIO 1774 1774 tristate "virtio-scsi support" 1775 1775 depends on VIRTIO 1776 + select BLK_DEV_INTEGRITY 1776 1777 help 1777 1778 This is the virtual HBA driver for virtio. If the kernel will 1778 1779 be used in a virtual machine, say Y or M.
+9 -9
drivers/scsi/libiscsi.c
··· 338 338 struct iscsi_session *session = conn->session; 339 339 struct scsi_cmnd *sc = task->sc; 340 340 struct iscsi_scsi_req *hdr; 341 - unsigned hdrlength, cmd_len; 341 + unsigned hdrlength, cmd_len, transfer_length; 342 342 itt_t itt; 343 343 int rc; 344 344 ··· 391 391 if (scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) 392 392 task->protected = true; 393 393 394 + transfer_length = scsi_transfer_length(sc); 395 + hdr->data_length = cpu_to_be32(transfer_length); 394 396 if (sc->sc_data_direction == DMA_TO_DEVICE) { 395 - unsigned out_len = scsi_out(sc)->length; 396 397 struct iscsi_r2t_info *r2t = &task->unsol_r2t; 397 398 398 - hdr->data_length = cpu_to_be32(out_len); 399 399 hdr->flags |= ISCSI_FLAG_CMD_WRITE; 400 400 /* 401 401 * Write counters: ··· 414 414 memset(r2t, 0, sizeof(*r2t)); 415 415 416 416 if (session->imm_data_en) { 417 - if (out_len >= session->first_burst) 417 + if (transfer_length >= session->first_burst) 418 418 task->imm_count = min(session->first_burst, 419 419 conn->max_xmit_dlength); 420 420 else 421 - task->imm_count = min(out_len, 422 - conn->max_xmit_dlength); 421 + task->imm_count = min(transfer_length, 422 + conn->max_xmit_dlength); 423 423 hton24(hdr->dlength, task->imm_count); 424 424 } else 425 425 zero_data(hdr->dlength); 426 426 427 427 if (!session->initial_r2t_en) { 428 - r2t->data_length = min(session->first_burst, out_len) - 428 + r2t->data_length = min(session->first_burst, 429 + transfer_length) - 429 430 task->imm_count; 430 431 r2t->data_offset = task->imm_count; 431 432 r2t->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); ··· 439 438 } else { 440 439 hdr->flags |= ISCSI_FLAG_CMD_FINAL; 441 440 zero_data(hdr->dlength); 442 - hdr->data_length = cpu_to_be32(scsi_in(sc)->length); 443 441 444 442 if (sc->sc_data_direction == DMA_FROM_DEVICE) 445 443 hdr->flags |= ISCSI_FLAG_CMD_READ; ··· 466 466 scsi_bidi_cmnd(sc) ? "bidirectional" : 467 467 sc->sc_data_direction == DMA_TO_DEVICE ? 468 468 "write" : "read", conn->id, sc, sc->cmnd[0], 469 - task->itt, scsi_bufflen(sc), 469 + task->itt, transfer_length, 470 470 scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, 471 471 session->cmdsn, 472 472 session->max_cmdsn - session->exp_cmdsn + 1);
+132 -65
drivers/scsi/qla2xxx/qla_target.c
··· 104 104 /* 105 105 * Global Variables 106 106 */ 107 - static struct kmem_cache *qla_tgt_cmd_cachep; 108 107 static struct kmem_cache *qla_tgt_mgmt_cmd_cachep; 109 108 static mempool_t *qla_tgt_mgmt_cmd_mempool; 110 109 static struct workqueue_struct *qla_tgt_wq; ··· 2704 2705 2705 2706 void qlt_free_cmd(struct qla_tgt_cmd *cmd) 2706 2707 { 2708 + struct qla_tgt_sess *sess = cmd->sess; 2709 + 2707 2710 ql_dbg(ql_dbg_tgt, cmd->vha, 0xe074, 2708 2711 "%s: se_cmd[%p] ox_id %04x\n", 2709 2712 __func__, &cmd->se_cmd, ··· 2714 2713 BUG_ON(cmd->sg_mapped); 2715 2714 if (unlikely(cmd->free_sg)) 2716 2715 kfree(cmd->sg); 2717 - kmem_cache_free(qla_tgt_cmd_cachep, cmd); 2716 + 2717 + if (!sess || !sess->se_sess) { 2718 + WARN_ON(1); 2719 + return; 2720 + } 2721 + percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); 2718 2722 } 2719 2723 EXPORT_SYMBOL(qlt_free_cmd); 2720 2724 ··· 3081 3075 /* 3082 3076 * Process context for I/O path into tcm_qla2xxx code 3083 3077 */ 3084 - static void qlt_do_work(struct work_struct *work) 3078 + static void __qlt_do_work(struct qla_tgt_cmd *cmd) 3085 3079 { 3086 - struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); 3087 3080 scsi_qla_host_t *vha = cmd->vha; 3088 3081 struct qla_hw_data *ha = vha->hw; 3089 3082 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; 3090 - struct qla_tgt_sess *sess = NULL; 3083 + struct qla_tgt_sess *sess = cmd->sess; 3091 3084 struct atio_from_isp *atio = &cmd->atio; 3092 3085 unsigned char *cdb; 3093 3086 unsigned long flags; ··· 3095 3090 3096 3091 if (tgt->tgt_stop) 3097 3092 goto out_term; 3098 - 3099 - spin_lock_irqsave(&ha->hardware_lock, flags); 3100 - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, 3101 - atio->u.isp24.fcp_hdr.s_id); 3102 - /* Do kref_get() before dropping qla_hw_data->hardware_lock. */ 3103 - if (sess) 3104 - kref_get(&sess->se_sess->sess_kref); 3105 - spin_unlock_irqrestore(&ha->hardware_lock, flags); 3106 - 3107 - if (unlikely(!sess)) { 3108 - uint8_t *s_id = atio->u.isp24.fcp_hdr.s_id; 3109 - 3110 - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, 3111 - "qla_target(%d): Unable to find wwn login" 3112 - " (s_id %x:%x:%x), trying to create it manually\n", 3113 - vha->vp_idx, s_id[0], s_id[1], s_id[2]); 3114 - 3115 - if (atio->u.raw.entry_count > 1) { 3116 - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, 3117 - "Dropping multy entry cmd %p\n", cmd); 3118 - goto out_term; 3119 - } 3120 - 3121 - mutex_lock(&vha->vha_tgt.tgt_mutex); 3122 - sess = qlt_make_local_sess(vha, s_id); 3123 - /* sess has an extra creation ref. */ 3124 - mutex_unlock(&vha->vha_tgt.tgt_mutex); 3125 - 3126 - if (!sess) 3127 - goto out_term; 3128 - } 3129 - 3130 - cmd->sess = sess; 3131 - cmd->loop_id = sess->loop_id; 3132 - cmd->conf_compl_supported = sess->conf_compl_supported; 3133 3093 3134 3094 cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; 3135 3095 cmd->tag = atio->u.isp24.exchange_addr; ··· 3123 3153 cmd, &cmd->se_cmd, cmd->unpacked_lun, cmd->tag, data_length, 3124 3154 cmd->atio.u.isp24.fcp_hdr.ox_id); 3125 3155 3126 - ret = vha->hw->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length, 3127 - fcp_task_attr, data_dir, bidi); 3156 + ret = ha->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length, 3157 + fcp_task_attr, data_dir, bidi); 3128 3158 if (ret != 0) 3129 3159 goto out_term; 3130 3160 /* ··· 3143 3173 */ 3144 3174 spin_lock_irqsave(&ha->hardware_lock, flags); 3145 3175 qlt_send_term_exchange(vha, NULL, &cmd->atio, 1); 3146 - kmem_cache_free(qla_tgt_cmd_cachep, cmd); 3147 - if (sess) 3148 - ha->tgt.tgt_ops->put_sess(sess); 3176 + percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); 3177 + ha->tgt.tgt_ops->put_sess(sess); 3149 3178 spin_unlock_irqrestore(&ha->hardware_lock, flags); 3179 + } 3180 + 3181 + static void qlt_do_work(struct work_struct *work) 3182 + { 3183 + struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); 3184 + 3185 + __qlt_do_work(cmd); 3186 + } 3187 + 3188 + static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, 3189 + struct qla_tgt_sess *sess, 3190 + struct atio_from_isp *atio) 3191 + { 3192 + struct se_session *se_sess = sess->se_sess; 3193 + struct qla_tgt_cmd *cmd; 3194 + int tag; 3195 + 3196 + tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); 3197 + if (tag < 0) 3198 + return NULL; 3199 + 3200 + cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; 3201 + memset(cmd, 0, sizeof(struct qla_tgt_cmd)); 3202 + 3203 + memcpy(&cmd->atio, atio, sizeof(*atio)); 3204 + cmd->state = QLA_TGT_STATE_NEW; 3205 + cmd->tgt = vha->vha_tgt.qla_tgt; 3206 + cmd->vha = vha; 3207 + cmd->se_cmd.map_tag = tag; 3208 + cmd->sess = sess; 3209 + cmd->loop_id = sess->loop_id; 3210 + cmd->conf_compl_supported = sess->conf_compl_supported; 3211 + 3212 + return cmd; 3213 + } 3214 + 3215 + static void qlt_send_busy(struct scsi_qla_host *, struct atio_from_isp *, 3216 + uint16_t); 3217 + 3218 + static void qlt_create_sess_from_atio(struct work_struct *work) 3219 + { 3220 + struct qla_tgt_sess_op *op = container_of(work, 3221 + struct qla_tgt_sess_op, work); 3222 + scsi_qla_host_t *vha = op->vha; 3223 + struct qla_hw_data *ha = vha->hw; 3224 + struct qla_tgt_sess *sess; 3225 + struct qla_tgt_cmd *cmd; 3226 + unsigned long flags; 3227 + uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id; 3228 + 3229 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, 3230 + "qla_target(%d): Unable to find wwn login" 3231 + " (s_id %x:%x:%x), trying to create it manually\n", 3232 + vha->vp_idx, s_id[0], s_id[1], s_id[2]); 3233 + 3234 + if (op->atio.u.raw.entry_count > 1) { 3235 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, 3236 + "Dropping multy entry atio %p\n", &op->atio); 3237 + goto out_term; 3238 + } 3239 + 3240 + mutex_lock(&vha->vha_tgt.tgt_mutex); 3241 + sess = qlt_make_local_sess(vha, s_id); 3242 + /* sess has an extra creation ref. */ 3243 + mutex_unlock(&vha->vha_tgt.tgt_mutex); 3244 + 3245 + if (!sess) 3246 + goto out_term; 3247 + /* 3248 + * Now obtain a pre-allocated session tag using the original op->atio 3249 + * packet header, and dispatch into __qlt_do_work() using the existing 3250 + * process context. 3251 + */ 3252 + cmd = qlt_get_tag(vha, sess, &op->atio); 3253 + if (!cmd) { 3254 + spin_lock_irqsave(&ha->hardware_lock, flags); 3255 + qlt_send_busy(vha, &op->atio, SAM_STAT_BUSY); 3256 + ha->tgt.tgt_ops->put_sess(sess); 3257 + spin_unlock_irqrestore(&ha->hardware_lock, flags); 3258 + kfree(op); 3259 + return; 3260 + } 3261 + /* 3262 + * __qlt_do_work() will call ha->tgt.tgt_ops->put_sess() to release 3263 + * the extra reference taken above by qlt_make_local_sess() 3264 + */ 3265 + __qlt_do_work(cmd); 3266 + kfree(op); 3267 + return; 3268 + 3269 + out_term: 3270 + spin_lock_irqsave(&ha->hardware_lock, flags); 3271 + qlt_send_term_exchange(vha, NULL, &op->atio, 1); 3272 + spin_unlock_irqrestore(&ha->hardware_lock, flags); 3273 + kfree(op); 3274 + 3150 3275 } 3151 3276 3152 3277 /* ha->hardware_lock supposed to be held on entry */ 3153 3278 static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, 3154 3279 struct atio_from_isp *atio) 3155 3280 { 3281 + struct qla_hw_data *ha = vha->hw; 3156 3282 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; 3283 + struct qla_tgt_sess *sess; 3157 3284 struct qla_tgt_cmd *cmd; 3158 3285 3159 3286 if (unlikely(tgt->tgt_stop)) { ··· 3259 3192 return -EFAULT; 3260 3193 } 3261 3194 3262 - cmd = kmem_cache_zalloc(qla_tgt_cmd_cachep, GFP_ATOMIC); 3195 + sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id); 3196 + if (unlikely(!sess)) { 3197 + struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op), 3198 + GFP_ATOMIC); 3199 + if (!op) 3200 + return -ENOMEM; 3201 + 3202 + memcpy(&op->atio, atio, sizeof(*atio)); 3203 + INIT_WORK(&op->work, qlt_create_sess_from_atio); 3204 + queue_work(qla_tgt_wq, &op->work); 3205 + return 0; 3206 + } 3207 + /* 3208 + * Do kref_get() before returning + dropping qla_hw_data->hardware_lock. 3209 + */ 3210 + kref_get(&sess->se_sess->sess_kref); 3211 + 3212 + cmd = qlt_get_tag(vha, sess, atio); 3263 3213 if (!cmd) { 3264 3214 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05e, 3265 3215 "qla_target(%d): Allocation of cmd failed\n", vha->vp_idx); 3216 + ha->tgt.tgt_ops->put_sess(sess); 3266 3217 return -ENOMEM; 3267 3218 } 3268 - 3269 - memcpy(&cmd->atio, atio, sizeof(*atio)); 3270 - cmd->state = QLA_TGT_STATE_NEW; 3271 - cmd->tgt = vha->vha_tgt.qla_tgt; 3272 - cmd->vha = vha; 3273 3219 3274 3220 INIT_WORK(&cmd->work, qlt_do_work); 3275 3221 queue_work(qla_tgt_wq, &cmd->work); ··· 5581 5501 if (!QLA_TGT_MODE_ENABLED()) 5582 5502 return 0; 5583 5503 5584 - qla_tgt_cmd_cachep = kmem_cache_create("qla_tgt_cmd_cachep", 5585 - sizeof(struct qla_tgt_cmd), __alignof__(struct qla_tgt_cmd), 0, 5586 - NULL); 5587 - if (!qla_tgt_cmd_cachep) { 5588 - ql_log(ql_log_fatal, NULL, 0xe06c, 5589 - "kmem_cache_create for qla_tgt_cmd_cachep failed\n"); 5590 - return -ENOMEM; 5591 - } 5592 - 5593 5504 qla_tgt_mgmt_cmd_cachep = kmem_cache_create("qla_tgt_mgmt_cmd_cachep", 5594 5505 sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct 5595 5506 qla_tgt_mgmt_cmd), 0, NULL); 5596 5507 if (!qla_tgt_mgmt_cmd_cachep) { 5597 5508 ql_log(ql_log_fatal, NULL, 0xe06d, 5598 5509 "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n"); 5599 - ret = -ENOMEM; 5600 - goto out; 5510 + return -ENOMEM; 5601 5511 } 5602 5512 5603 5513 qla_tgt_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab, ··· 5615 5545 mempool_destroy(qla_tgt_mgmt_cmd_mempool); 5616 5546 out_mgmt_cmd_cachep: 5617 5547 kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep); 5618 - out: 5619 - kmem_cache_destroy(qla_tgt_cmd_cachep); 5620 5548 return ret; 5621 5549 } 5622 5550 ··· 5626 5558 destroy_workqueue(qla_tgt_wq); 5627 5559 mempool_destroy(qla_tgt_mgmt_cmd_mempool); 5628 5560 kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep); 5629 - kmem_cache_destroy(qla_tgt_cmd_cachep); 5630 5561 }
+6
drivers/scsi/qla2xxx/qla_target.h
··· 870 870 struct list_head tgt_list_entry; 871 871 }; 872 872 873 + struct qla_tgt_sess_op { 874 + struct scsi_qla_host *vha; 875 + struct atio_from_isp atio; 876 + struct work_struct work; 877 + }; 878 + 873 879 /* 874 880 * Equivilant to IT Nexus (Initiator-Target) 875 881 */
+5 -1
drivers/scsi/qla2xxx/tcm_qla2xxx.c
··· 1501 1501 struct qla_tgt_sess *sess = qla_tgt_sess; 1502 1502 unsigned char port_name[36]; 1503 1503 unsigned long flags; 1504 + int num_tags = (ha->fw_xcb_count) ? ha->fw_xcb_count : 1505 + TCM_QLA2XXX_DEFAULT_TAGS; 1504 1506 1505 1507 lport = vha->vha_tgt.target_lport_ptr; 1506 1508 if (!lport) { ··· 1520 1518 } 1521 1519 se_tpg = &tpg->se_tpg; 1522 1520 1523 - se_sess = transport_init_session(TARGET_PROT_NORMAL); 1521 + se_sess = transport_init_session_tags(num_tags, 1522 + sizeof(struct qla_tgt_cmd), 1523 + TARGET_PROT_NORMAL); 1524 1524 if (IS_ERR(se_sess)) { 1525 1525 pr_err("Unable to initialize struct se_session\n"); 1526 1526 return PTR_ERR(se_sess);
+5
drivers/scsi/qla2xxx/tcm_qla2xxx.h
··· 4 4 #define TCM_QLA2XXX_VERSION "v0.1" 5 5 /* length of ASCII WWPNs including pad */ 6 6 #define TCM_QLA2XXX_NAMELEN 32 7 + /* 8 + * Number of pre-allocated per-session tags, based upon the worst-case 9 + * per port number of iocbs 10 + */ 11 + #define TCM_QLA2XXX_DEFAULT_TAGS 2088 7 12 8 13 #include "qla_target.h" 9 14
+69 -17
drivers/scsi/virtio_scsi.c
··· 23 23 #include <linux/virtio_config.h> 24 24 #include <linux/virtio_scsi.h> 25 25 #include <linux/cpu.h> 26 + #include <linux/blkdev.h> 26 27 #include <scsi/scsi_host.h> 27 28 #include <scsi/scsi_device.h> 28 29 #include <scsi/scsi_cmnd.h> ··· 38 37 struct completion *comp; 39 38 union { 40 39 struct virtio_scsi_cmd_req cmd; 40 + struct virtio_scsi_cmd_req_pi cmd_pi; 41 41 struct virtio_scsi_ctrl_tmf_req tmf; 42 42 struct virtio_scsi_ctrl_an_req an; 43 43 } req; ··· 401 399 size_t req_size, size_t resp_size) 402 400 { 403 401 struct scsi_cmnd *sc = cmd->sc; 404 - struct scatterlist *sgs[4], req, resp; 402 + struct scatterlist *sgs[6], req, resp; 405 403 struct sg_table *out, *in; 406 404 unsigned out_num = 0, in_num = 0; 407 405 ··· 419 417 sgs[out_num++] = &req; 420 418 421 419 /* Data-out buffer. */ 422 - if (out) 420 + if (out) { 421 + /* Place WRITE protection SGLs before Data OUT payload */ 422 + if (scsi_prot_sg_count(sc)) 423 + sgs[out_num++] = scsi_prot_sglist(sc); 423 424 sgs[out_num++] = out->sgl; 425 + } 424 426 425 427 /* Response header. */ 426 428 sg_init_one(&resp, &cmd->resp, resp_size); 427 429 sgs[out_num + in_num++] = &resp; 428 430 429 431 /* Data-in buffer */ 430 - if (in) 432 + if (in) { 433 + /* Place READ protection SGLs before Data IN payload */ 434 + if (scsi_prot_sg_count(sc)) 435 + sgs[out_num + in_num++] = scsi_prot_sglist(sc); 431 436 sgs[out_num + in_num++] = in->sgl; 437 + } 432 438 433 439 return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_ATOMIC); 434 440 } ··· 461 451 return err; 462 452 } 463 453 454 + static void virtio_scsi_init_hdr(struct virtio_scsi_cmd_req *cmd, 455 + struct scsi_cmnd *sc) 456 + { 457 + cmd->lun[0] = 1; 458 + cmd->lun[1] = sc->device->id; 459 + cmd->lun[2] = (sc->device->lun >> 8) | 0x40; 460 + cmd->lun[3] = sc->device->lun & 0xff; 461 + cmd->tag = (unsigned long)sc; 462 + cmd->task_attr = VIRTIO_SCSI_S_SIMPLE; 463 + cmd->prio = 0; 464 + cmd->crn = 0; 465 + } 466 + 467 + static void virtio_scsi_init_hdr_pi(struct virtio_scsi_cmd_req_pi *cmd_pi, 468 + struct scsi_cmnd *sc) 469 + { 470 + struct request *rq = sc->request; 471 + struct blk_integrity *bi; 472 + 473 + virtio_scsi_init_hdr((struct virtio_scsi_cmd_req *)cmd_pi, sc); 474 + 475 + if (!rq || !scsi_prot_sg_count(sc)) 476 + return; 477 + 478 + bi = blk_get_integrity(rq->rq_disk); 479 + 480 + if (sc->sc_data_direction == DMA_TO_DEVICE) 481 + cmd_pi->pi_bytesout = blk_rq_sectors(rq) * bi->tuple_size; 482 + else if (sc->sc_data_direction == DMA_FROM_DEVICE) 483 + cmd_pi->pi_bytesin = blk_rq_sectors(rq) * bi->tuple_size; 484 + } 485 + 464 486 static int virtscsi_queuecommand(struct virtio_scsi *vscsi, 465 487 struct virtio_scsi_vq *req_vq, 466 488 struct scsi_cmnd *sc) 467 489 { 468 490 struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); 469 491 struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc); 492 + int req_size; 470 493 471 494 BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); 472 495 ··· 511 468 512 469 memset(cmd, 0, sizeof(*cmd)); 513 470 cmd->sc = sc; 514 - cmd->req.cmd = (struct virtio_scsi_cmd_req){ 515 - .lun[0] = 1, 516 - .lun[1] = sc->device->id, 517 - .lun[2] = (sc->device->lun >> 8) | 0x40, 518 - .lun[3] = sc->device->lun & 0xff, 519 - .tag = (unsigned long)sc, 520 - .task_attr = VIRTIO_SCSI_S_SIMPLE, 521 - .prio = 0, 522 - .crn = 0, 523 - }; 524 471 525 472 BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); 526 - memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); 527 473 528 - if (virtscsi_kick_cmd(req_vq, cmd, 529 - sizeof cmd->req.cmd, sizeof cmd->resp.cmd) != 0) 474 + if (virtio_has_feature(vscsi->vdev, VIRTIO_SCSI_F_T10_PI)) { 475 + virtio_scsi_init_hdr_pi(&cmd->req.cmd_pi, sc); 476 + memcpy(cmd->req.cmd_pi.cdb, sc->cmnd, sc->cmd_len); 477 + req_size = sizeof(cmd->req.cmd_pi); 478 + } else { 479 + virtio_scsi_init_hdr(&cmd->req.cmd, sc); 480 + memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); 481 + req_size = sizeof(cmd->req.cmd); 482 + } 483 + 484 + if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)) != 0) 530 485 return SCSI_MLQUEUE_HOST_BUSY; 531 486 return 0; 532 487 } ··· 861 820 { 862 821 struct Scsi_Host *shost; 863 822 struct virtio_scsi *vscsi; 864 - int err; 823 + int err, host_prot; 865 824 u32 sg_elems, num_targets; 866 825 u32 cmd_per_lun; 867 826 u32 num_queues; ··· 911 870 shost->max_id = num_targets; 912 871 shost->max_channel = 0; 913 872 shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE; 873 + 874 + if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) { 875 + host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | 876 + SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | 877 + SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION; 878 + 879 + scsi_host_set_prot(shost, host_prot); 880 + scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); 881 + } 882 + 914 883 err = scsi_add_host(shost, &vdev->dev); 915 884 if (err) 916 885 goto scsi_add_host_failed; ··· 990 939 static unsigned int features[] = { 991 940 VIRTIO_SCSI_F_HOTPLUG, 992 941 VIRTIO_SCSI_F_CHANGE, 942 + VIRTIO_SCSI_F_T10_PI, 993 943 }; 994 944 995 945 static struct virtio_driver virtio_scsi_driver = {
+16 -13
drivers/target/iscsi/iscsi_target.c
··· 300 300 port = ntohs(sock_in->sin_port); 301 301 } 302 302 303 - if ((ip_match == true) && (np->np_port == port) && 303 + if (ip_match && (np->np_port == port) && 304 304 (np->np_network_transport == network_transport)) 305 305 return true; 306 306 ··· 325 325 } 326 326 327 327 match = iscsit_check_np_match(sockaddr, np, network_transport); 328 - if (match == true) { 328 + if (match) { 329 329 /* 330 330 * Increment the np_exports reference count now to 331 331 * prevent iscsit_del_np() below from being called ··· 1121 1121 /* 1122 1122 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes. 1123 1123 */ 1124 - if (dump_payload == true) 1124 + if (dump_payload) 1125 1125 goto after_immediate_data; 1126 1126 1127 1127 immed_ret = iscsit_handle_immediate_data(cmd, hdr, ··· 3390 3390 3391 3391 #define SENDTARGETS_BUF_LIMIT 32768U 3392 3392 3393 - static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) 3393 + static int 3394 + iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, 3395 + enum iscsit_transport_type network_transport) 3394 3396 { 3395 3397 char *payload = NULL; 3396 3398 struct iscsi_conn *conn = cmd->conn; ··· 3469 3467 struct iscsi_np *np = tpg_np->tpg_np; 3470 3468 bool inaddr_any = iscsit_check_inaddr_any(np); 3471 3469 3470 + if (np->np_network_transport != network_transport) 3471 + continue; 3472 + 3472 3473 if (!target_name_printed) { 3473 3474 len = sprintf(buf, "TargetName=%s", 3474 3475 tiqn->tiqn); ··· 3490 3485 3491 3486 len = sprintf(buf, "TargetAddress=" 3492 3487 "%s:%hu,%hu", 3493 - (inaddr_any == false) ? 3494 - np->np_ip : conn->local_ip, 3495 - (inaddr_any == false) ? 3496 - np->np_port : conn->local_port, 3488 + inaddr_any ? conn->local_ip : np->np_ip, 3489 + inaddr_any ? conn->local_port : np->np_port, 3497 3490 tpg->tpgt); 3498 3491 len += 1; 3499 3492 ··· 3523 3520 3524 3521 int 3525 3522 iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, 3526 - struct iscsi_text_rsp *hdr) 3523 + struct iscsi_text_rsp *hdr, 3524 + enum iscsit_transport_type network_transport) 3527 3525 { 3528 3526 int text_length, padding; 3529 3527 3530 - text_length = iscsit_build_sendtargets_response(cmd); 3528 + text_length = iscsit_build_sendtargets_response(cmd, network_transport); 3531 3529 if (text_length < 0) 3532 3530 return text_length; 3533 3531 ··· 3566 3562 u32 tx_size = 0; 3567 3563 int text_length, iov_count = 0, rc; 3568 3564 3569 - rc = iscsit_build_text_rsp(cmd, conn, hdr); 3565 + rc = iscsit_build_text_rsp(cmd, conn, hdr, ISCSI_TCP); 3570 3566 if (rc < 0) 3571 3567 return rc; 3572 3568 ··· 4238 4234 if (conn->conn_transport->iscsit_wait_conn) 4239 4235 conn->conn_transport->iscsit_wait_conn(conn); 4240 4236 4241 - iscsit_free_queue_reqs_for_conn(conn); 4242 - 4243 4237 /* 4244 4238 * During Connection recovery drop unacknowledged out of order 4245 4239 * commands for this connection, and prepare the other commands ··· 4254 4252 iscsit_clear_ooo_cmdsns_for_conn(conn); 4255 4253 iscsit_release_commands_from_conn(conn); 4256 4254 } 4255 + iscsit_free_queue_reqs_for_conn(conn); 4257 4256 4258 4257 /* 4259 4258 * Handle decrementing session or connection usage count if
+61 -13
drivers/target/iscsi/iscsi_target_auth.c
··· 71 71 challenge_asciihex); 72 72 } 73 73 74 + static int chap_check_algorithm(const char *a_str) 75 + { 76 + char *tmp, *orig, *token; 77 + 78 + tmp = kstrdup(a_str, GFP_KERNEL); 79 + if (!tmp) { 80 + pr_err("Memory allocation failed for CHAP_A temporary buffer\n"); 81 + return CHAP_DIGEST_UNKNOWN; 82 + } 83 + orig = tmp; 84 + 85 + token = strsep(&tmp, "="); 86 + if (!token) 87 + goto out; 88 + 89 + if (strcmp(token, "CHAP_A")) { 90 + pr_err("Unable to locate CHAP_A key\n"); 91 + goto out; 92 + } 93 + while (token) { 94 + token = strsep(&tmp, ","); 95 + if (!token) 96 + goto out; 97 + 98 + if (!strncmp(token, "5", 1)) { 99 + pr_debug("Selected MD5 Algorithm\n"); 100 + kfree(orig); 101 + return CHAP_DIGEST_MD5; 102 + } 103 + } 104 + out: 105 + kfree(orig); 106 + return CHAP_DIGEST_UNKNOWN; 107 + } 74 108 75 109 static struct iscsi_chap *chap_server_open( 76 110 struct iscsi_conn *conn, ··· 113 79 char *aic_str, 114 80 unsigned int *aic_len) 115 81 { 82 + int ret; 116 83 struct iscsi_chap *chap; 117 84 118 85 if (!(auth->naf_flags & NAF_USERID_SET) || ··· 128 93 return NULL; 129 94 130 95 chap = conn->auth_protocol; 131 - /* 132 - * We only support MD5 MDA presently. 133 - */ 134 - if (strncmp(a_str, "CHAP_A=5", 8)) { 135 - pr_err("CHAP_A is not MD5.\n"); 96 + ret = chap_check_algorithm(a_str); 97 + switch (ret) { 98 + case CHAP_DIGEST_MD5: 99 + pr_debug("[server] Got CHAP_A=5\n"); 100 + /* 101 + * Send back CHAP_A set to MD5. 102 + */ 103 + *aic_len = sprintf(aic_str, "CHAP_A=5"); 104 + *aic_len += 1; 105 + chap->digest_type = CHAP_DIGEST_MD5; 106 + pr_debug("[server] Sending CHAP_A=%d\n", chap->digest_type); 107 + break; 108 + case CHAP_DIGEST_UNKNOWN: 109 + default: 110 + pr_err("Unsupported CHAP_A value\n"); 136 111 return NULL; 137 112 } 138 - pr_debug("[server] Got CHAP_A=5\n"); 139 - /* 140 - * Send back CHAP_A set to MD5. 141 - */ 142 - *aic_len = sprintf(aic_str, "CHAP_A=5"); 143 - *aic_len += 1; 144 - chap->digest_type = CHAP_DIGEST_MD5; 145 - pr_debug("[server] Sending CHAP_A=%d\n", chap->digest_type); 113 + 146 114 /* 147 115 * Set Identifier. 148 116 */ ··· 349 311 strlen(challenge)); 350 312 if (!challenge_len) { 351 313 pr_err("Unable to convert incoming challenge\n"); 314 + goto out; 315 + } 316 + /* 317 + * During mutual authentication, the CHAP_C generated by the 318 + * initiator must not match the original CHAP_C generated by 319 + * the target. 320 + */ 321 + if (!memcmp(challenge_binhex, chap->challenge, CHAP_CHALLENGE_LENGTH)) { 322 + pr_err("initiator CHAP_C matches target CHAP_C, failing" 323 + " login attempt\n"); 352 324 goto out; 353 325 } 354 326 /*
+1
drivers/target/iscsi/iscsi_target_auth.h
··· 1 1 #ifndef _ISCSI_CHAP_H_ 2 2 #define _ISCSI_CHAP_H_ 3 3 4 + #define CHAP_DIGEST_UNKNOWN 0 4 5 #define CHAP_DIGEST_MD5 5 5 6 #define CHAP_DIGEST_SHA 6 6 7
+1 -1
drivers/target/iscsi/iscsi_target_login.c
··· 1145 1145 void iscsi_target_login_sess_out(struct iscsi_conn *conn, 1146 1146 struct iscsi_np *np, bool zero_tsih, bool new_sess) 1147 1147 { 1148 - if (new_sess == false) 1148 + if (!new_sess) 1149 1149 goto old_sess_out; 1150 1150 1151 1151 pr_err("iSCSI Login negotiation failed.\n");
+9 -3
drivers/target/iscsi/iscsi_target_nego.c
··· 404 404 } 405 405 406 406 rc = schedule_delayed_work(&conn->login_work, 0); 407 - if (rc == false) { 407 + if (!rc) { 408 408 pr_debug("iscsi_target_sk_data_ready, schedule_delayed_work" 409 409 " got false\n"); 410 410 } ··· 513 513 state = (tpg->tpg_state == TPG_STATE_ACTIVE); 514 514 spin_unlock(&tpg->tpg_state_lock); 515 515 516 - if (state == false) { 516 + if (!state) { 517 517 pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n"); 518 518 iscsi_target_restore_sock_callbacks(conn); 519 519 iscsi_target_login_drop(conn, login); ··· 528 528 state = iscsi_target_sk_state_check(sk); 529 529 read_unlock_bh(&sk->sk_callback_lock); 530 530 531 - if (state == false) { 531 + if (!state) { 532 532 pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); 533 533 iscsi_target_restore_sock_callbacks(conn); 534 534 iscsi_target_login_drop(conn, login); ··· 773 773 } 774 774 775 775 goto do_auth; 776 + } else if (!payload_length) { 777 + pr_err("Initiator sent zero length security payload," 778 + " login failed\n"); 779 + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, 780 + ISCSI_LOGIN_STATUS_AUTH_FAILED); 781 + return -1; 776 782 } 777 783 778 784 if (login->first_request)
+7 -7
drivers/target/iscsi/iscsi_target_parameters.c
··· 474 474 if (!strcmp(param->name, AUTHMETHOD)) { 475 475 SET_PSTATE_NEGOTIATE(param); 476 476 } else if (!strcmp(param->name, HEADERDIGEST)) { 477 - if (iser == false) 477 + if (!iser) 478 478 SET_PSTATE_NEGOTIATE(param); 479 479 } else if (!strcmp(param->name, DATADIGEST)) { 480 - if (iser == false) 480 + if (!iser) 481 481 SET_PSTATE_NEGOTIATE(param); 482 482 } else if (!strcmp(param->name, MAXCONNECTIONS)) { 483 483 SET_PSTATE_NEGOTIATE(param); ··· 497 497 } else if (!strcmp(param->name, IMMEDIATEDATA)) { 498 498 SET_PSTATE_NEGOTIATE(param); 499 499 } else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) { 500 - if (iser == false) 500 + if (!iser) 501 501 SET_PSTATE_NEGOTIATE(param); 502 502 } else if (!strcmp(param->name, MAXXMITDATASEGMENTLENGTH)) { 503 503 continue; ··· 528 528 } else if (!strcmp(param->name, OFMARKINT)) { 529 529 SET_PSTATE_NEGOTIATE(param); 530 530 } else if (!strcmp(param->name, RDMAEXTENSIONS)) { 531 - if (iser == true) 531 + if (iser) 532 532 SET_PSTATE_NEGOTIATE(param); 533 533 } else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) { 534 - if (iser == true) 534 + if (iser) 535 535 SET_PSTATE_NEGOTIATE(param); 536 536 } else if (!strcmp(param->name, TARGETRECVDATASEGMENTLENGTH)) { 537 - if (iser == true) 537 + if (iser) 538 538 SET_PSTATE_NEGOTIATE(param); 539 539 } 540 540 } ··· 1605 1605 1606 1606 tmpbuf = kzalloc(length + 1, GFP_KERNEL); 1607 1607 if (!tmpbuf) { 1608 - pr_err("Unable to allocate memory for tmpbuf.\n"); 1608 + pr_err("Unable to allocate %u + 1 bytes for tmpbuf.\n", length); 1609 1609 return -1; 1610 1610 } 1611 1611
+3 -5
drivers/target/iscsi/iscsi_target_tpg.c
··· 189 189 iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown); 190 190 } 191 191 192 - void iscsit_clear_tpg_np_login_threads( 192 + static void iscsit_clear_tpg_np_login_threads( 193 193 struct iscsi_portal_group *tpg, 194 194 bool shutdown) 195 195 { ··· 275 275 spin_lock(&tpg->tpg_state_lock); 276 276 tpg->tpg_state = TPG_STATE_INACTIVE; 277 277 spin_unlock(&tpg->tpg_state_lock); 278 - 279 - iscsit_clear_tpg_np_login_threads(tpg, true); 280 278 281 279 if (iscsit_release_sessions_for_tpg(tpg, force) < 0) { 282 280 pr_err("Unable to delete iSCSI Target Portal Group:" ··· 451 453 452 454 match = iscsit_check_np_match(sockaddr, np, 453 455 network_transport); 454 - if (match == true) 456 + if (match) 455 457 break; 456 458 } 457 459 spin_unlock(&tpg->tpg_np_lock); ··· 473 475 474 476 if (!tpg_np_parent) { 475 477 if (iscsit_tpg_check_network_portal(tpg->tpg_tiqn, sockaddr, 476 - network_transport) == true) { 478 + network_transport)) { 477 479 pr_err("Network Portal: %s already exists on a" 478 480 " different TPG on %s\n", ip_str, 479 481 tpg->tpg_tiqn->tiqn);
-1
drivers/target/iscsi/iscsi_target_tpg.h
··· 8 8 struct iscsi_np *, struct iscsi_tpg_np **); 9 9 extern int iscsit_get_tpg(struct iscsi_portal_group *); 10 10 extern void iscsit_put_tpg(struct iscsi_portal_group *); 11 - extern void iscsit_clear_tpg_np_login_threads(struct iscsi_portal_group *, bool); 12 11 extern void iscsit_tpg_dump_params(struct iscsi_portal_group *); 13 12 extern int iscsit_tpg_add_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *); 14 13 extern int iscsit_tpg_del_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *,
+12 -3
drivers/target/loopback/tcm_loop.c
··· 179 179 struct tcm_loop_hba *tl_hba; 180 180 struct tcm_loop_tpg *tl_tpg; 181 181 struct scatterlist *sgl_bidi = NULL; 182 - u32 sgl_bidi_count = 0; 182 + u32 sgl_bidi_count = 0, transfer_length; 183 183 int rc; 184 184 185 185 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); ··· 213 213 214 214 } 215 215 216 - if (!scsi_prot_sg_count(sc) && scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) 216 + transfer_length = scsi_transfer_length(sc); 217 + if (!scsi_prot_sg_count(sc) && 218 + scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) { 217 219 se_cmd->prot_pto = true; 220 + /* 221 + * loopback transport doesn't support 222 + * WRITE_GENERATE, READ_STRIP protection 223 + * information operations, go ahead unprotected. 224 + */ 225 + transfer_length = scsi_bufflen(sc); 226 + } 218 227 219 228 rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd, 220 229 &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun, 221 - scsi_bufflen(sc), tcm_loop_sam_attr(sc), 230 + transfer_length, tcm_loop_sam_attr(sc), 222 231 sc->sc_data_direction, 0, 223 232 scsi_sglist(sc), scsi_sg_count(sc), 224 233 sgl_bidi, sgl_bidi_count,
+24 -44
drivers/target/target_core_sbc.c
··· 81 81 transport_kunmap_data_sg(cmd); 82 82 } 83 83 84 - target_complete_cmd(cmd, GOOD); 84 + target_complete_cmd_with_length(cmd, GOOD, 8); 85 85 return 0; 86 86 } 87 87 ··· 137 137 transport_kunmap_data_sg(cmd); 138 138 } 139 139 140 - target_complete_cmd(cmd, GOOD); 140 + target_complete_cmd_with_length(cmd, GOOD, 32); 141 141 return 0; 142 142 } 143 143 ··· 174 174 static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) 175 175 { 176 176 return cmd->se_dev->dev_attrib.block_size * sectors; 177 - } 178 - 179 - static int sbc_check_valid_sectors(struct se_cmd *cmd) 180 - { 181 - struct se_device *dev = cmd->se_dev; 182 - unsigned long long end_lba; 183 - u32 sectors; 184 - 185 - sectors = cmd->data_length / dev->dev_attrib.block_size; 186 - end_lba = dev->transport->get_blocks(dev) + 1; 187 - 188 - if (cmd->t_task_lba + sectors > end_lba) { 189 - pr_err("target: lba %llu, sectors %u exceeds end lba %llu\n", 190 - cmd->t_task_lba, sectors, end_lba); 191 - return -EINVAL; 192 - } 193 - 194 - return 0; 195 177 } 196 178 197 179 static inline u32 transport_get_sectors_6(unsigned char *cdb) ··· 647 665 648 666 cmd->prot_type = dev->dev_attrib.pi_prot_type; 649 667 cmd->prot_length = dev->prot_length * sectors; 650 - pr_debug("%s: prot_type=%d, prot_length=%d prot_op=%d prot_checks=%d\n", 651 - __func__, cmd->prot_type, cmd->prot_length, 668 + 669 + /** 670 + * In case protection information exists over the wire 671 + * we modify command data length to describe pure data. 672 + * The actual transfer length is data length + protection 673 + * length 674 + **/ 675 + if (protect) 676 + cmd->data_length = sectors * dev->dev_attrib.block_size; 677 + 678 + pr_debug("%s: prot_type=%d, data_length=%d, prot_length=%d " 679 + "prot_op=%d prot_checks=%d\n", 680 + __func__, cmd->prot_type, cmd->data_length, cmd->prot_length, 652 681 cmd->prot_op, cmd->prot_checks); 653 682 654 683 return true; ··· 870 877 break; 871 878 case SYNCHRONIZE_CACHE: 872 879 case SYNCHRONIZE_CACHE_16: 873 - if (!ops->execute_sync_cache) { 874 - size = 0; 875 - cmd->execute_cmd = sbc_emulate_noop; 876 - break; 877 - } 878 - 879 - /* 880 - * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE 881 - */ 882 880 if (cdb[0] == SYNCHRONIZE_CACHE) { 883 881 sectors = transport_get_sectors_10(cdb); 884 882 cmd->t_task_lba = transport_lba_32(cdb); ··· 877 893 sectors = transport_get_sectors_16(cdb); 878 894 cmd->t_task_lba = transport_lba_64(cdb); 879 895 } 880 - 881 - size = sbc_get_size(cmd, sectors); 882 - 883 - /* 884 - * Check to ensure that LBA + Range does not exceed past end of 885 - * device for IBLOCK and FILEIO ->do_sync_cache() backend calls 886 - */ 887 - if (cmd->t_task_lba || sectors) { 888 - if (sbc_check_valid_sectors(cmd) < 0) 889 - return TCM_ADDRESS_OUT_OF_RANGE; 896 + if (ops->execute_sync_cache) { 897 + cmd->execute_cmd = ops->execute_sync_cache; 898 + goto check_lba; 890 899 } 891 - cmd->execute_cmd = ops->execute_sync_cache; 900 + size = 0; 901 + cmd->execute_cmd = sbc_emulate_noop; 892 902 break; 893 903 case UNMAP: 894 904 if (!ops->execute_unmap) ··· 925 947 break; 926 948 case VERIFY: 927 949 size = 0; 950 + sectors = transport_get_sectors_10(cdb); 951 + cmd->t_task_lba = transport_lba_32(cdb); 928 952 cmd->execute_cmd = sbc_emulate_noop; 929 - break; 953 + goto check_lba; 930 954 case REZERO_UNIT: 931 955 case SEEK_6: 932 956 case SEEK_10: ··· 968 988 dev->dev_attrib.hw_max_sectors); 969 989 return TCM_INVALID_CDB_FIELD; 970 990 } 971 - 991 + check_lba: 972 992 end_lba = dev->transport->get_blocks(dev) + 1; 973 993 if (cmd->t_task_lba + sectors > end_lba) { 974 994 pr_err("cmd exceeds last lba %llu "
+8 -10
drivers/target/target_core_spc.c
··· 129 129 spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) 130 130 { 131 131 struct se_device *dev = cmd->se_dev; 132 - u16 len = 0; 132 + u16 len; 133 133 134 134 if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { 135 - u32 unit_serial_len; 136 - 137 - unit_serial_len = strlen(dev->t10_wwn.unit_serial); 138 - unit_serial_len++; /* For NULL Terminator */ 139 - 140 - len += sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial); 135 + len = sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial); 141 136 len++; /* Extra Byte for NULL Terminator */ 142 137 buf[3] = len; 143 138 } ··· 716 721 unsigned char *buf; 717 722 sense_reason_t ret; 718 723 int p; 724 + int len = 0; 719 725 720 726 buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL); 721 727 if (!buf) { ··· 738 742 } 739 743 740 744 ret = spc_emulate_inquiry_std(cmd, buf); 745 + len = buf[4] + 5; 741 746 goto out; 742 747 } 743 748 ··· 746 749 if (cdb[2] == evpd_handlers[p].page) { 747 750 buf[1] = cdb[2]; 748 751 ret = evpd_handlers[p].emulate(cmd, buf); 752 + len = get_unaligned_be16(&buf[2]) + 4; 749 753 goto out; 750 754 } 751 755 } ··· 763 765 kfree(buf); 764 766 765 767 if (!ret) 766 - target_complete_cmd(cmd, GOOD); 768 + target_complete_cmd_with_length(cmd, GOOD, len); 767 769 return ret; 768 770 } 769 771 ··· 1101 1103 transport_kunmap_data_sg(cmd); 1102 1104 } 1103 1105 1104 - target_complete_cmd(cmd, GOOD); 1106 + target_complete_cmd_with_length(cmd, GOOD, length); 1105 1107 return 0; 1106 1108 } 1107 1109 ··· 1277 1279 buf[3] = (lun_count & 0xff); 1278 1280 transport_kunmap_data_sg(cmd); 1279 1281 1280 - target_complete_cmd(cmd, GOOD); 1282 + target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8); 1281 1283 return 0; 1282 1284 } 1283 1285 EXPORT_SYMBOL(spc_emulate_report_luns);
+32 -5
drivers/target/target_core_transport.c
··· 504 504 * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group 505 505 * removal context. 506 506 */ 507 - if (se_nacl && comp_nacl == true) 507 + if (se_nacl && comp_nacl) 508 508 target_put_nacl(se_nacl); 509 509 510 510 transport_free_session(se_sess); ··· 562 562 563 563 spin_unlock_irqrestore(&cmd->t_state_lock, flags); 564 564 565 - complete(&cmd->t_transport_stop_comp); 565 + complete_all(&cmd->t_transport_stop_comp); 566 566 return 1; 567 567 } 568 568 ··· 687 687 if (cmd->transport_state & CMD_T_ABORTED && 688 688 cmd->transport_state & CMD_T_STOP) { 689 689 spin_unlock_irqrestore(&cmd->t_state_lock, flags); 690 - complete(&cmd->t_transport_stop_comp); 690 + complete_all(&cmd->t_transport_stop_comp); 691 691 return; 692 692 } else if (!success) { 693 693 INIT_WORK(&cmd->work, target_complete_failure_work); ··· 702 702 queue_work(target_completion_wq, &cmd->work); 703 703 } 704 704 EXPORT_SYMBOL(target_complete_cmd); 705 + 706 + void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) 707 + { 708 + if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) { 709 + if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { 710 + cmd->residual_count += cmd->data_length - length; 711 + } else { 712 + cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; 713 + cmd->residual_count = cmd->data_length - length; 714 + } 715 + 716 + cmd->data_length = length; 717 + } 718 + 719 + target_complete_cmd(cmd, scsi_status); 720 + } 721 + EXPORT_SYMBOL(target_complete_cmd_with_length); 705 722 706 723 static void target_add_to_state_list(struct se_cmd *cmd) 707 724 { ··· 1778 1761 cmd->se_tfo->get_task_tag(cmd)); 1779 1762 1780 1763 spin_unlock_irq(&cmd->t_state_lock); 1781 - complete(&cmd->t_transport_stop_comp); 1764 + complete_all(&cmd->t_transport_stop_comp); 1782 1765 return; 1783 1766 } 1784 1767 ··· 2380 2363 * fabric acknowledgement that requires two target_put_sess_cmd() 2381 2364 * invocations before se_cmd descriptor release. 2382 2365 */ 2383 - if (ack_kref == true) { 2366 + if (ack_kref) { 2384 2367 kref_get(&se_cmd->cmd_kref); 2385 2368 se_cmd->se_cmd_flags |= SCF_ACK_KREF; 2386 2369 } ··· 2424 2407 */ 2425 2408 int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd) 2426 2409 { 2410 + if (!se_sess) { 2411 + se_cmd->se_tfo->release_cmd(se_cmd); 2412 + return 1; 2413 + } 2427 2414 return kref_put_spinlock_irqsave(&se_cmd->cmd_kref, target_release_cmd_kref, 2428 2415 &se_sess->sess_cmd_lock); 2429 2416 } ··· 2955 2934 int transport_generic_handle_tmr( 2956 2935 struct se_cmd *cmd) 2957 2936 { 2937 + unsigned long flags; 2938 + 2939 + spin_lock_irqsave(&cmd->t_state_lock, flags); 2940 + cmd->transport_state |= CMD_T_ACTIVE; 2941 + spin_unlock_irqrestore(&cmd->t_state_lock, flags); 2942 + 2958 2943 INIT_WORK(&cmd->work, target_tmr_work); 2959 2944 queue_work(cmd->se_dev->tmr_wq, &cmd->work); 2960 2945 return 0;
+5 -5
drivers/target/target_core_xcopy.c
··· 70 70 unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN], *dev_wwn; 71 71 int rc; 72 72 73 - if (src == true) 73 + if (src) 74 74 dev_wwn = &xop->dst_tid_wwn[0]; 75 75 else 76 76 dev_wwn = &xop->src_tid_wwn[0]; ··· 88 88 if (rc != 0) 89 89 continue; 90 90 91 - if (src == true) { 91 + if (src) { 92 92 xop->dst_dev = se_dev; 93 93 pr_debug("XCOPY 0xe4: Setting xop->dst_dev: %p from located" 94 94 " se_dev\n", xop->dst_dev); ··· 166 166 return -EINVAL; 167 167 } 168 168 169 - if (src == true) { 169 + if (src) { 170 170 memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); 171 171 /* 172 172 * Determine if the source designator matches the local device ··· 236 236 /* 237 237 * Assume target descriptors are in source -> destination order.. 238 238 */ 239 - if (src == true) 239 + if (src) 240 240 src = false; 241 241 else 242 242 src = true; ··· 560 560 * reservations. The pt_cmd->se_lun pointer will be setup from within 561 561 * target_xcopy_setup_pt_port() 562 562 */ 563 - if (remote_port == false) { 563 + if (!remote_port) { 564 564 pt_cmd->se_cmd_flags |= SCF_SE_LUN_CMD | SCF_CMD_XCOPY_PASSTHROUGH; 565 565 return 0; 566 566 }
+16 -3
drivers/target/tcm_fc/tfc_cmd.c
··· 128 128 struct fc_lport *lport; 129 129 struct fc_exch *ep; 130 130 size_t len; 131 + int rc; 131 132 132 133 if (cmd->aborted) 133 134 return 0; ··· 138 137 len = sizeof(*fcp) + se_cmd->scsi_sense_length; 139 138 fp = fc_frame_alloc(lport, len); 140 139 if (!fp) { 141 - /* XXX shouldn't just drop it - requeue and retry? */ 142 - return 0; 140 + se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL; 141 + return -ENOMEM; 143 142 } 143 + 144 144 fcp = fc_frame_payload_get(fp, len); 145 145 memset(fcp, 0, len); 146 146 fcp->resp.fr_status = se_cmd->scsi_status; ··· 172 170 fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP, 173 171 FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0); 174 172 175 - lport->tt.seq_send(lport, cmd->seq, fp); 173 + rc = lport->tt.seq_send(lport, cmd->seq, fp); 174 + if (rc) { 175 + pr_info_ratelimited("%s: Failed to send response frame %p, " 176 + "xid <0x%x>\n", __func__, fp, ep->xid); 177 + /* 178 + * Generate a TASK_SET_FULL status to notify the initiator 179 + * to reduce it's queue_depth after the se_cmd response has 180 + * been re-queued by target-core. 181 + */ 182 + se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL; 183 + return -ENOMEM; 184 + } 176 185 lport->tt.exch_done(cmd->seq); 177 186 return 0; 178 187 }
+15 -2
drivers/target/tcm_fc/tfc_io.c
··· 82 82 83 83 if (cmd->aborted) 84 84 return 0; 85 + 86 + if (se_cmd->scsi_status == SAM_STAT_TASK_SET_FULL) 87 + goto queue_status; 88 + 85 89 ep = fc_seq_exch(cmd->seq); 86 90 lport = ep->lp; 87 91 cmd->seq = lport->tt.seq_start_next(cmd->seq); ··· 182 178 FC_TYPE_FCP, f_ctl, fh_off); 183 179 error = lport->tt.seq_send(lport, seq, fp); 184 180 if (error) { 185 - /* XXX For now, initiator will retry */ 186 - pr_err_ratelimited("%s: Failed to send frame %p, " 181 + pr_info_ratelimited("%s: Failed to send frame %p, " 187 182 "xid <0x%x>, remaining %zu, " 188 183 "lso_max <0x%x>\n", 189 184 __func__, fp, ep->xid, 190 185 remaining, lport->lso_max); 186 + /* 187 + * Go ahead and set TASK_SET_FULL status ignoring the 188 + * rest of the DataIN, and immediately attempt to 189 + * send the response via ft_queue_status() in order 190 + * to notify the initiator that it should reduce it's 191 + * per LUN queue_depth. 192 + */ 193 + se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL; 194 + break; 191 195 } 192 196 } 197 + queue_status: 193 198 return ft_queue_status(se_cmd); 194 199 } 195 200
+215 -99
drivers/vhost/scsi.c
··· 57 57 #define TCM_VHOST_MAX_CDB_SIZE 32 58 58 #define TCM_VHOST_DEFAULT_TAGS 256 59 59 #define TCM_VHOST_PREALLOC_SGLS 2048 60 - #define TCM_VHOST_PREALLOC_PAGES 2048 60 + #define TCM_VHOST_PREALLOC_UPAGES 2048 61 + #define TCM_VHOST_PREALLOC_PROT_SGLS 512 61 62 62 63 struct vhost_scsi_inflight { 63 64 /* Wait for the flush operation to finish */ ··· 80 79 u64 tvc_tag; 81 80 /* The number of scatterlists associated with this cmd */ 82 81 u32 tvc_sgl_count; 82 + u32 tvc_prot_sgl_count; 83 83 /* Saved unpacked SCSI LUN for tcm_vhost_submission_work() */ 84 84 u32 tvc_lun; 85 85 /* Pointer to the SGL formatted memory from virtio-scsi */ 86 86 struct scatterlist *tvc_sgl; 87 + struct scatterlist *tvc_prot_sgl; 87 88 struct page **tvc_upages; 88 89 /* Pointer to response */ 89 90 struct virtio_scsi_cmd_resp __user *tvc_resp; ··· 169 166 }; 170 167 171 168 enum { 172 - VHOST_SCSI_FEATURES = VHOST_FEATURES | (1ULL << VIRTIO_SCSI_F_HOTPLUG) 169 + VHOST_SCSI_FEATURES = VHOST_FEATURES | (1ULL << VIRTIO_SCSI_F_HOTPLUG) | 170 + (1ULL << VIRTIO_SCSI_F_T10_PI) 173 171 }; 174 172 175 173 #define VHOST_SCSI_MAX_TARGET 256 ··· 460 456 struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, 461 457 struct tcm_vhost_cmd, tvc_se_cmd); 462 458 struct se_session *se_sess = se_cmd->se_sess; 459 + int i; 463 460 464 461 if (tv_cmd->tvc_sgl_count) { 465 - u32 i; 466 462 for (i = 0; i < tv_cmd->tvc_sgl_count; i++) 467 463 put_page(sg_page(&tv_cmd->tvc_sgl[i])); 464 + } 465 + if (tv_cmd->tvc_prot_sgl_count) { 466 + for (i = 0; i < tv_cmd->tvc_prot_sgl_count; i++) 467 + put_page(sg_page(&tv_cmd->tvc_prot_sgl[i])); 468 468 } 469 469 470 470 tcm_vhost_put_inflight(tv_cmd->inflight); ··· 721 713 } 722 714 723 715 static struct tcm_vhost_cmd * 724 - vhost_scsi_get_tag(struct vhost_virtqueue *vq, 725 - struct tcm_vhost_tpg *tpg, 726 - struct virtio_scsi_cmd_req *v_req, 727 - u32 exp_data_len, 728 - int data_direction) 716 + vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct tcm_vhost_tpg *tpg, 717 + unsigned char *cdb, u64 scsi_tag, u16 lun, u8 task_attr, 718 + u32 exp_data_len, int data_direction) 729 719 { 730 720 struct tcm_vhost_cmd *cmd; 731 721 struct tcm_vhost_nexus *tv_nexus; 732 722 struct se_session *se_sess; 733 - struct scatterlist *sg; 723 + struct scatterlist *sg, *prot_sg; 734 724 struct page **pages; 735 725 int tag; 736 726 ··· 747 741 748 742 cmd = &((struct tcm_vhost_cmd *)se_sess->sess_cmd_map)[tag]; 749 743 sg = cmd->tvc_sgl; 744 + prot_sg = cmd->tvc_prot_sgl; 750 745 pages = cmd->tvc_upages; 751 746 memset(cmd, 0, sizeof(struct tcm_vhost_cmd)); 752 747 753 748 cmd->tvc_sgl = sg; 749 + cmd->tvc_prot_sgl = prot_sg; 754 750 cmd->tvc_upages = pages; 755 751 cmd->tvc_se_cmd.map_tag = tag; 756 - cmd->tvc_tag = v_req->tag; 757 - cmd->tvc_task_attr = v_req->task_attr; 752 + cmd->tvc_tag = scsi_tag; 753 + cmd->tvc_lun = lun; 754 + cmd->tvc_task_attr = task_attr; 758 755 cmd->tvc_exp_data_len = exp_data_len; 759 756 cmd->tvc_data_direction = data_direction; 760 757 cmd->tvc_nexus = tv_nexus; 761 758 cmd->inflight = tcm_vhost_get_inflight(vq); 759 + 760 + memcpy(cmd->tvc_cdb, cdb, TCM_VHOST_MAX_CDB_SIZE); 762 761 763 762 return cmd; 764 763 } ··· 778 767 struct scatterlist *sgl, 779 768 unsigned int sgl_count, 780 769 struct iovec *iov, 781 - int write) 770 + struct page **pages, 771 + bool write) 782 772 { 783 773 unsigned int npages = 0, pages_nr, offset, nbytes; 784 774 struct scatterlist *sg = sgl; 785 775 void __user *ptr = iov->iov_base; 786 776 size_t len = iov->iov_len; 787 - struct page **pages; 788 777 int ret, i; 789 778 790 - if (sgl_count > TCM_VHOST_PREALLOC_SGLS) { 791 - pr_err("vhost_scsi_map_to_sgl() psgl_count: %u greater than" 792 - " preallocated TCM_VHOST_PREALLOC_SGLS: %u\n", 793 - sgl_count, TCM_VHOST_PREALLOC_SGLS); 794 - return -ENOBUFS; 795 - } 796 - 797 779 pages_nr = iov_num_pages(iov); 798 - if (pages_nr > sgl_count) 799 - return -ENOBUFS; 800 - 801 - if (pages_nr > TCM_VHOST_PREALLOC_PAGES) { 780 + if (pages_nr > sgl_count) { 802 781 pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than" 803 - " preallocated TCM_VHOST_PREALLOC_PAGES: %u\n", 804 - pages_nr, TCM_VHOST_PREALLOC_PAGES); 782 + " sgl_count: %u\n", pages_nr, sgl_count); 805 783 return -ENOBUFS; 806 784 } 807 - 808 - pages = tv_cmd->tvc_upages; 785 + if (pages_nr > TCM_VHOST_PREALLOC_UPAGES) { 786 + pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than" 787 + " preallocated TCM_VHOST_PREALLOC_UPAGES: %u\n", 788 + pages_nr, TCM_VHOST_PREALLOC_UPAGES); 789 + return -ENOBUFS; 790 + } 809 791 810 792 ret = get_user_pages_fast((unsigned long)ptr, pages_nr, write, pages); 811 793 /* No pages were pinned */ ··· 829 825 static int 830 826 vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd, 831 827 struct iovec *iov, 832 - unsigned int niov, 833 - int write) 828 + int niov, 829 + bool write) 834 830 { 835 - int ret; 836 - unsigned int i; 837 - u32 sgl_count; 838 - struct scatterlist *sg; 831 + struct scatterlist *sg = cmd->tvc_sgl; 832 + unsigned int sgl_count = 0; 833 + int ret, i; 839 834 840 - /* 841 - * Find out how long sglist needs to be 842 - */ 843 - sgl_count = 0; 844 835 for (i = 0; i < niov; i++) 845 836 sgl_count += iov_num_pages(&iov[i]); 846 837 847 - /* TODO overflow checking */ 838 + if (sgl_count > TCM_VHOST_PREALLOC_SGLS) { 839 + pr_err("vhost_scsi_map_iov_to_sgl() sgl_count: %u greater than" 840 + " preallocated TCM_VHOST_PREALLOC_SGLS: %u\n", 841 + sgl_count, TCM_VHOST_PREALLOC_SGLS); 842 + return -ENOBUFS; 843 + } 848 844 849 - sg = cmd->tvc_sgl; 850 845 pr_debug("%s sg %p sgl_count %u\n", __func__, sg, sgl_count); 851 846 sg_init_table(sg, sgl_count); 852 - 853 847 cmd->tvc_sgl_count = sgl_count; 854 848 855 - pr_debug("Mapping %u iovecs for %u pages\n", niov, sgl_count); 849 + pr_debug("Mapping iovec %p for %u pages\n", &iov[0], sgl_count); 850 + 856 851 for (i = 0; i < niov; i++) { 857 852 ret = vhost_scsi_map_to_sgl(cmd, sg, sgl_count, &iov[i], 858 - write); 853 + cmd->tvc_upages, write); 859 854 if (ret < 0) { 860 855 for (i = 0; i < cmd->tvc_sgl_count; i++) 861 856 put_page(sg_page(&cmd->tvc_sgl[i])); ··· 862 859 cmd->tvc_sgl_count = 0; 863 860 return ret; 864 861 } 865 - 866 862 sg += ret; 867 863 sgl_count -= ret; 864 + } 865 + return 0; 866 + } 867 + 868 + static int 869 + vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd, 870 + struct iovec *iov, 871 + int niov, 872 + bool write) 873 + { 874 + struct scatterlist *prot_sg = cmd->tvc_prot_sgl; 875 + unsigned int prot_sgl_count = 0; 876 + int ret, i; 877 + 878 + for (i = 0; i < niov; i++) 879 + prot_sgl_count += iov_num_pages(&iov[i]); 880 + 881 + if (prot_sgl_count > TCM_VHOST_PREALLOC_PROT_SGLS) { 882 + pr_err("vhost_scsi_map_iov_to_prot() sgl_count: %u greater than" 883 + " preallocated TCM_VHOST_PREALLOC_PROT_SGLS: %u\n", 884 + prot_sgl_count, TCM_VHOST_PREALLOC_PROT_SGLS); 885 + return -ENOBUFS; 886 + } 887 + 888 + pr_debug("%s prot_sg %p prot_sgl_count %u\n", __func__, 889 + prot_sg, prot_sgl_count); 890 + sg_init_table(prot_sg, prot_sgl_count); 891 + cmd->tvc_prot_sgl_count = prot_sgl_count; 892 + 893 + for (i = 0; i < niov; i++) { 894 + ret = vhost_scsi_map_to_sgl(cmd, prot_sg, prot_sgl_count, &iov[i], 895 + cmd->tvc_upages, write); 896 + if (ret < 0) { 897 + for (i = 0; i < cmd->tvc_prot_sgl_count; i++) 898 + put_page(sg_page(&cmd->tvc_prot_sgl[i])); 899 + 900 + cmd->tvc_prot_sgl_count = 0; 901 + return ret; 902 + } 903 + prot_sg += ret; 904 + prot_sgl_count -= ret; 868 905 } 869 906 return 0; 870 907 } ··· 915 872 container_of(work, struct tcm_vhost_cmd, work); 916 873 struct tcm_vhost_nexus *tv_nexus; 917 874 struct se_cmd *se_cmd = &cmd->tvc_se_cmd; 918 - struct scatterlist *sg_ptr, *sg_bidi_ptr = NULL; 919 - int rc, sg_no_bidi = 0; 875 + struct scatterlist *sg_ptr, *sg_prot_ptr = NULL; 876 + int rc; 920 877 878 + /* FIXME: BIDI operation */ 921 879 if (cmd->tvc_sgl_count) { 922 880 sg_ptr = cmd->tvc_sgl; 923 - /* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ 924 - #if 0 925 - if (se_cmd->se_cmd_flags & SCF_BIDI) { 926 - sg_bidi_ptr = NULL; 927 - sg_no_bidi = 0; 928 - } 929 - #endif 881 + 882 + if (cmd->tvc_prot_sgl_count) 883 + sg_prot_ptr = cmd->tvc_prot_sgl; 884 + else 885 + se_cmd->prot_pto = true; 930 886 } else { 931 887 sg_ptr = NULL; 932 888 } ··· 936 894 cmd->tvc_lun, cmd->tvc_exp_data_len, 937 895 cmd->tvc_task_attr, cmd->tvc_data_direction, 938 896 TARGET_SCF_ACK_KREF, sg_ptr, cmd->tvc_sgl_count, 939 - sg_bidi_ptr, sg_no_bidi, NULL, 0); 897 + NULL, 0, sg_prot_ptr, cmd->tvc_prot_sgl_count); 940 898 if (rc < 0) { 941 899 transport_send_check_condition_and_sense(se_cmd, 942 900 TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); ··· 968 926 { 969 927 struct tcm_vhost_tpg **vs_tpg; 970 928 struct virtio_scsi_cmd_req v_req; 929 + struct virtio_scsi_cmd_req_pi v_req_pi; 971 930 struct tcm_vhost_tpg *tpg; 972 931 struct tcm_vhost_cmd *cmd; 973 - u32 exp_data_len, data_first, data_num, data_direction; 932 + u64 tag; 933 + u32 exp_data_len, data_first, data_num, data_direction, prot_first; 974 934 unsigned out, in, i; 975 - int head, ret; 976 - u8 target; 935 + int head, ret, data_niov, prot_niov, prot_bytes; 936 + size_t req_size; 937 + u16 lun; 938 + u8 *target, *lunp, task_attr; 939 + bool hdr_pi; 940 + void *req, *cdb; 977 941 978 942 mutex_lock(&vq->mutex); 979 943 /* ··· 1010 962 break; 1011 963 } 1012 964 1013 - /* FIXME: BIDI operation */ 965 + /* FIXME: BIDI operation */ 1014 966 if (out == 1 && in == 1) { 1015 967 data_direction = DMA_NONE; 1016 968 data_first = 0; ··· 1040 992 break; 1041 993 } 1042 994 1043 - if (unlikely(vq->iov[0].iov_len != sizeof(v_req))) { 1044 - vq_err(vq, "Expecting virtio_scsi_cmd_req, got %zu" 1045 - " bytes\n", vq->iov[0].iov_len); 995 + if (vhost_has_feature(vq, VIRTIO_SCSI_F_T10_PI)) { 996 + req = &v_req_pi; 997 + lunp = &v_req_pi.lun[0]; 998 + target = &v_req_pi.lun[1]; 999 + req_size = sizeof(v_req_pi); 1000 + hdr_pi = true; 1001 + } else { 1002 + req = &v_req; 1003 + lunp = &v_req.lun[0]; 1004 + target = &v_req.lun[1]; 1005 + req_size = sizeof(v_req); 1006 + hdr_pi = false; 1007 + } 1008 + 1009 + if (unlikely(vq->iov[0].iov_len < req_size)) { 1010 + pr_err("Expecting virtio-scsi header: %zu, got %zu\n", 1011 + req_size, vq->iov[0].iov_len); 1046 1012 break; 1047 1013 } 1048 - pr_debug("Calling __copy_from_user: vq->iov[0].iov_base: %p," 1049 - " len: %zu\n", vq->iov[0].iov_base, sizeof(v_req)); 1050 - ret = __copy_from_user(&v_req, vq->iov[0].iov_base, 1051 - sizeof(v_req)); 1014 + ret = memcpy_fromiovecend(req, &vq->iov[0], 0, req_size); 1052 1015 if (unlikely(ret)) { 1053 1016 vq_err(vq, "Faulted on virtio_scsi_cmd_req\n"); 1054 1017 break; 1055 1018 } 1056 1019 1057 1020 /* virtio-scsi spec requires byte 0 of the lun to be 1 */ 1058 - if (unlikely(v_req.lun[0] != 1)) { 1021 + if (unlikely(*lunp != 1)) { 1059 1022 vhost_scsi_send_bad_target(vs, vq, head, out); 1060 1023 continue; 1061 1024 } 1062 1025 1063 - /* Extract the tpgt */ 1064 - target = v_req.lun[1]; 1065 - tpg = ACCESS_ONCE(vs_tpg[target]); 1026 + tpg = ACCESS_ONCE(vs_tpg[*target]); 1066 1027 1067 1028 /* Target does not exist, fail the request */ 1068 1029 if (unlikely(!tpg)) { ··· 1079 1022 continue; 1080 1023 } 1081 1024 1082 - exp_data_len = 0; 1083 - for (i = 0; i < data_num; i++) 1084 - exp_data_len += vq->iov[data_first + i].iov_len; 1025 + data_niov = data_num; 1026 + prot_niov = prot_first = prot_bytes = 0; 1027 + /* 1028 + * Determine if any protection information iovecs are preceeding 1029 + * the actual data payload, and adjust data_first + data_niov 1030 + * values accordingly for vhost_scsi_map_iov_to_sgl() below. 1031 + * 1032 + * Also extract virtio_scsi header bits for vhost_scsi_get_tag() 1033 + */ 1034 + if (hdr_pi) { 1035 + if (v_req_pi.pi_bytesout) { 1036 + if (data_direction != DMA_TO_DEVICE) { 1037 + vq_err(vq, "Received non zero do_pi_niov" 1038 + ", but wrong data_direction\n"); 1039 + goto err_cmd; 1040 + } 1041 + prot_bytes = v_req_pi.pi_bytesout; 1042 + } else if (v_req_pi.pi_bytesin) { 1043 + if (data_direction != DMA_FROM_DEVICE) { 1044 + vq_err(vq, "Received non zero di_pi_niov" 1045 + ", but wrong data_direction\n"); 1046 + goto err_cmd; 1047 + } 1048 + prot_bytes = v_req_pi.pi_bytesin; 1049 + } 1050 + if (prot_bytes) { 1051 + int tmp = 0; 1085 1052 1086 - cmd = vhost_scsi_get_tag(vq, tpg, &v_req, 1087 - exp_data_len, data_direction); 1053 + for (i = 0; i < data_num; i++) { 1054 + tmp += vq->iov[data_first + i].iov_len; 1055 + prot_niov++; 1056 + if (tmp >= prot_bytes) 1057 + break; 1058 + } 1059 + prot_first = data_first; 1060 + data_first += prot_niov; 1061 + data_niov = data_num - prot_niov; 1062 + } 1063 + tag = v_req_pi.tag; 1064 + task_attr = v_req_pi.task_attr; 1065 + cdb = &v_req_pi.cdb[0]; 1066 + lun = ((v_req_pi.lun[2] << 8) | v_req_pi.lun[3]) & 0x3FFF; 1067 + } else { 1068 + tag = v_req.tag; 1069 + task_attr = v_req.task_attr; 1070 + cdb = &v_req.cdb[0]; 1071 + lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF; 1072 + } 1073 + exp_data_len = 0; 1074 + for (i = 0; i < data_niov; i++) 1075 + exp_data_len += vq->iov[data_first + i].iov_len; 1076 + /* 1077 + * Check that the recieved CDB size does not exceeded our 1078 + * hardcoded max for vhost-scsi 1079 + * 1080 + * TODO what if cdb was too small for varlen cdb header? 1081 + */ 1082 + if (unlikely(scsi_command_size(cdb) > TCM_VHOST_MAX_CDB_SIZE)) { 1083 + vq_err(vq, "Received SCSI CDB with command_size: %d that" 1084 + " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", 1085 + scsi_command_size(cdb), TCM_VHOST_MAX_CDB_SIZE); 1086 + goto err_cmd; 1087 + } 1088 + 1089 + cmd = vhost_scsi_get_tag(vq, tpg, cdb, tag, lun, task_attr, 1090 + exp_data_len + prot_bytes, 1091 + data_direction); 1088 1092 if (IS_ERR(cmd)) { 1089 1093 vq_err(vq, "vhost_scsi_get_tag failed %ld\n", 1090 1094 PTR_ERR(cmd)); 1091 1095 goto err_cmd; 1092 1096 } 1097 + 1093 1098 pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction" 1094 1099 ": %d\n", cmd, exp_data_len, data_direction); 1095 1100 ··· 1159 1040 cmd->tvc_vq = vq; 1160 1041 cmd->tvc_resp = vq->iov[out].iov_base; 1161 1042 1162 - /* 1163 - * Copy in the recieved CDB descriptor into cmd->tvc_cdb 1164 - * that will be used by tcm_vhost_new_cmd_map() and down into 1165 - * target_setup_cmd_from_cdb() 1166 - */ 1167 - memcpy(cmd->tvc_cdb, v_req.cdb, TCM_VHOST_MAX_CDB_SIZE); 1168 - /* 1169 - * Check that the recieved CDB size does not exceeded our 1170 - * hardcoded max for tcm_vhost 1171 - */ 1172 - /* TODO what if cdb was too small for varlen cdb header? */ 1173 - if (unlikely(scsi_command_size(cmd->tvc_cdb) > 1174 - TCM_VHOST_MAX_CDB_SIZE)) { 1175 - vq_err(vq, "Received SCSI CDB with command_size: %d that" 1176 - " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", 1177 - scsi_command_size(cmd->tvc_cdb), 1178 - TCM_VHOST_MAX_CDB_SIZE); 1179 - goto err_free; 1180 - } 1181 - cmd->tvc_lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF; 1182 - 1183 1043 pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n", 1184 1044 cmd->tvc_cdb[0], cmd->tvc_lun); 1185 1045 1046 + if (prot_niov) { 1047 + ret = vhost_scsi_map_iov_to_prot(cmd, 1048 + &vq->iov[prot_first], prot_niov, 1049 + data_direction == DMA_FROM_DEVICE); 1050 + if (unlikely(ret)) { 1051 + vq_err(vq, "Failed to map iov to" 1052 + " prot_sgl\n"); 1053 + goto err_free; 1054 + } 1055 + } 1186 1056 if (data_direction != DMA_NONE) { 1187 1057 ret = vhost_scsi_map_iov_to_sgl(cmd, 1188 - &vq->iov[data_first], data_num, 1058 + &vq->iov[data_first], data_niov, 1189 1059 data_direction == DMA_FROM_DEVICE); 1190 1060 if (unlikely(ret)) { 1191 1061 vq_err(vq, "Failed to map iov to sgl\n"); 1192 1062 goto err_free; 1193 1063 } 1194 1064 } 1195 - 1196 1065 /* 1197 1066 * Save the descriptor from vhost_get_vq_desc() to be used to 1198 1067 * complete the virtio-scsi request in TCM callback context via ··· 1823 1716 tv_cmd = &((struct tcm_vhost_cmd *)se_sess->sess_cmd_map)[i]; 1824 1717 1825 1718 kfree(tv_cmd->tvc_sgl); 1719 + kfree(tv_cmd->tvc_prot_sgl); 1826 1720 kfree(tv_cmd->tvc_upages); 1827 1721 } 1828 1722 } ··· 1858 1750 tv_nexus->tvn_se_sess = transport_init_session_tags( 1859 1751 TCM_VHOST_DEFAULT_TAGS, 1860 1752 sizeof(struct tcm_vhost_cmd), 1861 - TARGET_PROT_NORMAL); 1753 + TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS); 1862 1754 if (IS_ERR(tv_nexus->tvn_se_sess)) { 1863 1755 mutex_unlock(&tpg->tv_tpg_mutex); 1864 1756 kfree(tv_nexus); ··· 1877 1769 } 1878 1770 1879 1771 tv_cmd->tvc_upages = kzalloc(sizeof(struct page *) * 1880 - TCM_VHOST_PREALLOC_PAGES, GFP_KERNEL); 1772 + TCM_VHOST_PREALLOC_UPAGES, GFP_KERNEL); 1881 1773 if (!tv_cmd->tvc_upages) { 1882 1774 mutex_unlock(&tpg->tv_tpg_mutex); 1883 1775 pr_err("Unable to allocate tv_cmd->tvc_upages\n"); 1776 + goto out; 1777 + } 1778 + 1779 + tv_cmd->tvc_prot_sgl = kzalloc(sizeof(struct scatterlist) * 1780 + TCM_VHOST_PREALLOC_PROT_SGLS, GFP_KERNEL); 1781 + if (!tv_cmd->tvc_prot_sgl) { 1782 + mutex_unlock(&tpg->tv_tpg_mutex); 1783 + pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n"); 1884 1784 goto out; 1885 1785 } 1886 1786 }
+14 -1
include/linux/virtio_scsi.h
··· 35 35 u8 lun[8]; /* Logical Unit Number */ 36 36 u64 tag; /* Command identifier */ 37 37 u8 task_attr; /* Task attribute */ 38 - u8 prio; 38 + u8 prio; /* SAM command priority field */ 39 39 u8 crn; 40 + u8 cdb[VIRTIO_SCSI_CDB_SIZE]; 41 + } __packed; 42 + 43 + /* SCSI command request, followed by protection information */ 44 + struct virtio_scsi_cmd_req_pi { 45 + u8 lun[8]; /* Logical Unit Number */ 46 + u64 tag; /* Command identifier */ 47 + u8 task_attr; /* Task attribute */ 48 + u8 prio; /* SAM command priority field */ 49 + u8 crn; 50 + u32 pi_bytesout; /* DataOUT PI Number of bytes */ 51 + u32 pi_bytesin; /* DataIN PI Number of bytes */ 40 52 u8 cdb[VIRTIO_SCSI_CDB_SIZE]; 41 53 } __packed; 42 54 ··· 109 97 #define VIRTIO_SCSI_F_INOUT 0 110 98 #define VIRTIO_SCSI_F_HOTPLUG 1 111 99 #define VIRTIO_SCSI_F_CHANGE 2 100 + #define VIRTIO_SCSI_F_T10_PI 3 112 101 113 102 /* Response codes */ 114 103 #define VIRTIO_SCSI_S_OK 0
+17
include/scsi/scsi_cmnd.h
··· 7 7 #include <linux/types.h> 8 8 #include <linux/timer.h> 9 9 #include <linux/scatterlist.h> 10 + #include <scsi/scsi_device.h> 10 11 11 12 struct Scsi_Host; 12 13 struct scsi_device; ··· 314 313 static inline void set_driver_byte(struct scsi_cmnd *cmd, char status) 315 314 { 316 315 cmd->result = (cmd->result & 0x00ffffff) | (status << 24); 316 + } 317 + 318 + static inline unsigned scsi_transfer_length(struct scsi_cmnd *scmd) 319 + { 320 + unsigned int xfer_len = blk_rq_bytes(scmd->request); 321 + unsigned int prot_op = scsi_get_prot_op(scmd); 322 + unsigned int sector_size = scmd->device->sector_size; 323 + 324 + switch (prot_op) { 325 + case SCSI_PROT_NORMAL: 326 + case SCSI_PROT_WRITE_STRIP: 327 + case SCSI_PROT_READ_INSERT: 328 + return xfer_len; 329 + } 330 + 331 + return xfer_len + (xfer_len >> ilog2(sector_size)) * 8; 317 332 } 318 333 319 334 #endif /* _SCSI_SCSI_CMND_H */
+2 -1
include/target/iscsi/iscsi_transport.h
··· 70 70 extern void iscsit_build_task_mgt_rsp(struct iscsi_cmd *, struct iscsi_conn *, 71 71 struct iscsi_tm_rsp *); 72 72 extern int iscsit_build_text_rsp(struct iscsi_cmd *, struct iscsi_conn *, 73 - struct iscsi_text_rsp *); 73 + struct iscsi_text_rsp *, 74 + enum iscsit_transport_type); 74 75 extern void iscsit_build_reject(struct iscsi_cmd *, struct iscsi_conn *, 75 76 struct iscsi_reject *); 76 77 extern int iscsit_build_logout_rsp(struct iscsi_cmd *, struct iscsi_conn *,
+1
include/target/target_core_backend.h
··· 59 59 void transport_subsystem_release(struct se_subsystem_api *); 60 60 61 61 void target_complete_cmd(struct se_cmd *, u8); 62 + void target_complete_cmd_with_length(struct se_cmd *, u8, int); 62 63 63 64 sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); 64 65 sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd);