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