Branch data Line data Source code
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_internal/cunit.h"
13 : :
14 : : #include "spdk/log.h"
15 : : #include "spdk_internal/mock.h"
16 : :
17 : : #include "scsi/scsi_internal.h"
18 : :
19 : 12 : 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 : 102 : 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 [ - + - + ]: 102 : if (g_task_pool_is_empty) {
37 : 0 : return NULL;
38 : : }
39 : :
40 : 102 : task = calloc(1, sizeof(*task));
41 [ - + ]: 102 : if (!task) {
42 : 0 : return NULL;
43 : : }
44 : :
45 : 102 : task->conn = conn;
46 : 102 : task->scsi.cpl_fn = cpl_fn;
47 [ + + ]: 102 : if (parent) {
48 : 12 : parent->scsi.ref++;
49 : 12 : task->parent = parent;
50 : 12 : task->tag = parent->tag;
51 : 12 : task->lun_id = parent->lun_id;
52 : 12 : task->scsi.dxfer_dir = parent->scsi.dxfer_dir;
53 : 12 : task->scsi.transfer_len = parent->scsi.transfer_len;
54 : 12 : task->scsi.lun = parent->scsi.lun;
55 : 12 : task->scsi.cdb = parent->scsi.cdb;
56 : 12 : task->scsi.target_port = parent->scsi.target_port;
57 : 12 : task->scsi.initiator_port = parent->scsi.initiator_port;
58 [ + - - + ]: 12 : if (conn && (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
59 : 0 : conn->data_in_cnt++;
60 : : }
61 : : }
62 : :
63 : 102 : task->scsi.iovs = &task->scsi.iov;
64 : 102 : return task;
65 : : }
66 : :
67 : : void
68 : 84 : spdk_scsi_task_put(struct spdk_scsi_task *task)
69 : : {
70 : 84 : free(task);
71 : 84 : }
72 : :
73 : : void
74 : 210 : iscsi_put_pdu(struct spdk_iscsi_pdu *pdu)
75 : : {
76 [ - + ]: 210 : if (!pdu) {
77 : 0 : return;
78 : : }
79 : :
80 : 210 : pdu->ref--;
81 [ - + ]: 210 : if (pdu->ref < 0) {
82 : 0 : CU_FAIL("negative ref count");
83 : 0 : pdu->ref = 0;
84 : : }
85 : :
86 [ + + ]: 210 : if (pdu->ref == 0) {
87 [ + + + + : 207 : if (pdu->data && !pdu->data_from_mempool) {
+ + ]
88 : 54 : free(pdu->data);
89 : : }
90 : 207 : free(pdu);
91 : : }
92 : : }
93 : :
94 : : struct spdk_iscsi_pdu *
95 : 219 : iscsi_get_pdu(struct spdk_iscsi_conn *conn)
96 : : {
97 : : struct spdk_iscsi_pdu *pdu;
98 : :
99 [ - + ]: 219 : assert(conn != NULL);
100 [ + + + + ]: 219 : if (g_pdu_pool_is_empty) {
101 : 6 : return NULL;
102 : : }
103 : :
104 : 213 : pdu = malloc(sizeof(*pdu));
105 [ - + ]: 213 : if (!pdu) {
106 : 0 : return NULL;
107 : : }
108 : :
109 [ - + ]: 213 : memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs));
110 : 213 : pdu->ref = 1;
111 : 213 : pdu->conn = conn;
112 : :
113 : 213 : return pdu;
114 : : }
115 : :
116 : 18 : DEFINE_STUB_V(spdk_scsi_task_process_null_lun, (struct spdk_scsi_task *task));
117 : :
118 : 0 : DEFINE_STUB_V(spdk_scsi_task_process_abort, (struct spdk_scsi_task *task));
119 : :
120 : : void
121 : 12 : spdk_scsi_dev_queue_task(struct spdk_scsi_dev *dev, struct spdk_scsi_task *task)
122 : : {
123 : : struct spdk_scsi_lun *lun;
124 : :
125 : 12 : lun = TAILQ_FIRST(&dev->luns);
126 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(lun != NULL);
127 : :
128 : 12 : TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
129 : 12 : }
130 : :
131 [ - + ]: 12 : 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 : 0 : 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 : 15 : spdk_scsi_dev_get_name(const struct spdk_scsi_dev *dev)
139 : : {
140 [ + - ]: 15 : if (dev != NULL) {
141 : 15 : return dev->name;
142 : : }
143 : :
144 : 0 : return NULL;
145 : : }
146 : :
147 [ # # ]: 0 : 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 : 0 : 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 [ - + ]: 15 : DEFINE_STUB(spdk_scsi_dev_add_port, int,
158 : : (struct spdk_scsi_dev *dev, uint64_t id, const char *name), 0);
159 : :
160 [ - + ]: 3 : DEFINE_STUB(iscsi_drop_conns, int,
161 : : (struct spdk_iscsi_conn *conn, const char *conn_match, int drop_all),
162 : : 0);
163 : :
164 [ - + ]: 15 : DEFINE_STUB(spdk_scsi_dev_delete_port, int,
165 : : (struct spdk_scsi_dev *dev, uint64_t id), 0);
166 : :
167 : 0 : DEFINE_STUB_V(shutdown_iscsi_conns, (void));
168 : :
169 : 0 : DEFINE_STUB_V(iscsi_conns_request_logout, (struct spdk_iscsi_tgt_node *target, int pg_tag));
170 : :
171 [ # # ]: 0 : DEFINE_STUB(iscsi_get_active_conns, int, (struct spdk_iscsi_tgt_node *target), 0);
172 : :
173 : : void
174 : 3 : iscsi_task_cpl(struct spdk_scsi_task *scsi_task)
175 : : {
176 : : struct spdk_iscsi_task *iscsi_task;
177 : :
178 [ + - ]: 3 : if (scsi_task != NULL) {
179 : 3 : iscsi_task = iscsi_task_from_scsi_task(scsi_task);
180 [ - + - - ]: 3 : if (iscsi_task->parent && (iscsi_task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
181 [ # # ]: 0 : assert(iscsi_task->conn->data_in_cnt > 0);
182 : 0 : iscsi_task->conn->data_in_cnt--;
183 : : }
184 : :
185 : 3 : free(iscsi_task);
186 : : }
187 : 3 : }
188 : :
189 : 0 : 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 : 54 : iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int bytes, void *buf)
199 : : {
200 : 54 : uint32_t *data = buf;
201 : : int i;
202 : :
203 [ + + + + ]: 54 : if (g_conn_read_data_digest) {
204 : 3 : MAKE_DIGEST_WORD(buf, g_data_digest);
205 : 3 : return ISCSI_DIGEST_LEN;
206 : : }
207 : :
208 : : /* Limit the length to 4 bytes multiples. */
209 [ - + ]: 51 : SPDK_CU_ASSERT_FATAL((bytes % 4) == 0);
210 : :
211 [ + + ]: 276582 : for (i = 0; i < bytes; i += 4) {
212 : 276531 : data[i / 4] = g_conn_read_len + i;
213 : : }
214 : :
215 : 51 : g_conn_read_len += bytes;
216 : :
217 : 51 : return bytes;
218 : : }
219 : :
220 : : int
221 : 0 : iscsi_conn_readv_data(struct spdk_iscsi_conn *conn, struct iovec *iov, int iovcnt)
222 : : {
223 : 0 : int i, len = 0;
224 : :
225 [ # # ]: 0 : for (i = 0; i < iovcnt; i++) {
226 : 0 : len += iov[i].iov_len;
227 : : }
228 : :
229 : 0 : return len;
230 : : }
231 : :
232 : : void
233 : 141 : 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 : 141 : TAILQ_INSERT_TAIL(&g_write_pdu_list, pdu, tailq);
237 : 141 : }
238 : :
239 : 9 : DEFINE_STUB_V(iscsi_conn_logout, (struct spdk_iscsi_conn *conn));
240 : :
241 : 0 : 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 : 12 : spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
246 : : {
247 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(task->iovs != NULL);
248 : 12 : task->iovs[0].iov_base = data;
249 : 12 : task->iovs[0].iov_len = len;
250 : 12 : }
|