1 #include "iscsi/task.h" 2 #include "iscsi/iscsi.h" 3 #include "iscsi/conn.h" 4 5 #include "spdk/env.h" 6 #include "spdk/sock.h" 7 #include "spdk_cunit.h" 8 9 #include "spdk/log.h" 10 #include "spdk_internal/mock.h" 11 12 #include "scsi/scsi_internal.h" 13 14 SPDK_LOG_REGISTER_COMPONENT(iscsi) 15 16 TAILQ_HEAD(, spdk_iscsi_pdu) g_write_pdu_list = TAILQ_HEAD_INITIALIZER(g_write_pdu_list); 17 18 static bool g_task_pool_is_empty = false; 19 static bool g_pdu_pool_is_empty = false; 20 static uint32_t g_conn_read_len; 21 22 struct spdk_iscsi_task * 23 iscsi_task_get(struct spdk_iscsi_conn *conn, 24 struct spdk_iscsi_task *parent, 25 spdk_scsi_task_cpl cpl_fn) 26 { 27 struct spdk_iscsi_task *task; 28 29 if (g_task_pool_is_empty) { 30 return NULL; 31 } 32 33 task = calloc(1, sizeof(*task)); 34 if (!task) { 35 return NULL; 36 } 37 38 task->conn = conn; 39 task->scsi.cpl_fn = cpl_fn; 40 if (parent) { 41 parent->scsi.ref++; 42 task->parent = parent; 43 task->tag = parent->tag; 44 task->lun_id = parent->lun_id; 45 task->scsi.dxfer_dir = parent->scsi.dxfer_dir; 46 task->scsi.transfer_len = parent->scsi.transfer_len; 47 task->scsi.lun = parent->scsi.lun; 48 task->scsi.cdb = parent->scsi.cdb; 49 task->scsi.target_port = parent->scsi.target_port; 50 task->scsi.initiator_port = parent->scsi.initiator_port; 51 if (conn && (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) { 52 conn->data_in_cnt++; 53 } 54 } 55 56 task->scsi.iovs = &task->scsi.iov; 57 return task; 58 } 59 60 void 61 spdk_scsi_task_put(struct spdk_scsi_task *task) 62 { 63 free(task); 64 } 65 66 void 67 iscsi_put_pdu(struct spdk_iscsi_pdu *pdu) 68 { 69 if (!pdu) { 70 return; 71 } 72 73 pdu->ref--; 74 if (pdu->ref < 0) { 75 CU_FAIL("negative ref count"); 76 pdu->ref = 0; 77 } 78 79 if (pdu->ref == 0) { 80 if (pdu->data && !pdu->data_from_mempool) { 81 free(pdu->data); 82 } 83 free(pdu); 84 } 85 } 86 87 struct spdk_iscsi_pdu * 88 iscsi_get_pdu(struct spdk_iscsi_conn *conn) 89 { 90 struct spdk_iscsi_pdu *pdu; 91 92 assert(conn != NULL); 93 if (g_pdu_pool_is_empty) { 94 return NULL; 95 } 96 97 pdu = malloc(sizeof(*pdu)); 98 if (!pdu) { 99 return NULL; 100 } 101 102 memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs)); 103 pdu->ref = 1; 104 pdu->conn = conn; 105 106 return pdu; 107 } 108 109 DEFINE_STUB_V(spdk_scsi_task_process_null_lun, (struct spdk_scsi_task *task)); 110 111 DEFINE_STUB_V(spdk_scsi_task_process_abort, (struct spdk_scsi_task *task)); 112 113 void 114 spdk_scsi_dev_queue_task(struct spdk_scsi_dev *dev, struct spdk_scsi_task *task) 115 { 116 assert(dev->lun[0] != NULL); 117 118 TAILQ_INSERT_TAIL(&dev->lun[0]->tasks, task, scsi_link); 119 } 120 121 DEFINE_STUB(spdk_scsi_dev_find_port_by_id, struct spdk_scsi_port *, 122 (struct spdk_scsi_dev *dev, uint64_t id), NULL); 123 124 DEFINE_STUB_V(spdk_scsi_dev_queue_mgmt_task, 125 (struct spdk_scsi_dev *dev, struct spdk_scsi_task *task)); 126 127 const char * 128 spdk_scsi_dev_get_name(const struct spdk_scsi_dev *dev) 129 { 130 if (dev != NULL) { 131 return dev->name; 132 } 133 134 return NULL; 135 } 136 137 DEFINE_STUB(spdk_scsi_dev_construct, struct spdk_scsi_dev *, 138 (const char *name, const char **bdev_name_list, 139 int *lun_id_list, int num_luns, uint8_t protocol_id, 140 void (*hotremove_cb)(const struct spdk_scsi_lun *, void *), 141 void *hotremove_ctx), 142 NULL); 143 144 DEFINE_STUB_V(spdk_scsi_dev_destruct, 145 (struct spdk_scsi_dev *dev, spdk_scsi_dev_destruct_cb_t cb_fn, void *cb_arg)); 146 147 DEFINE_STUB(spdk_scsi_dev_add_port, int, 148 (struct spdk_scsi_dev *dev, uint64_t id, const char *name), 0); 149 150 DEFINE_STUB(iscsi_drop_conns, int, 151 (struct spdk_iscsi_conn *conn, const char *conn_match, int drop_all), 152 0); 153 154 DEFINE_STUB(spdk_scsi_dev_delete_port, int, 155 (struct spdk_scsi_dev *dev, uint64_t id), 0); 156 157 DEFINE_STUB_V(shutdown_iscsi_conns, (void)); 158 159 DEFINE_STUB_V(iscsi_conns_request_logout, (struct spdk_iscsi_tgt_node *target, int pg_tag)); 160 161 DEFINE_STUB(iscsi_get_active_conns, int, (struct spdk_iscsi_tgt_node *target), 0); 162 163 void 164 iscsi_task_cpl(struct spdk_scsi_task *scsi_task) 165 { 166 struct spdk_iscsi_task *iscsi_task; 167 168 if (scsi_task != NULL) { 169 iscsi_task = iscsi_task_from_scsi_task(scsi_task); 170 if (iscsi_task->parent && (iscsi_task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) { 171 assert(iscsi_task->conn->data_in_cnt > 0); 172 iscsi_task->conn->data_in_cnt--; 173 } 174 175 free(iscsi_task); 176 } 177 } 178 179 DEFINE_STUB_V(iscsi_task_mgmt_cpl, (struct spdk_scsi_task *scsi_task)); 180 181 int 182 iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int bytes, void *buf) 183 { 184 uint32_t *data = buf; 185 int i; 186 187 /* Limit the length to 4 bytes multiples. */ 188 SPDK_CU_ASSERT_FATAL((bytes % 4) == 0); 189 190 for (i = 0; i < bytes; i += 4) { 191 data[i / 4] = g_conn_read_len + i; 192 } 193 194 g_conn_read_len += bytes; 195 196 return bytes; 197 } 198 199 int 200 iscsi_conn_readv_data(struct spdk_iscsi_conn *conn, struct iovec *iov, int iovcnt) 201 { 202 int i, len = 0; 203 204 for (i = 0; i < iovcnt; i++) { 205 len += iov[i].iov_len; 206 } 207 208 return len; 209 } 210 211 void 212 iscsi_conn_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu, 213 iscsi_conn_xfer_complete_cb cb_fn, void *cb_arg) 214 { 215 TAILQ_INSERT_TAIL(&g_write_pdu_list, pdu, tailq); 216 } 217 218 DEFINE_STUB_V(iscsi_conn_logout, (struct spdk_iscsi_conn *conn)); 219 220 DEFINE_STUB_V(spdk_scsi_task_set_status, 221 (struct spdk_scsi_task *task, int sc, int sk, int asc, int ascq)); 222 223 void 224 spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len) 225 { 226 SPDK_CU_ASSERT_FATAL(task->iovs != NULL); 227 task->iovs[0].iov_base = data; 228 task->iovs[0].iov_len = len; 229 } 230