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