xref: /spdk/test/unit/lib/iscsi/common.c (revision 9efad7468f30e1c5f7442823f5a8b17acd1e6a9b)
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 	struct spdk_scsi_lun *lun;
117 
118 	lun = TAILQ_FIRST(&dev->luns);
119 	SPDK_CU_ASSERT_FATAL(lun != NULL);
120 
121 	TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
122 }
123 
124 DEFINE_STUB(spdk_scsi_dev_find_port_by_id, struct spdk_scsi_port *,
125 	    (struct spdk_scsi_dev *dev, uint64_t id), NULL);
126 
127 DEFINE_STUB_V(spdk_scsi_dev_queue_mgmt_task,
128 	      (struct spdk_scsi_dev *dev, struct spdk_scsi_task *task));
129 
130 const char *
131 spdk_scsi_dev_get_name(const struct spdk_scsi_dev *dev)
132 {
133 	if (dev != NULL) {
134 		return dev->name;
135 	}
136 
137 	return NULL;
138 }
139 
140 DEFINE_STUB(spdk_scsi_dev_construct, struct spdk_scsi_dev *,
141 	    (const char *name, const char **bdev_name_list,
142 	     int *lun_id_list, int num_luns, uint8_t protocol_id,
143 	     void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
144 	     void *hotremove_ctx),
145 	    NULL);
146 
147 DEFINE_STUB_V(spdk_scsi_dev_destruct,
148 	      (struct spdk_scsi_dev *dev, spdk_scsi_dev_destruct_cb_t cb_fn, void *cb_arg));
149 
150 DEFINE_STUB(spdk_scsi_dev_add_port, int,
151 	    (struct spdk_scsi_dev *dev, uint64_t id, const char *name), 0);
152 
153 DEFINE_STUB(iscsi_drop_conns, int,
154 	    (struct spdk_iscsi_conn *conn, const char *conn_match, int drop_all),
155 	    0);
156 
157 DEFINE_STUB(spdk_scsi_dev_delete_port, int,
158 	    (struct spdk_scsi_dev *dev, uint64_t id), 0);
159 
160 DEFINE_STUB_V(shutdown_iscsi_conns, (void));
161 
162 DEFINE_STUB_V(iscsi_conns_request_logout, (struct spdk_iscsi_tgt_node *target, int pg_tag));
163 
164 DEFINE_STUB(iscsi_get_active_conns, int, (struct spdk_iscsi_tgt_node *target), 0);
165 
166 void
167 iscsi_task_cpl(struct spdk_scsi_task *scsi_task)
168 {
169 	struct spdk_iscsi_task *iscsi_task;
170 
171 	if (scsi_task != NULL) {
172 		iscsi_task = iscsi_task_from_scsi_task(scsi_task);
173 		if (iscsi_task->parent && (iscsi_task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
174 			assert(iscsi_task->conn->data_in_cnt > 0);
175 			iscsi_task->conn->data_in_cnt--;
176 		}
177 
178 		free(iscsi_task);
179 	}
180 }
181 
182 DEFINE_STUB_V(iscsi_task_mgmt_cpl, (struct spdk_scsi_task *scsi_task));
183 
184 int
185 iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int bytes, void *buf)
186 {
187 	uint32_t *data = buf;
188 	int i;
189 
190 	/* Limit the length to 4 bytes multiples. */
191 	SPDK_CU_ASSERT_FATAL((bytes % 4) == 0);
192 
193 	for (i = 0; i < bytes; i += 4) {
194 		data[i / 4] = g_conn_read_len + i;
195 	}
196 
197 	g_conn_read_len += bytes;
198 
199 	return bytes;
200 }
201 
202 int
203 iscsi_conn_readv_data(struct spdk_iscsi_conn *conn, struct iovec *iov, int iovcnt)
204 {
205 	int i, len = 0;
206 
207 	for (i = 0; i < iovcnt; i++) {
208 		len += iov[i].iov_len;
209 	}
210 
211 	return len;
212 }
213 
214 void
215 iscsi_conn_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu,
216 		     iscsi_conn_xfer_complete_cb cb_fn, void *cb_arg)
217 {
218 	TAILQ_INSERT_TAIL(&g_write_pdu_list, pdu, tailq);
219 }
220 
221 DEFINE_STUB_V(iscsi_conn_logout, (struct spdk_iscsi_conn *conn));
222 
223 DEFINE_STUB_V(spdk_scsi_task_set_status,
224 	      (struct spdk_scsi_task *task, int sc, int sk, int asc, int ascq));
225 
226 void
227 spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
228 {
229 	SPDK_CU_ASSERT_FATAL(task->iovs != NULL);
230 	task->iovs[0].iov_base = data;
231 	task->iovs[0].iov_len = len;
232 }
233