1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 3 * Copyright (C) 2016 Intel Corporation. 4 * All rights reserved. 5 */ 6 7 #ifndef SPDK_ISCSI_TASK_H 8 #define SPDK_ISCSI_TASK_H 9 10 #include "iscsi/iscsi.h" 11 #include "spdk/scsi.h" 12 #include "spdk/util.h" 13 14 struct spdk_iscsi_task { 15 struct spdk_scsi_task scsi; 16 17 struct spdk_iscsi_task *parent; 18 19 struct spdk_iscsi_conn *conn; 20 struct spdk_iscsi_pdu *pdu; 21 struct spdk_mobj *mobj; 22 uint64_t start_tsc; 23 uint32_t outstanding_r2t; 24 25 uint32_t desired_data_transfer_length; 26 27 /* Only valid for Read/Write */ 28 uint32_t bytes_completed; 29 30 uint32_t data_out_cnt; 31 32 /* 33 * Tracks the current offset of large read or write io. 34 */ 35 uint32_t current_data_offset; 36 37 /* 38 * next_expected_r2t_offset is used when we receive 39 * the DataOUT PDU. 40 */ 41 uint32_t next_expected_r2t_offset; 42 43 /* 44 * Tracks the length of the R2T that is in progress. 45 * Used to check that an R2T burst does not exceed 46 * MaxBurstLength. 47 */ 48 uint32_t current_r2t_length; 49 50 /* 51 * next_r2t_offset is used when we are sending the 52 * R2T packet to keep track of next offset of r2t. 53 */ 54 uint32_t next_r2t_offset; 55 uint32_t R2TSN; 56 uint32_t r2t_datasn; /* record next datasn for a r2tsn */ 57 uint32_t acked_r2tsn; /* next r2tsn to be acked */ 58 uint32_t datain_datasn; 59 uint32_t acked_data_sn; /* next expected datain datasn */ 60 uint32_t ttt; 61 bool is_r2t_active; 62 63 uint32_t tag; 64 65 /** 66 * Record the lun id just in case the lun is invalid, 67 * which will happen when hot removing the lun. 68 */ 69 int lun_id; 70 71 struct spdk_poller *mgmt_poller; 72 73 TAILQ_ENTRY(spdk_iscsi_task) link; 74 75 TAILQ_HEAD(subtask_list, spdk_iscsi_task) subtask_list; 76 TAILQ_ENTRY(spdk_iscsi_task) subtask_link; 77 bool is_queued; /* is queued in scsi layer for handling */ 78 }; 79 80 static inline void 81 iscsi_task_put(struct spdk_iscsi_task *task) 82 { 83 spdk_scsi_task_put(&task->scsi); 84 } 85 86 static inline struct spdk_iscsi_pdu * 87 iscsi_task_get_pdu(struct spdk_iscsi_task *task) 88 { 89 return task->pdu; 90 } 91 92 static inline void 93 iscsi_task_set_pdu(struct spdk_iscsi_task *task, struct spdk_iscsi_pdu *pdu) 94 { 95 task->pdu = pdu; 96 } 97 98 static inline struct iscsi_bhs * 99 iscsi_task_get_bhs(struct spdk_iscsi_task *task) 100 { 101 return &iscsi_task_get_pdu(task)->bhs; 102 } 103 104 static inline void 105 iscsi_task_associate_pdu(struct spdk_iscsi_task *task, struct spdk_iscsi_pdu *pdu) 106 { 107 iscsi_task_set_pdu(task, pdu); 108 pdu->ref++; 109 } 110 111 static inline void 112 iscsi_task_disassociate_pdu(struct spdk_iscsi_task *task) 113 { 114 if (iscsi_task_get_pdu(task)) { 115 iscsi_put_pdu(iscsi_task_get_pdu(task)); 116 iscsi_task_set_pdu(task, NULL); 117 } 118 } 119 120 static inline int 121 iscsi_task_is_immediate(struct spdk_iscsi_task *task) 122 { 123 struct iscsi_bhs_scsi_req *scsi_req; 124 125 scsi_req = (struct iscsi_bhs_scsi_req *)iscsi_task_get_bhs(task); 126 return (scsi_req->immediate == 1); 127 } 128 129 static inline int 130 iscsi_task_is_read(struct spdk_iscsi_task *task) 131 { 132 struct iscsi_bhs_scsi_req *scsi_req; 133 134 scsi_req = (struct iscsi_bhs_scsi_req *)iscsi_task_get_bhs(task); 135 return (scsi_req->read_bit == 1); 136 } 137 138 struct spdk_iscsi_task *iscsi_task_get(struct spdk_iscsi_conn *conn, 139 struct spdk_iscsi_task *parent, 140 spdk_scsi_task_cpl cpl_fn); 141 142 static inline struct spdk_iscsi_task * 143 iscsi_task_from_scsi_task(struct spdk_scsi_task *task) 144 { 145 return SPDK_CONTAINEROF(task, struct spdk_iscsi_task, scsi); 146 } 147 148 static inline struct spdk_iscsi_task * 149 iscsi_task_get_primary(struct spdk_iscsi_task *task) 150 { 151 if (task->parent) { 152 return task->parent; 153 } else { 154 return task; 155 } 156 } 157 158 static inline void 159 iscsi_task_set_mobj(struct spdk_iscsi_task *task, struct spdk_mobj *mobj) 160 { 161 task->mobj = mobj; 162 } 163 164 static inline struct spdk_mobj * 165 iscsi_task_get_mobj(struct spdk_iscsi_task *task) 166 { 167 return task->mobj; 168 } 169 170 #endif /* SPDK_ISCSI_TASK_H */ 171