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 "spdk/stdinc.h"
7 : :
8 : : #include "scsi/task.c"
9 : : #include "scsi/scsi_bdev.c"
10 : : #include "common/lib/test_env.c"
11 : :
12 : : #include "spdk_internal/cunit.h"
13 : :
14 : : #include "spdk_internal/mock.h"
15 : : #include "spdk/bdev_module.h"
16 : :
17 : 5 : SPDK_LOG_REGISTER_COMPONENT(scsi)
18 : :
19 : : static uint64_t g_test_bdev_num_blocks;
20 : :
21 : : TAILQ_HEAD(, spdk_bdev_io) g_bdev_io_queue;
22 : : int g_outstanding_bdev_io_count = 0;
23 : : int g_scsi_cb_called = 0;
24 : :
25 : : TAILQ_HEAD(, spdk_bdev_io_wait_entry) g_io_wait_queue;
26 : : int g_pending_bdev_io_count = 0;
27 : : bool g_bdev_io_pool_full = false;
28 : : int g_bdev_io_pool_count = -1;
29 : :
30 : : bool
31 : 0 : spdk_bdev_io_type_supported(struct spdk_bdev *bdev, enum spdk_bdev_io_type io_type)
32 : : {
33 [ # # ]: 0 : abort();
34 : : return false;
35 : : }
36 : :
37 : 80 : DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *bdev_io));
38 : :
39 : 0 : DEFINE_STUB(spdk_bdev_get_name, const char *,
40 : : (const struct spdk_bdev *bdev), "test");
41 : :
42 : 15 : DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
43 : : (const struct spdk_bdev *bdev), 512);
44 : :
45 : 0 : DEFINE_STUB(spdk_bdev_get_acwu, uint16_t,
46 : : (const struct spdk_bdev *bdev), 1);
47 : :
48 : 30 : DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
49 : : (const struct spdk_bdev *bdev), 8);
50 : :
51 [ + + ]: 15 : DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
52 : : (const struct spdk_bdev *bdev), false);
53 : :
54 : 75 : DEFINE_STUB(spdk_bdev_get_data_block_size, uint32_t,
55 : : (const struct spdk_bdev *bdev), 512);
56 : :
57 : 0 : DEFINE_STUB(spdk_bdev_get_physical_block_size, uint32_t,
58 : : (const struct spdk_bdev *bdev), 4096);
59 : :
60 : : uint64_t
61 : 110 : spdk_bdev_get_num_blocks(const struct spdk_bdev *bdev)
62 : : {
63 : 110 : return g_test_bdev_num_blocks;
64 : : }
65 : :
66 : 1285 : DEFINE_STUB(spdk_bdev_get_product_name, const char *,
67 : : (const struct spdk_bdev *bdev), "test product");
68 : :
69 [ + + ]: 10 : DEFINE_STUB(spdk_bdev_has_write_cache, bool,
70 : : (const struct spdk_bdev *bdev), false);
71 : :
72 : 15 : DEFINE_STUB(spdk_bdev_get_dif_type, enum spdk_dif_type,
73 : : (const struct spdk_bdev *bdev), SPDK_DIF_DISABLE);
74 : :
75 [ + + ]: 15 : DEFINE_STUB(spdk_bdev_is_dif_head_of_md, bool,
76 : : (const struct spdk_bdev *bdev), false);
77 : :
78 [ + + ]: 30 : DEFINE_STUB(spdk_bdev_is_dif_check_enabled, bool,
79 : : (const struct spdk_bdev *bdev, enum spdk_dif_check_type check_type), false);
80 : :
81 : 0 : DEFINE_STUB(scsi_pr_out, int, (struct spdk_scsi_task *task,
82 : : uint8_t *cdb, uint8_t *data, uint16_t data_len), 0);
83 : :
84 : 0 : DEFINE_STUB(scsi_pr_in, int, (struct spdk_scsi_task *task, uint8_t *cdb,
85 : : uint8_t *data, uint16_t data_len), 0);
86 : :
87 : 0 : DEFINE_STUB(scsi2_reserve, int, (struct spdk_scsi_task *task, uint8_t *cdb), 0);
88 : 0 : DEFINE_STUB(scsi2_release, int, (struct spdk_scsi_task *task), 0);
89 : :
90 : : void
91 : 80 : scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
92 : : {
93 [ + - ]: 80 : g_scsi_cb_called++;
94 : 80 : }
95 : :
96 : 0 : DEFINE_STUB_V(scsi_lun_complete_reset_task,
97 : : (struct spdk_scsi_lun *lun, struct spdk_scsi_task *task));
98 : :
99 : 0 : DEFINE_STUB(spdk_scsi_lun_id_int_to_fmt, uint64_t, (int lun_id), 0);
100 : :
101 : 0 : DEFINE_STUB(spdk_scsi_dev_get_first_lun, struct spdk_scsi_lun *,
102 : : (struct spdk_scsi_dev *dev), NULL);
103 : :
104 : 0 : DEFINE_STUB(spdk_scsi_dev_get_next_lun, struct spdk_scsi_lun *,
105 : : (struct spdk_scsi_lun *prev_lun), NULL);
106 : :
107 : 0 : DEFINE_STUB(spdk_scsi_sbc_opcode_string, const char *,
108 : : (uint8_t opcode, uint16_t sa), "UNKNOWN");
109 : :
110 : : static void
111 : 1370 : ut_put_task(struct spdk_scsi_task *task)
112 : : {
113 [ + + + - : 1370 : if (task->alloc_len) {
+ + ]
114 [ + - + - : 15 : free(task->iov.iov_base);
+ - ]
115 : 3 : }
116 : :
117 [ + - + - : 1370 : task->iov.iov_base = NULL;
+ - ]
118 [ + - + - : 1370 : task->iov.iov_len = 0;
+ - ]
119 [ + - + - ]: 1370 : task->alloc_len = 0;
120 [ + + # # ]: 1370 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
121 : 1370 : }
122 : :
123 : : static void
124 : 1370 : ut_init_task(struct spdk_scsi_task *task)
125 : : {
126 [ + + ]: 1370 : memset(task, 0xFF, sizeof(*task));
127 [ + - + - : 1370 : task->iov.iov_base = NULL;
+ - ]
128 [ + - + - : 1370 : task->iovs = &task->iov;
+ - ]
129 [ + - + - ]: 1370 : task->iovcnt = 1;
130 [ + - + - ]: 1370 : task->alloc_len = 0;
131 [ + - + - ]: 1370 : task->dxfer_dir = SPDK_SCSI_DIR_NONE;
132 : 1370 : }
133 : :
134 : : void
135 : 65 : spdk_bdev_io_get_scsi_status(const struct spdk_bdev_io *bdev_io,
136 : : int *sc, int *sk, int *asc, int *ascq)
137 : : {
138 [ + - + + : 65 : switch (bdev_io->internal.status) {
+ - + + -
+ ]
139 : 44 : case SPDK_BDEV_IO_STATUS_SUCCESS:
140 [ + - ]: 55 : *sc = SPDK_SCSI_STATUS_GOOD;
141 [ + - ]: 55 : *sk = SPDK_SCSI_SENSE_NO_SENSE;
142 [ + - ]: 55 : *asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
143 [ + - ]: 55 : *ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
144 : 55 : break;
145 : 0 : case SPDK_BDEV_IO_STATUS_MISCOMPARE:
146 [ # # ]: 0 : *sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
147 [ # # ]: 0 : *sk = SPDK_SCSI_SENSE_MISCOMPARE;
148 [ # # ]: 0 : *asc = SPDK_SCSI_ASC_MISCOMPARE_DURING_VERIFY_OPERATION;
149 [ # # # # : 0 : *ascq = bdev_io->internal.error.scsi.ascq;
# # # # #
# # # ]
150 : 0 : break;
151 : 4 : case SPDK_BDEV_IO_STATUS_SCSI_ERROR:
152 [ + - + - : 5 : *sc = bdev_io->internal.error.scsi.sc;
+ - + - +
- + - ]
153 [ + - + - : 5 : *sk = bdev_io->internal.error.scsi.sk;
+ - + - +
- + - ]
154 [ + - + - : 5 : *asc = bdev_io->internal.error.scsi.asc;
+ - + - +
- + - ]
155 [ + - + - : 5 : *ascq = bdev_io->internal.error.scsi.ascq;
+ - + - +
- + - ]
156 : 5 : break;
157 : 4 : default:
158 [ + - ]: 5 : *sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
159 [ + - ]: 5 : *sk = SPDK_SCSI_SENSE_ABORTED_COMMAND;
160 [ + - ]: 5 : *asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
161 [ + - ]: 5 : *ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
162 : 5 : break;
163 : : }
164 : 65 : }
165 : :
166 : : void
167 : 0 : spdk_bdev_io_get_iovec(struct spdk_bdev_io *bdev_io, struct iovec **iovp, int *iovcntp)
168 : : {
169 [ # # ]: 0 : *iovp = NULL;
170 [ # # ]: 0 : *iovcntp = 0;
171 : 0 : }
172 : :
173 : : static void
174 : 90 : ut_bdev_io_complete(void)
175 : : {
176 : 18 : struct spdk_bdev_io *bdev_io;
177 : :
178 [ + + ]: 221 : while (!TAILQ_EMPTY(&g_bdev_io_queue)) {
179 : 95 : bdev_io = TAILQ_FIRST(&g_bdev_io_queue);
180 [ + + + - : 95 : TAILQ_REMOVE(&g_bdev_io_queue, bdev_io, internal.link);
+ - + - +
+ + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
- + - + -
+ - + - +
+ - + - +
- + - + -
+ - + - +
- + - ]
181 [ + - + - : 95 : bdev_io->internal.cb(bdev_io, true, bdev_io->internal.caller_ctx);
+ - - + +
- + - + -
+ - ]
182 : 95 : free(bdev_io);
183 [ + - ]: 95 : g_outstanding_bdev_io_count--;
184 [ + + ]: 95 : if (g_bdev_io_pool_count != -1) {
185 [ + - ]: 25 : g_bdev_io_pool_count++;
186 : 5 : }
187 : : }
188 : 90 : }
189 : :
190 : : static void
191 : 90 : ut_bdev_io_retry(void)
192 : : {
193 : 18 : struct spdk_bdev_io_wait_entry *entry;
194 : :
195 [ + + ]: 120 : while (!TAILQ_EMPTY(&g_io_wait_queue)) {
196 : 30 : entry = TAILQ_FIRST(&g_io_wait_queue);
197 [ + + + - : 30 : TAILQ_REMOVE(&g_io_wait_queue, entry, link);
+ - - + #
# # # # #
# # # # #
# # # # #
# # - + -
+ - + - +
+ - + - +
- + - + -
+ - + - ]
198 [ + - ]: 30 : g_pending_bdev_io_count--;
199 [ + - + - : 30 : entry->cb_fn(entry->cb_arg);
- + + - +
- + - ]
200 : : }
201 : 90 : }
202 : :
203 : : static void
204 : 60 : ut_bdev_io_flush(void)
205 : : {
206 [ + + + + ]: 140 : while (!TAILQ_EMPTY(&g_bdev_io_queue) || !TAILQ_EMPTY(&g_io_wait_queue)) {
207 : 80 : ut_bdev_io_complete();
208 : 80 : ut_bdev_io_retry();
209 : : }
210 : 60 : }
211 : :
212 : : static int
213 : 135 : _spdk_bdev_io_op(spdk_bdev_io_completion_cb cb, void *cb_arg)
214 : : {
215 : 27 : struct spdk_bdev_io *bdev_io;
216 : :
217 [ + + + + ]: 135 : if (g_bdev_io_pool_full) {
218 : 30 : g_bdev_io_pool_full = false;
219 : 30 : return -ENOMEM;
220 [ + + ]: 105 : } else if (g_bdev_io_pool_count == 0) {
221 : 10 : return -ENOMEM;
222 [ + + ]: 95 : } else if (g_bdev_io_pool_count != -1) {
223 [ + - ]: 25 : g_bdev_io_pool_count--;
224 : 5 : }
225 : :
226 : 95 : bdev_io = calloc(1, sizeof(*bdev_io));
227 [ + + # # ]: 95 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
228 [ + - + - : 95 : bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
+ - ]
229 [ + - + - : 95 : bdev_io->internal.cb = cb;
+ - ]
230 [ + - + - : 95 : bdev_io->internal.caller_ctx = cb_arg;
+ - ]
231 : :
232 [ + - + - : 95 : TAILQ_INSERT_TAIL(&g_bdev_io_queue, bdev_io, internal.link);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
233 [ + - ]: 95 : g_outstanding_bdev_io_count++;
234 : :
235 : 95 : return 0;
236 : 27 : }
237 : :
238 : : int
239 : 35 : spdk_bdev_readv_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
240 : : struct iovec *iov, int iovcnt,
241 : : uint64_t offset_blocks, uint64_t num_blocks,
242 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
243 : : {
244 : 35 : return _spdk_bdev_io_op(cb, cb_arg);
245 : : }
246 : :
247 : : int
248 : 15 : spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
249 : : struct iovec *iov, int iovcnt,
250 : : uint64_t offset_blocks, uint64_t num_blocks,
251 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
252 : : {
253 : 15 : return _spdk_bdev_io_op(cb, cb_arg);
254 : : }
255 : :
256 : : int
257 : 0 : spdk_bdev_comparev_and_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
258 : : struct iovec *compare_iov, int compare_iovcnt,
259 : : struct iovec *write_iov, int write_iovcnt,
260 : : uint64_t offset_blocks, uint64_t num_blocks,
261 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
262 : : {
263 : 0 : return _spdk_bdev_io_op(cb, cb_arg);
264 : : }
265 : :
266 : : int
267 : 70 : spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
268 : : uint64_t offset_blocks, uint64_t num_blocks,
269 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
270 : : {
271 : 70 : return _spdk_bdev_io_op(cb, cb_arg);
272 : : }
273 : :
274 : : int
275 : 0 : spdk_bdev_reset(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
276 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
277 : : {
278 : 0 : return _spdk_bdev_io_op(cb, cb_arg);
279 : : }
280 : :
281 : : int
282 : 15 : spdk_bdev_flush_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
283 : : uint64_t offset_blocks, uint64_t num_blocks,
284 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
285 : : {
286 : 15 : return _spdk_bdev_io_op(cb, cb_arg);
287 : : }
288 : :
289 : : int
290 : 30 : spdk_bdev_queue_io_wait(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
291 : : struct spdk_bdev_io_wait_entry *entry)
292 : : {
293 [ + - + - : 30 : TAILQ_INSERT_TAIL(&g_io_wait_queue, entry, link);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
294 [ + - ]: 30 : g_pending_bdev_io_count++;
295 : 30 : return 0;
296 : : }
297 : :
298 : : int
299 : 15 : spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
300 : : bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
301 : : uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
302 : : uint32_t data_offset, uint64_t guard_seed, struct spdk_dif_ctx_init_ext_opts *opts)
303 : : {
304 [ + - + - : 15 : ctx->dif_pi_format = opts->dif_pi_format;
+ - + - ]
305 [ + - + - ]: 15 : ctx->init_ref_tag = init_ref_tag;
306 [ + - + - : 15 : ctx->ref_tag_offset = data_offset / 512;
+ - ]
307 : 15 : return 0;
308 : : }
309 : :
310 : : /*
311 : : * This test specifically tests a mode select 6 command from the
312 : : * Windows SCSI compliance test that caused SPDK to crash.
313 : : */
314 : : static void
315 : 5 : mode_select_6_test(void)
316 : : {
317 : 4 : struct spdk_bdev bdev;
318 : 4 : struct spdk_scsi_task task;
319 : 4 : struct spdk_scsi_lun lun;
320 : 4 : struct spdk_scsi_dev dev;
321 : 4 : char cdb[16];
322 : 4 : char data[24];
323 : 1 : int rc;
324 : :
325 : 5 : ut_init_task(&task);
326 : :
327 [ + - + - ]: 5 : cdb[0] = 0x15;
328 [ + - + - : 5 : cdb[1] = 0x11;
+ - ]
329 [ + - + - : 5 : cdb[2] = 0x00;
+ - ]
330 [ + - + - : 5 : cdb[3] = 0x00;
+ - ]
331 [ + - + - : 5 : cdb[4] = 0x18;
+ - ]
332 [ + - + - : 5 : cdb[5] = 0x00;
+ - ]
333 [ + - ]: 5 : task.cdb = cdb;
334 : :
335 [ + + + - ]: 5 : snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
336 [ + - ]: 5 : lun.bdev = &bdev;
337 [ + - ]: 5 : lun.dev = &dev;
338 [ + - ]: 5 : task.lun = &lun;
339 : :
340 [ + + ]: 5 : memset(data, 0, sizeof(data));
341 [ + - + - : 5 : data[4] = 0x08;
+ - ]
342 [ + - + - : 5 : data[5] = 0x02;
+ - ]
343 : 5 : spdk_scsi_task_set_data(&task, data, sizeof(data));
344 : :
345 : 5 : rc = bdev_scsi_execute(&task);
346 : :
347 : 5 : CU_ASSERT_EQUAL(rc, 0);
348 : :
349 : 5 : ut_put_task(&task);
350 : 5 : }
351 : :
352 : : /*
353 : : * This test specifically tests a mode select 6 command which
354 : : * contains no mode pages.
355 : : */
356 : : static void
357 : 5 : mode_select_6_test2(void)
358 : : {
359 : 4 : struct spdk_bdev bdev;
360 : 4 : struct spdk_scsi_task task;
361 : 4 : struct spdk_scsi_lun lun;
362 : 4 : struct spdk_scsi_dev dev;
363 : 4 : char cdb[16];
364 : 1 : int rc;
365 : :
366 : 5 : ut_init_task(&task);
367 : :
368 [ + - + - ]: 5 : cdb[0] = 0x15;
369 [ + - + - : 5 : cdb[1] = 0x00;
+ - ]
370 [ + - + - : 5 : cdb[2] = 0x00;
+ - ]
371 [ + - + - : 5 : cdb[3] = 0x00;
+ - ]
372 [ + - + - : 5 : cdb[4] = 0x00;
+ - ]
373 [ + - + - : 5 : cdb[5] = 0x00;
+ - ]
374 [ + - ]: 5 : task.cdb = cdb;
375 : :
376 [ + + + - ]: 5 : snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
377 [ + - ]: 5 : lun.bdev = &bdev;
378 [ + - ]: 5 : lun.dev = &dev;
379 [ + - ]: 5 : task.lun = &lun;
380 : :
381 : 5 : rc = bdev_scsi_execute(&task);
382 : :
383 : 5 : CU_ASSERT_EQUAL(rc, 0);
384 : :
385 : 5 : ut_put_task(&task);
386 : 5 : }
387 : :
388 : : /*
389 : : * This test specifically tests a mode sense 6 command which
390 : : * return all subpage 00h mode pages.
391 : : */
392 : : static void
393 : 5 : mode_sense_6_test(void)
394 : : {
395 : 4 : struct spdk_bdev bdev;
396 : 4 : struct spdk_scsi_task task;
397 : 4 : struct spdk_scsi_lun lun;
398 : 4 : struct spdk_scsi_dev dev;
399 : 4 : char cdb[12];
400 : 1 : unsigned char *data;
401 : 1 : int rc;
402 : 5 : unsigned char mode_data_len = 0;
403 : 5 : unsigned char medium_type = 0;
404 : 5 : unsigned char dev_specific_param = 0;
405 : 5 : unsigned char blk_descriptor_len = 0;
406 : :
407 [ + + ]: 5 : memset(&bdev, 0, sizeof(struct spdk_bdev));
408 : 5 : ut_init_task(&task);
409 [ + + ]: 5 : memset(cdb, 0, sizeof(cdb));
410 : :
411 [ + - + - ]: 5 : cdb[0] = 0x1A;
412 [ + - + - : 5 : cdb[2] = 0x3F;
+ - ]
413 [ + - + - : 5 : cdb[4] = 0xFF;
+ - ]
414 [ + - ]: 5 : task.cdb = cdb;
415 : :
416 [ + + + - ]: 5 : snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
417 [ + - ]: 5 : lun.bdev = &bdev;
418 [ + - ]: 5 : lun.dev = &dev;
419 [ + - ]: 5 : task.lun = &lun;
420 : :
421 : 5 : rc = bdev_scsi_execute(&task);
422 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(rc == 0);
423 : :
424 [ + - + - : 5 : data = task.iovs[0].iov_base;
+ - + - ]
425 [ + - + - ]: 5 : mode_data_len = data[0];
426 [ + - + - ]: 5 : medium_type = data[1];
427 [ + - + - ]: 5 : dev_specific_param = data[2];
428 [ + - + - ]: 5 : blk_descriptor_len = data[3];
429 : :
430 : 5 : CU_ASSERT(mode_data_len >= 11);
431 : 5 : CU_ASSERT_EQUAL(medium_type, 0);
432 : 5 : CU_ASSERT_EQUAL(dev_specific_param, 0);
433 : 5 : CU_ASSERT_EQUAL(blk_descriptor_len, 8);
434 : :
435 : 5 : ut_put_task(&task);
436 : 5 : }
437 : :
438 : : /*
439 : : * This test specifically tests a mode sense 10 command which
440 : : * return all subpage 00h mode pages.
441 : : */
442 : : static void
443 : 5 : mode_sense_10_test(void)
444 : : {
445 : 4 : struct spdk_bdev bdev;
446 : 4 : struct spdk_scsi_task task;
447 : 4 : struct spdk_scsi_lun lun;
448 : 4 : struct spdk_scsi_dev dev;
449 : 4 : char cdb[12];
450 : 1 : unsigned char *data;
451 : 1 : int rc;
452 : 5 : unsigned short mode_data_len = 0;
453 : 5 : unsigned char medium_type = 0;
454 : 5 : unsigned char dev_specific_param = 0;
455 : 5 : unsigned short blk_descriptor_len = 0;
456 : :
457 [ + + ]: 5 : memset(&bdev, 0, sizeof(struct spdk_bdev));
458 : 5 : ut_init_task(&task);
459 [ + + ]: 5 : memset(cdb, 0, sizeof(cdb));
460 [ + - + - ]: 5 : cdb[0] = 0x5A;
461 [ + - + - : 5 : cdb[2] = 0x3F;
+ - ]
462 [ + - + - : 5 : cdb[8] = 0xFF;
+ - ]
463 [ + - ]: 5 : task.cdb = cdb;
464 : :
465 [ + + + - ]: 5 : snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
466 [ + - ]: 5 : lun.bdev = &bdev;
467 [ + - ]: 5 : lun.dev = &dev;
468 [ + - ]: 5 : task.lun = &lun;
469 : :
470 : 5 : rc = bdev_scsi_execute(&task);
471 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(rc == 0);
472 : :
473 [ + - + - : 5 : data = task.iovs[0].iov_base;
+ - + - ]
474 [ + + + - : 5 : mode_data_len = ((data[0] << 8) + data[1]);
- + + - +
- + - +
- ]
475 [ + - + - ]: 5 : medium_type = data[2];
476 [ + - + - ]: 5 : dev_specific_param = data[3];
477 [ + + + - : 5 : blk_descriptor_len = ((data[6] << 8) + data[7]);
- + + - +
- + - +
- ]
478 : :
479 : 5 : CU_ASSERT(mode_data_len >= 14);
480 : 5 : CU_ASSERT_EQUAL(medium_type, 0);
481 : 5 : CU_ASSERT_EQUAL(dev_specific_param, 0);
482 : 5 : CU_ASSERT_EQUAL(blk_descriptor_len, 8);
483 : :
484 : 5 : ut_put_task(&task);
485 : 5 : }
486 : :
487 : : /*
488 : : * This test specifically tests a scsi inquiry command from the
489 : : * Windows SCSI compliance test that failed to return the
490 : : * expected SCSI error sense code.
491 : : */
492 : : static void
493 : 5 : inquiry_evpd_test(void)
494 : : {
495 : 4 : struct spdk_bdev bdev;
496 : 4 : struct spdk_scsi_task task;
497 : 4 : struct spdk_scsi_lun lun;
498 : 4 : struct spdk_scsi_dev dev;
499 : 4 : char cdb[6];
500 : 1 : int rc;
501 : :
502 : 5 : ut_init_task(&task);
503 : :
504 [ + - + - ]: 5 : cdb[0] = 0x12;
505 [ + - + - : 5 : cdb[1] = 0x00; /* EVPD = 0 */
+ - ]
506 [ + - + - : 5 : cdb[2] = 0xff; /* PageCode non-zero */
+ - ]
507 [ + - + - : 5 : cdb[3] = 0x00;
+ - ]
508 [ + - + - : 5 : cdb[4] = 0xff;
+ - ]
509 [ + - + - : 5 : cdb[5] = 0x00;
+ - ]
510 [ + - ]: 5 : task.cdb = cdb;
511 : :
512 [ + + + - ]: 5 : snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
513 [ + - ]: 5 : lun.bdev = &bdev;
514 [ + - ]: 5 : lun.dev = &dev;
515 [ + - ]: 5 : task.lun = &lun;
516 : :
517 : 5 : rc = bdev_scsi_execute(&task);
518 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(rc == 0);
519 : :
520 : 5 : CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
521 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
+ - ]
522 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[12], 0x24);
+ - ]
523 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[13], 0x0);
+ - ]
524 : :
525 : 5 : ut_put_task(&task);
526 : 5 : }
527 : :
528 : : /*
529 : : * This test is to verify specific return data for a standard scsi inquiry
530 : : * command: Version
531 : : */
532 : : static void
533 : 5 : inquiry_standard_test(void)
534 : : {
535 : 5 : struct spdk_bdev bdev = { .blocklen = 512 };
536 : 4 : struct spdk_scsi_task task;
537 : 4 : struct spdk_scsi_lun lun;
538 : 4 : struct spdk_scsi_dev dev;
539 : 4 : char cdb[6];
540 : 1 : char *data;
541 : 1 : struct spdk_scsi_cdb_inquiry_data *inq_data;
542 : 1 : int rc;
543 : :
544 : 5 : ut_init_task(&task);
545 : :
546 [ + - + - ]: 5 : cdb[0] = 0x12;
547 [ + - + - : 5 : cdb[1] = 0x00; /* EVPD = 0 */
+ - ]
548 [ + - + - : 5 : cdb[2] = 0x00; /* PageCode zero - requesting standard inquiry */
+ - ]
549 [ + - + - : 5 : cdb[3] = 0x00;
+ - ]
550 [ + - + - : 5 : cdb[4] = 0xff; /* Indicate data size used by conformance test */
+ - ]
551 [ + - + - : 5 : cdb[5] = 0x00;
+ - ]
552 [ + - ]: 5 : task.cdb = cdb;
553 : :
554 [ + + + - ]: 5 : snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
555 [ + - ]: 5 : lun.bdev = &bdev;
556 [ + - ]: 5 : lun.dev = &dev;
557 [ + - ]: 5 : task.lun = &lun;
558 : :
559 : 5 : rc = bdev_scsi_execute(&task);
560 : :
561 [ + - + - : 5 : data = task.iovs[0].iov_base;
+ - + - ]
562 [ + - ]: 5 : inq_data = (struct spdk_scsi_cdb_inquiry_data *)&data[0];
563 : :
564 [ + - + - ]: 5 : CU_ASSERT_EQUAL(inq_data->version, SPDK_SPC_VERSION_SPC3);
565 : 5 : CU_ASSERT_EQUAL(rc, 0);
566 : :
567 : 5 : ut_put_task(&task);
568 : 5 : }
569 : :
570 : : static void
571 : 1280 : _inquiry_overflow_test(uint8_t alloc_len)
572 : : {
573 : 1280 : struct spdk_bdev bdev = { .blocklen = 512 };
574 : 1024 : struct spdk_scsi_task task;
575 : 1024 : struct spdk_scsi_lun lun;
576 : 1024 : struct spdk_scsi_dev dev;
577 : 1024 : uint8_t cdb[6];
578 : 256 : int rc;
579 : : /* expects a 4K internal data buffer */
580 : 1024 : char data[4096], data_compare[4096];
581 : :
582 : 1280 : ut_init_task(&task);
583 : :
584 [ + - + - ]: 1280 : cdb[0] = 0x12;
585 [ + - + - : 1280 : cdb[1] = 0x00; /* EVPD = 0 */
+ - ]
586 [ + - + - : 1280 : cdb[2] = 0x00; /* PageCode zero - requesting standard inquiry */
+ - ]
587 [ + - + - : 1280 : cdb[3] = 0x00;
+ - ]
588 [ + - + - : 1280 : cdb[4] = alloc_len; /* Indicate data size used by conformance test */
+ - ]
589 [ + - + - : 1280 : cdb[5] = 0x00;
+ - ]
590 [ + - ]: 1280 : task.cdb = cdb;
591 : :
592 [ + - + - ]: 1280 : snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
593 [ + - ]: 1280 : lun.bdev = &bdev;
594 [ + - ]: 1280 : lun.dev = &dev;
595 [ + - ]: 1280 : task.lun = &lun;
596 : :
597 [ + - ]: 1280 : memset(data, 0, sizeof(data));
598 [ + - ]: 1280 : memset(data_compare, 0, sizeof(data_compare));
599 : :
600 : 1280 : spdk_scsi_task_set_data(&task, data, sizeof(data));
601 : :
602 : 1280 : rc = bdev_scsi_execute(&task);
603 [ + + # # ]: 1280 : SPDK_CU_ASSERT_FATAL(rc == 0);
604 : :
605 [ + + + + : 1280 : CU_ASSERT_EQUAL(memcmp(data + alloc_len, data_compare + alloc_len, sizeof(data) - alloc_len), 0);
+ - + - +
- + - ]
606 [ + - ]: 1280 : CU_ASSERT(task.data_transferred <= alloc_len);
607 : :
608 : 1280 : ut_put_task(&task);
609 : 1280 : }
610 : :
611 : : static void
612 : 5 : inquiry_overflow_test(void)
613 : : {
614 : 1 : int i;
615 : :
616 [ + + - + ]: 1285 : for (i = 0; i < 256; i++) {
617 : 1280 : _inquiry_overflow_test(i);
618 : 256 : }
619 : 5 : }
620 : :
621 : : static void
622 : 5 : scsi_name_padding_test(void)
623 : : {
624 : 4 : char name[SPDK_SCSI_DEV_MAX_NAME + 1];
625 : 4 : char buf[SPDK_SCSI_DEV_MAX_NAME + 1];
626 : 1 : int written, i;
627 : :
628 : : /* case 1 */
629 [ + + ]: 5 : memset(name, '\0', sizeof(name));
630 [ + + ]: 5 : memset(name, 'x', 251);
631 : 5 : written = bdev_scsi_pad_scsi_name(buf, name);
632 : :
633 : 5 : CU_ASSERT(written == 252);
634 [ + - + - : 5 : CU_ASSERT(buf[250] == 'x');
+ - ]
635 [ + - + - : 5 : CU_ASSERT(buf[251] == '\0');
+ - ]
636 : :
637 : : /* case 2: */
638 [ + + ]: 5 : memset(name, '\0', sizeof(name));
639 [ + + ]: 5 : memset(name, 'x', 252);
640 : 5 : written = bdev_scsi_pad_scsi_name(buf, name);
641 : :
642 : 5 : CU_ASSERT(written == 256);
643 [ + - + - : 5 : CU_ASSERT(buf[251] == 'x');
+ - ]
644 [ + + + - ]: 25 : for (i = 252; i < 256; i++) {
645 [ + - + - : 20 : CU_ASSERT(buf[i] == '\0');
+ - ]
646 : 4 : }
647 : :
648 : : /* case 3 */
649 [ + + ]: 5 : memset(name, '\0', sizeof(name));
650 [ + + ]: 5 : memset(name, 'x', 255);
651 : 5 : written = bdev_scsi_pad_scsi_name(buf, name);
652 : :
653 : 5 : CU_ASSERT(written == 256);
654 [ + - + - : 5 : CU_ASSERT(buf[254] == 'x');
+ - ]
655 [ + - + - : 5 : CU_ASSERT(buf[255] == '\0');
+ - ]
656 : 5 : }
657 : :
658 : : /*
659 : : * This test is to verify specific error translation from bdev to scsi.
660 : : */
661 : : static void
662 : 5 : task_complete_test(void)
663 : : {
664 : 4 : struct spdk_scsi_task task;
665 : 5 : struct spdk_bdev_io bdev_io = {};
666 : 4 : struct spdk_scsi_lun lun;
667 : :
668 : 5 : ut_init_task(&task);
669 : :
670 [ + - + - : 5 : TAILQ_INIT(&lun.tasks);
+ - + - +
- ]
671 [ + - + - : 5 : TAILQ_INSERT_TAIL(&lun.tasks, &task, scsi_link);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
672 [ + - ]: 5 : task.lun = &lun;
673 : :
674 [ + - + - ]: 5 : bdev_io.internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
675 [ + - + - ]: 5 : bdev_scsi_task_complete_cmd(&bdev_io, bdev_io.internal.status, &task);
676 : 5 : CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD);
677 : 5 : CU_ASSERT(g_scsi_cb_called == 1);
678 : 5 : g_scsi_cb_called = 0;
679 : :
680 [ + - + - ]: 5 : bdev_io.internal.status = SPDK_BDEV_IO_STATUS_SCSI_ERROR;
681 [ + - + - : 5 : bdev_io.internal.error.scsi.sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
+ - + - ]
682 [ + - + - : 5 : bdev_io.internal.error.scsi.sk = SPDK_SCSI_SENSE_HARDWARE_ERROR;
+ - + - ]
683 [ + - + - : 5 : bdev_io.internal.error.scsi.asc = SPDK_SCSI_ASC_WARNING;
+ - + - ]
684 [ + - + - : 5 : bdev_io.internal.error.scsi.ascq = SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED;
+ - + - ]
685 [ + - + - ]: 5 : bdev_scsi_task_complete_cmd(&bdev_io, bdev_io.internal.status, &task);
686 : 5 : CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
687 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_HARDWARE_ERROR);
+ - ]
688 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_WARNING);
+ - ]
689 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED);
+ - ]
690 : 5 : CU_ASSERT(g_scsi_cb_called == 1);
691 : 5 : g_scsi_cb_called = 0;
692 : :
693 [ + - + - ]: 5 : bdev_io.internal.status = SPDK_BDEV_IO_STATUS_FAILED;
694 [ + - + - ]: 5 : bdev_scsi_task_complete_cmd(&bdev_io, bdev_io.internal.status, &task);
695 : 5 : CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
696 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ABORTED_COMMAND);
+ - ]
697 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
+ - ]
698 [ + - + - : 5 : CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
+ - ]
699 : 5 : CU_ASSERT(g_scsi_cb_called == 1);
700 : 5 : g_scsi_cb_called = 0;
701 : :
702 : 5 : ut_put_task(&task);
703 : 5 : }
704 : :
705 : : static void
706 : 5 : lba_range_test(void)
707 : : {
708 : 5 : struct spdk_bdev bdev = { .blocklen = 512 };
709 : 4 : struct spdk_scsi_lun lun;
710 : 4 : struct spdk_scsi_task task;
711 : 4 : uint8_t cdb[16];
712 : 1 : int rc;
713 : :
714 [ + - ]: 5 : lun.bdev = &bdev;
715 : :
716 : 5 : ut_init_task(&task);
717 [ + - ]: 5 : task.lun = &lun;
718 [ + - + - : 5 : task.lun->bdev_desc = NULL;
+ - ]
719 [ + - + - : 5 : task.lun->io_channel = NULL;
+ - ]
720 [ + - ]: 5 : task.cdb = cdb;
721 : :
722 [ + + ]: 5 : memset(cdb, 0, sizeof(cdb));
723 [ + - + - ]: 5 : cdb[0] = 0x88; /* READ (16) */
724 : :
725 : : /* Test block device size of 4 blocks */
726 : 5 : g_test_bdev_num_blocks = 4;
727 : :
728 : : /* LBA = 0, length = 1 (in range) */
729 [ + - + - ]: 5 : to_be64(&cdb[2], 0); /* LBA */
730 [ + - + - ]: 5 : to_be32(&cdb[10], 1); /* transfer length */
731 [ + - ]: 5 : task.transfer_len = 1 * 512;
732 [ + - ]: 5 : task.offset = 0;
733 [ + - ]: 5 : task.length = 1 * 512;
734 : 5 : rc = bdev_scsi_execute(&task);
735 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
736 : 5 : CU_ASSERT(task.status == 0xFF);
737 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_bdev_io_queue));
738 : 5 : ut_bdev_io_flush();
739 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
740 : 5 : CU_ASSERT(g_scsi_cb_called == 1);
741 : 5 : g_scsi_cb_called = 0;
742 : :
743 : : /* LBA = 4, length = 1 (LBA out of range) */
744 [ + - + - ]: 5 : to_be64(&cdb[2], 4); /* LBA */
745 [ + - + - ]: 5 : to_be32(&cdb[10], 1); /* transfer length */
746 [ + - ]: 5 : task.transfer_len = 1 * 512;
747 [ + - ]: 5 : task.offset = 0;
748 [ + - ]: 5 : task.length = 1 * 512;
749 : 5 : rc = bdev_scsi_execute(&task);
750 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
751 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
752 [ + - + - : 5 : CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);
+ - ]
753 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
754 : :
755 : : /* LBA = 0, length = 4 (in range, max valid size) */
756 [ + - + - ]: 5 : to_be64(&cdb[2], 0); /* LBA */
757 [ + - + - ]: 5 : to_be32(&cdb[10], 4); /* transfer length */
758 [ + - ]: 5 : task.transfer_len = 4 * 512;
759 : 5 : task.status = 0xFF;
760 [ + - ]: 5 : task.offset = 0;
761 [ + - ]: 5 : task.length = 1 * 512;
762 : 5 : rc = bdev_scsi_execute(&task);
763 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
764 : 5 : CU_ASSERT(task.status == 0xFF);
765 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_bdev_io_queue));
766 : 5 : ut_bdev_io_flush();
767 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
768 : 5 : CU_ASSERT(g_scsi_cb_called == 1);
769 : 5 : g_scsi_cb_called = 0;
770 : :
771 : : /* LBA = 0, length = 5 (LBA in range, length beyond end of bdev) */
772 [ + - + - ]: 5 : to_be64(&cdb[2], 0); /* LBA */
773 [ + - + - ]: 5 : to_be32(&cdb[10], 5); /* transfer length */
774 [ + - ]: 5 : task.transfer_len = 5 * 512;
775 [ + - ]: 5 : task.offset = 0;
776 [ + - ]: 5 : task.length = 1 * 512;
777 : 5 : rc = bdev_scsi_execute(&task);
778 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
779 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
780 [ + - + - : 5 : CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);
+ - ]
781 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
782 : :
783 : 5 : ut_put_task(&task);
784 : 5 : }
785 : :
786 : : static void
787 : 5 : xfer_len_test(void)
788 : : {
789 : 5 : struct spdk_bdev bdev = { .blocklen = 512 };
790 : 4 : struct spdk_scsi_lun lun;
791 : 4 : struct spdk_scsi_task task;
792 : 4 : uint8_t cdb[16];
793 : 1 : int rc;
794 : :
795 [ + - ]: 5 : lun.bdev = &bdev;
796 : :
797 : 5 : ut_init_task(&task);
798 [ + - ]: 5 : task.lun = &lun;
799 [ + - + - : 5 : task.lun->bdev_desc = NULL;
+ - ]
800 [ + - + - : 5 : task.lun->io_channel = NULL;
+ - ]
801 [ + - ]: 5 : task.cdb = cdb;
802 : :
803 [ + + ]: 5 : memset(cdb, 0, sizeof(cdb));
804 [ + - + - ]: 5 : cdb[0] = 0x88; /* READ (16) */
805 : :
806 : : /* Test block device size of 512 MiB */
807 : 5 : g_test_bdev_num_blocks = 512 * 1024 * 1024;
808 : :
809 : : /* 1 block */
810 [ + - + - ]: 5 : to_be64(&cdb[2], 0); /* LBA */
811 [ + - + - ]: 5 : to_be32(&cdb[10], 1); /* transfer length */
812 [ + - ]: 5 : task.transfer_len = 1 * 512;
813 [ + - ]: 5 : task.offset = 0;
814 [ + - ]: 5 : task.length = 1 * 512;
815 : 5 : rc = bdev_scsi_execute(&task);
816 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
817 : 5 : CU_ASSERT(task.status == 0xFF);
818 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_bdev_io_queue));
819 : 5 : ut_bdev_io_flush();
820 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
821 : 5 : CU_ASSERT(g_scsi_cb_called == 1);
822 : 5 : g_scsi_cb_called = 0;
823 : :
824 : : /* max transfer length (as reported in block limits VPD page) */
825 [ + - + - ]: 5 : to_be64(&cdb[2], 0); /* LBA */
826 [ + - + - ]: 5 : to_be32(&cdb[10], SPDK_WORK_BLOCK_SIZE / 512); /* transfer length */
827 [ + - ]: 5 : task.transfer_len = SPDK_WORK_BLOCK_SIZE;
828 : 5 : task.status = 0xFF;
829 [ + - ]: 5 : task.offset = 0;
830 [ + - ]: 5 : task.length = 1 * 512;
831 : 5 : rc = bdev_scsi_execute(&task);
832 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
833 : 5 : CU_ASSERT(task.status == 0xFF);
834 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_bdev_io_queue));
835 : 5 : ut_bdev_io_flush();
836 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
837 : 5 : CU_ASSERT(g_scsi_cb_called == 1);
838 : 5 : g_scsi_cb_called = 0;
839 : :
840 : : /* max transfer length plus one block (invalid) */
841 [ + - + - ]: 5 : to_be64(&cdb[2], 0); /* LBA */
842 [ + - + - ]: 5 : to_be32(&cdb[10], SPDK_WORK_BLOCK_SIZE / 512 + 1); /* transfer length */
843 [ + - ]: 5 : task.transfer_len = SPDK_WORK_BLOCK_SIZE + 512;
844 [ + - ]: 5 : task.offset = 0;
845 [ + - ]: 5 : task.length = 1 * 512;
846 : 5 : rc = bdev_scsi_execute(&task);
847 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
848 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
849 [ + - + - : 5 : CU_ASSERT((task.sense_data[2] & 0xf) == SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
+ - ]
850 [ + - + - : 5 : CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB);
+ - ]
851 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
852 : :
853 : : /* zero transfer length (valid) */
854 [ + - + - ]: 5 : to_be64(&cdb[2], 0); /* LBA */
855 [ + - + - ]: 5 : to_be32(&cdb[10], 0); /* transfer length */
856 [ + - ]: 5 : task.transfer_len = 0;
857 [ + - ]: 5 : task.offset = 0;
858 [ + - ]: 5 : task.length = 0;
859 : 5 : rc = bdev_scsi_execute(&task);
860 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
861 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
862 [ + - ]: 5 : CU_ASSERT(task.data_transferred == 0);
863 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
864 : :
865 : : /* zero transfer length past end of disk (invalid) */
866 [ + - + - ]: 5 : to_be64(&cdb[2], g_test_bdev_num_blocks); /* LBA */
867 [ + - + - ]: 5 : to_be32(&cdb[10], 0); /* transfer length */
868 [ + - ]: 5 : task.transfer_len = 0;
869 [ + - ]: 5 : task.offset = 0;
870 [ + - ]: 5 : task.length = 0;
871 : 5 : rc = bdev_scsi_execute(&task);
872 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
873 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
874 [ + - + - : 5 : CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);
+ - ]
875 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
876 : :
877 : 5 : ut_put_task(&task);
878 : 5 : }
879 : :
880 : : static void
881 : 10 : _xfer_test(bool bdev_io_pool_full)
882 : : {
883 : 10 : struct spdk_bdev bdev = { .blocklen = 512 };
884 : 8 : struct spdk_scsi_lun lun;
885 : 8 : struct spdk_scsi_task task;
886 : 8 : uint8_t cdb[16];
887 : 8 : char data[4096];
888 : 2 : int rc;
889 : :
890 [ + - ]: 10 : lun.bdev = &bdev;
891 : :
892 : : /* Test block device size of 512 MiB */
893 : 10 : g_test_bdev_num_blocks = 512 * 1024 * 1024;
894 : :
895 : : /* Read 1 block */
896 : 10 : ut_init_task(&task);
897 [ + - ]: 10 : task.lun = &lun;
898 [ + - + - : 10 : task.lun->bdev_desc = NULL;
+ - ]
899 [ + - + - : 10 : task.lun->io_channel = NULL;
+ - ]
900 [ + - ]: 10 : task.cdb = cdb;
901 [ + + ]: 10 : memset(cdb, 0, sizeof(cdb));
902 [ + - + - ]: 10 : cdb[0] = 0x88; /* READ (16) */
903 [ + - + - ]: 10 : to_be64(&cdb[2], 0); /* LBA */
904 [ + - + - ]: 10 : to_be32(&cdb[10], 1); /* transfer length */
905 [ + - ]: 10 : task.transfer_len = 1 * 512;
906 [ + - ]: 10 : task.offset = 0;
907 [ + - ]: 10 : task.length = 1 * 512;
908 [ + - ]: 10 : g_bdev_io_pool_full = bdev_io_pool_full;
909 : 10 : rc = bdev_scsi_execute(&task);
910 : 10 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
911 : 10 : CU_ASSERT(task.status == 0xFF);
912 : :
913 : 10 : ut_bdev_io_flush();
914 : 10 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
915 : 10 : CU_ASSERT(g_scsi_cb_called == 1);
916 : 10 : g_scsi_cb_called = 0;
917 : 10 : ut_put_task(&task);
918 : :
919 : : /* Write 1 block */
920 : 10 : ut_init_task(&task);
921 [ + - ]: 10 : task.lun = &lun;
922 [ + - ]: 10 : task.cdb = cdb;
923 [ + + ]: 10 : memset(cdb, 0, sizeof(cdb));
924 [ + - + - ]: 10 : cdb[0] = 0x8a; /* WRITE (16) */
925 [ + - + - ]: 10 : to_be64(&cdb[2], 0); /* LBA */
926 [ + - + - ]: 10 : to_be32(&cdb[10], 1); /* transfer length */
927 [ + - ]: 10 : task.transfer_len = 1 * 512;
928 [ + - ]: 10 : task.offset = 0;
929 [ + - ]: 10 : task.length = 1 * 512;
930 [ + - ]: 10 : g_bdev_io_pool_full = bdev_io_pool_full;
931 : 10 : rc = bdev_scsi_execute(&task);
932 : 10 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
933 : 10 : CU_ASSERT(task.status == 0xFF);
934 : :
935 : 10 : ut_bdev_io_flush();
936 : 10 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
937 : 10 : CU_ASSERT(g_scsi_cb_called == 1);
938 : 10 : g_scsi_cb_called = 0;
939 : 10 : ut_put_task(&task);
940 : :
941 : : /* Unmap 5 blocks using 2 descriptors */
942 : 10 : ut_init_task(&task);
943 [ + - ]: 10 : task.lun = &lun;
944 [ + - ]: 10 : task.cdb = cdb;
945 [ + + ]: 10 : memset(cdb, 0, sizeof(cdb));
946 [ + - + - ]: 10 : cdb[0] = 0x42; /* UNMAP */
947 [ + - + - ]: 10 : to_be16(&data[7], 2); /* 2 parameters in list */
948 [ + + ]: 10 : memset(data, 0, sizeof(data));
949 [ + - + - ]: 10 : to_be16(&data[2], 32); /* 2 descriptors */
950 [ + - + - ]: 10 : to_be64(&data[8], 1); /* LBA 1 */
951 [ + - + - ]: 10 : to_be32(&data[16], 2); /* 2 blocks */
952 [ + - + - ]: 10 : to_be64(&data[24], 10); /* LBA 10 */
953 [ + - + - ]: 10 : to_be32(&data[32], 3); /* 3 blocks */
954 : 10 : spdk_scsi_task_set_data(&task, data, sizeof(data));
955 : 10 : task.status = SPDK_SCSI_STATUS_GOOD;
956 [ + - ]: 10 : g_bdev_io_pool_full = bdev_io_pool_full;
957 : 10 : rc = bdev_scsi_execute(&task);
958 : 10 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
959 : 10 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
960 : :
961 : 10 : ut_bdev_io_flush();
962 : 10 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
963 : 10 : CU_ASSERT(g_scsi_cb_called == 1);
964 : 10 : g_scsi_cb_called = 0;
965 : 10 : ut_put_task(&task);
966 : :
967 : : /* Flush 1 block */
968 : 10 : ut_init_task(&task);
969 [ + - ]: 10 : task.lun = &lun;
970 [ + - ]: 10 : task.cdb = cdb;
971 [ + + ]: 10 : memset(cdb, 0, sizeof(cdb));
972 [ + - + - ]: 10 : cdb[0] = 0x91; /* SYNCHRONIZE CACHE (16) */
973 [ + - + - ]: 10 : to_be64(&cdb[2], 0); /* LBA */
974 [ + - + - ]: 10 : to_be32(&cdb[10], 1); /* 1 blocks */
975 [ + - ]: 10 : g_bdev_io_pool_full = bdev_io_pool_full;
976 : 10 : rc = bdev_scsi_execute(&task);
977 : 10 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
978 : 10 : CU_ASSERT(task.status == 0xFF);
979 : :
980 : 10 : ut_bdev_io_flush();
981 : 10 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
982 : 10 : CU_ASSERT(g_scsi_cb_called == 1);
983 : 10 : g_scsi_cb_called = 0;
984 [ + + # # ]: 10 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
985 : :
986 : 10 : ut_put_task(&task);
987 : 10 : }
988 : :
989 : : static void
990 : 5 : xfer_test(void)
991 : : {
992 : 5 : _xfer_test(false);
993 : 5 : _xfer_test(true);
994 : 5 : }
995 : :
996 : : static void
997 : 5 : get_dif_ctx_test(void)
998 : : {
999 : 5 : struct spdk_bdev bdev = {};
1000 : 5 : struct spdk_scsi_task task = {};
1001 : 5 : struct spdk_dif_ctx dif_ctx = {};
1002 : 4 : uint8_t cdb[16];
1003 : 1 : bool ret;
1004 : :
1005 [ + - + - ]: 5 : cdb[0] = SPDK_SBC_READ_6;
1006 [ + - + - : 5 : cdb[1] = 0x12;
+ - ]
1007 [ + - + - : 5 : cdb[2] = 0x34;
+ - ]
1008 [ + - + - : 5 : cdb[3] = 0x50;
+ - ]
1009 [ + - ]: 5 : task.cdb = cdb;
1010 [ + - ]: 5 : task.offset = 0x6 * 512;
1011 : :
1012 : 5 : ret = bdev_scsi_get_dif_ctx(&bdev, &task, &dif_ctx);
1013 [ + - ]: 5 : CU_ASSERT(ret == true);
1014 [ + - + - ]: 5 : CU_ASSERT(dif_ctx.init_ref_tag + dif_ctx.ref_tag_offset == 0x123456);
1015 : :
1016 [ + - + - ]: 5 : cdb[0] = SPDK_SBC_WRITE_12;
1017 [ + - + - ]: 5 : to_be32(&cdb[2], 0x12345670);
1018 [ + - ]: 5 : task.offset = 0x8 * 512;
1019 : :
1020 : 5 : ret = bdev_scsi_get_dif_ctx(&bdev, &task, &dif_ctx);
1021 [ + - ]: 5 : CU_ASSERT(ret == true);
1022 [ + - + - ]: 5 : CU_ASSERT(dif_ctx.init_ref_tag + dif_ctx.ref_tag_offset == 0x12345678);
1023 : :
1024 [ + - + - ]: 5 : cdb[0] = SPDK_SBC_WRITE_16;
1025 [ + - + - ]: 5 : to_be64(&cdb[2], 0x0000000012345670);
1026 [ + - ]: 5 : task.offset = 0x8 * 512;
1027 : :
1028 : 5 : ret = bdev_scsi_get_dif_ctx(&bdev, &task, &dif_ctx);
1029 [ + - ]: 5 : CU_ASSERT(ret == true);
1030 [ + - + - ]: 5 : CU_ASSERT(dif_ctx.init_ref_tag + dif_ctx.ref_tag_offset == 0x12345678);
1031 : 5 : }
1032 : :
1033 : : static void
1034 : 5 : unmap_split_test(void)
1035 : : {
1036 : 5 : struct spdk_bdev bdev = { .blocklen = 512 };
1037 : 4 : struct spdk_scsi_lun lun;
1038 : 4 : struct spdk_scsi_task task;
1039 : 4 : uint8_t cdb[16];
1040 : 4 : char data[4096];
1041 : 1 : int rc;
1042 : :
1043 [ + - ]: 5 : lun.bdev = &bdev;
1044 : :
1045 : : /* Test block device size of 512 MiB */
1046 : 5 : g_test_bdev_num_blocks = 512 * 1024 * 1024;
1047 : :
1048 : : /* Unmap 5 blocks using 5 descriptors. bdev_io pool size is 2.
1049 : : * Hence, unmap should be done by 3 iterations.
1050 : : * 1st - 2 unmaps, 2nd - 2 unmaps, and 3rd - 1 unmap.
1051 : : */
1052 : 5 : ut_init_task(&task);
1053 [ + - ]: 5 : task.lun = &lun;
1054 [ + - ]: 5 : task.cdb = cdb;
1055 [ + + ]: 5 : memset(cdb, 0, sizeof(cdb));
1056 [ + - + - ]: 5 : cdb[0] = 0x42; /* UNMAP */
1057 [ + - + - ]: 5 : to_be16(&data[7], 5); /* 5 parameters in list */
1058 [ + + ]: 5 : memset(data, 0, sizeof(data));
1059 [ + - + - ]: 5 : to_be16(&data[2], 80); /* 2 descriptors */
1060 [ + - + - ]: 5 : to_be64(&data[8], 1); /* LBA 1 */
1061 [ + - + - ]: 5 : to_be32(&data[16], 2); /* 2 blocks */
1062 [ + - + - ]: 5 : to_be64(&data[24], 5); /* LBA 5 */
1063 [ + - + - ]: 5 : to_be32(&data[32], 3); /* 3 blocks */
1064 [ + - + - ]: 5 : to_be64(&data[40], 10); /* LBA 10 */
1065 [ + - + - ]: 5 : to_be32(&data[48], 1); /* 1 block */
1066 [ + - + - ]: 5 : to_be64(&data[56], 15); /* LBA 15 */
1067 [ + - + - ]: 5 : to_be32(&data[64], 4); /* 4 blocks */
1068 [ + - + - ]: 5 : to_be64(&data[72], 30); /* LBA 30 */
1069 [ + - + - ]: 5 : to_be32(&data[80], 1); /* 1 block */
1070 : 5 : spdk_scsi_task_set_data(&task, data, sizeof(data));
1071 : 5 : task.status = SPDK_SCSI_STATUS_GOOD;
1072 : :
1073 : 5 : g_bdev_io_pool_full = true;
1074 : :
1075 : 5 : rc = bdev_scsi_execute(&task);
1076 : 5 : CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
1077 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
1078 : 5 : CU_ASSERT(g_scsi_cb_called == 0);
1079 : 5 : CU_ASSERT(g_outstanding_bdev_io_count == 0);
1080 : 5 : CU_ASSERT(g_pending_bdev_io_count == 1);
1081 : :
1082 : 5 : g_bdev_io_pool_count = 2;
1083 : 5 : ut_bdev_io_retry();
1084 : :
1085 : 5 : CU_ASSERT(g_outstanding_bdev_io_count == 2);
1086 : 5 : CU_ASSERT(g_pending_bdev_io_count == 0);
1087 : :
1088 : 5 : g_bdev_io_pool_full = true;
1089 : 5 : ut_bdev_io_complete();
1090 : :
1091 : 5 : CU_ASSERT(g_outstanding_bdev_io_count == 0);
1092 : 5 : CU_ASSERT(g_pending_bdev_io_count == 1);
1093 : :
1094 : 5 : ut_bdev_io_retry();
1095 : :
1096 : 5 : CU_ASSERT(g_outstanding_bdev_io_count == 2);
1097 : 5 : CU_ASSERT(g_pending_bdev_io_count == 0);
1098 : :
1099 : 5 : ut_bdev_io_complete();
1100 : :
1101 : 5 : CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
1102 : 5 : CU_ASSERT(g_scsi_cb_called == 1);
1103 : :
1104 : 5 : g_scsi_cb_called = 0;
1105 : 5 : g_bdev_io_pool_count = -1;
1106 : :
1107 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
1108 [ + + # # ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_io_wait_queue));
1109 : :
1110 : 5 : ut_put_task(&task);
1111 : 5 : }
1112 : :
1113 : : int
1114 : 5 : main(int argc, char **argv)
1115 : : {
1116 : 5 : CU_pSuite suite = NULL;
1117 : 1 : unsigned int num_failures;
1118 : :
1119 [ + - ]: 5 : TAILQ_INIT(&g_bdev_io_queue);
1120 [ + - ]: 5 : TAILQ_INIT(&g_io_wait_queue);
1121 : :
1122 : 5 : CU_initialize_registry();
1123 : :
1124 : 5 : suite = CU_add_suite("translation_suite", NULL, NULL);
1125 : :
1126 : 5 : CU_ADD_TEST(suite, mode_select_6_test);
1127 : 5 : CU_ADD_TEST(suite, mode_select_6_test2);
1128 : 5 : CU_ADD_TEST(suite, mode_sense_6_test);
1129 : 5 : CU_ADD_TEST(suite, mode_sense_10_test);
1130 : 5 : CU_ADD_TEST(suite, inquiry_evpd_test);
1131 : 5 : CU_ADD_TEST(suite, inquiry_standard_test);
1132 : 5 : CU_ADD_TEST(suite, inquiry_overflow_test);
1133 : 5 : CU_ADD_TEST(suite, task_complete_test);
1134 : 5 : CU_ADD_TEST(suite, lba_range_test);
1135 : 5 : CU_ADD_TEST(suite, xfer_len_test);
1136 : 5 : CU_ADD_TEST(suite, xfer_test);
1137 : 5 : CU_ADD_TEST(suite, scsi_name_padding_test);
1138 : 5 : CU_ADD_TEST(suite, get_dif_ctx_test);
1139 : 5 : CU_ADD_TEST(suite, unmap_split_test);
1140 : :
1141 : 5 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
1142 : 5 : CU_cleanup_registry();
1143 : 6 : return num_failures;
1144 : 1 : }
|