]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/test/unit/lib/scsi/scsi_pr.c/scsi_pr_ut.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / test / unit / lib / scsi / scsi_pr.c / scsi_pr_ut.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "spdk/stdinc.h"
35
36 #include "scsi/port.c"
37 #include "scsi/scsi_pr.c"
38
39 #include "spdk_cunit.h"
40
41 #include "spdk_internal/mock.h"
42
43 SPDK_LOG_REGISTER_COMPONENT("scsi", SPDK_LOG_SCSI)
44
45 void
46 spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
47 int asc, int ascq)
48 {
49 task->status = sc;
50 }
51
52 /*
53 * Reservation Unit Test Configuration
54 *
55 * -------- -------- -------
56 * | Host A | | Host B | | Host C|
57 * -------- -------- -------
58 * | | |
59 * ------ ------ ------
60 * |Port A| |Port B| |Port C|
61 * ------ ------ ------
62 * \ | /
63 * \ | /
64 * \ | /
65 * ------------------------
66 * | Target Node 1 Port 0 |
67 * ------------------------
68 * |
69 * ----------------------------------
70 * | Target Node |
71 * ----------------------------------
72 * |
73 * -----
74 * |LUN 0|
75 * -----
76 *
77 */
78
79 static struct spdk_scsi_lun g_lun;
80 static struct spdk_scsi_port g_i_port_a;
81 static struct spdk_scsi_port g_i_port_b;
82 static struct spdk_scsi_port g_i_port_c;
83 static struct spdk_scsi_port g_t_port_0;
84
85 static void
86 ut_lun_deinit(void)
87 {
88 struct spdk_scsi_pr_registrant *reg, *tmp;
89
90 TAILQ_FOREACH_SAFE(reg, &g_lun.reg_head, link, tmp) {
91 TAILQ_REMOVE(&g_lun.reg_head, reg, link);
92 free(reg);
93 }
94 g_lun.reservation.rtype = 0;
95 g_lun.reservation.crkey = 0;
96 g_lun.reservation.holder = NULL;
97 g_lun.pr_generation = 0;
98 }
99
100 static void
101 ut_port_init(void)
102 {
103 int rc;
104
105 /* g_i_port_a */
106 rc = spdk_scsi_port_construct(&g_i_port_a, 0xa, 0,
107 "iqn.2016-06.io.spdk:fe5aacf7420a,i,0x00023d00000a");
108 SPDK_CU_ASSERT_FATAL(rc == 0);
109 spdk_scsi_port_set_iscsi_transport_id(&g_i_port_a,
110 "iqn.2016-06.io.spdk:fe5aacf7420a", 0x00023d00000a);
111 /* g_i_port_b */
112 rc = spdk_scsi_port_construct(&g_i_port_b, 0xb, 0,
113 "iqn.2016-06.io.spdk:fe5aacf7420b,i,0x00023d00000b");
114 SPDK_CU_ASSERT_FATAL(rc == 0);
115 spdk_scsi_port_set_iscsi_transport_id(&g_i_port_b,
116 "iqn.2016-06.io.spdk:fe5aacf7420b", 0x00023d00000b);
117 /* g_i_port_c */
118 rc = spdk_scsi_port_construct(&g_i_port_c, 0xc, 0,
119 "iqn.2016-06.io.spdk:fe5aacf7420c,i,0x00023d00000c");
120 SPDK_CU_ASSERT_FATAL(rc == 0);
121 spdk_scsi_port_set_iscsi_transport_id(&g_i_port_c,
122 "iqn.2016-06.io.spdk:fe5aacf7420c", 0x00023d00000c);
123 /* g_t_port_0 */
124 rc = spdk_scsi_port_construct(&g_t_port_0, 0x0, 1,
125 "iqn.2016-06.io.spdk:fe5aacf74200,t,0x00023d000000");
126 SPDK_CU_ASSERT_FATAL(rc == 0);
127 spdk_scsi_port_set_iscsi_transport_id(&g_t_port_0,
128 "iqn.2016-06.io.spdk:fe5aacf74200", 0x00023d000000);
129 }
130
131 static void
132 ut_lun_init(void)
133 {
134 TAILQ_INIT(&g_lun.reg_head);
135 }
136
137 static void
138 ut_init_reservation_test(void)
139 {
140 ut_lun_init();
141 ut_port_init();
142 ut_lun_init();
143 }
144
145 static void
146 ut_deinit_reservation_test(void)
147 {
148 ut_lun_deinit();
149 }
150
151 /* Host A: register with key 0xa.
152 * Host B: register with key 0xb.
153 * Host C: register with key 0xc.
154 */
155 static void
156 test_build_registrants(void)
157 {
158 struct spdk_scsi_pr_registrant *reg;
159 struct spdk_scsi_task task = {0};
160 uint32_t gen;
161 int rc;
162
163 task.lun = &g_lun;
164 task.target_port = &g_t_port_0;
165
166 gen = g_lun.pr_generation;
167
168 /* I_T nexus: Initiator Port A to Target Port 0 */
169 task.initiator_port = &g_i_port_a;
170 /* Test Case: Host A registers with a new key */
171 task.status = 0;
172 rc = spdk_scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
173 0x0, 0xa1, 0, 0, 0);
174 SPDK_CU_ASSERT_FATAL(rc == 0);
175 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
176 SPDK_CU_ASSERT_FATAL(reg != NULL);
177 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
178 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
179
180 /* Test Case: Host A replaces with a new key */
181 task.status = 0;
182 rc = spdk_scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
183 0xa1, 0xa, 0, 0, 0);
184 SPDK_CU_ASSERT_FATAL(rc == 0);
185 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
186 SPDK_CU_ASSERT_FATAL(reg != NULL);
187 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa);
188 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 2);
189
190 /* Test Case: Host A replaces with a new key, reservation conflict is expected */
191 task.status = 0;
192 rc = spdk_scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
193 0xa1, 0xdead, 0, 0, 0);
194 SPDK_CU_ASSERT_FATAL(rc < 0);
195 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
196 SPDK_CU_ASSERT_FATAL(reg != NULL);
197 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa);
198 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 2);
199 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
200
201 /* I_T nexus: Initiator Port B to Target Port 0 */
202 task.initiator_port = &g_i_port_b;
203 /* Test Case: Host B registers with a new key */
204 task.status = 0;
205 rc = spdk_scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
206 0x0, 0xb, 0, 0, 0);
207 SPDK_CU_ASSERT_FATAL(rc == 0);
208 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
209 SPDK_CU_ASSERT_FATAL(reg != NULL);
210 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb);
211 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 3);
212
213 /* I_T nexus: Initiator Port C to Target Port 0 */
214 task.initiator_port = &g_i_port_c;
215 /* Test Case: Host C registers with a new key */
216 task.status = 0;
217 rc = spdk_scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
218 0x0, 0xc, 0, 0, 0);
219 SPDK_CU_ASSERT_FATAL(rc == 0);
220 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
221 SPDK_CU_ASSERT_FATAL(reg != NULL);
222 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc);
223 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 4);
224 }
225
226 static void
227 test_reservation_register(void)
228 {
229 ut_init_reservation_test();
230
231 test_build_registrants();
232
233 ut_deinit_reservation_test();
234 }
235
236 static void
237 test_reservation_reserve(void)
238 {
239 struct spdk_scsi_pr_registrant *reg;
240 struct spdk_scsi_task task = {0};
241 uint32_t gen;
242 int rc;
243
244 task.lun = &g_lun;
245 task.target_port = &g_t_port_0;
246
247 ut_init_reservation_test();
248 test_build_registrants();
249
250 gen = g_lun.pr_generation;
251
252 task.initiator_port = &g_i_port_a;
253 task.status = 0;
254 /* Test Case: Host A acquires the reservation */
255 rc = spdk_scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
256 0xa, 0, 0, 0);
257 SPDK_CU_ASSERT_FATAL(rc == 0);
258 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
259 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
260 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
261
262 /* Test Case: Host B acquires the reservation, reservation
263 * conflict is expected.
264 */
265 task.initiator_port = &g_i_port_b;
266 task.status = 0;
267 rc = spdk_scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
268 0xb, 0, 0, 0);
269 SPDK_CU_ASSERT_FATAL(rc < 0);
270 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
271 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
272 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
273 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
274
275 /* Test Case: Host A unregister with reservation */
276 task.initiator_port = &g_i_port_a;
277 task.status = 0;
278 rc = spdk_scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
279 0xa, 0, 0, 0, 0);
280 SPDK_CU_ASSERT_FATAL(rc == 0);
281 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == 0);
282 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0);
283 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
284 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
285 SPDK_CU_ASSERT_FATAL(reg == NULL);
286
287 /* Test Case: Host B acquires the reservation */
288 task.initiator_port = &g_i_port_b;
289 task.status = 0;
290 rc = spdk_scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
291 0xb, 0, 0, 0);
292 SPDK_CU_ASSERT_FATAL(rc == 0);
293 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
294 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
295
296 /* Test Case: Host C acquires the reservation with invalid type */
297 task.initiator_port = &g_i_port_c;
298 task.status = 0;
299 rc = spdk_scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
300 0xc, 0, 0, 0);
301 SPDK_CU_ASSERT_FATAL(rc < 0);
302 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
303 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
304 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
305
306 /* Test Case: Host C acquires the reservation, all registrants type */
307 task.status = 0;
308 rc = spdk_scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
309 0xc, 0, 0, 0);
310 SPDK_CU_ASSERT_FATAL(rc == 0);
311 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
312 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
313
314 ut_deinit_reservation_test();
315 }
316
317 static void
318 test_reservation_preempt_non_all_regs(void)
319 {
320 struct spdk_scsi_pr_registrant *reg;
321 struct spdk_scsi_task task = {0};
322 uint32_t gen;
323 int rc;
324
325 task.lun = &g_lun;
326 task.target_port = &g_t_port_0;
327
328 ut_init_reservation_test();
329 test_build_registrants();
330
331 task.initiator_port = &g_i_port_a;
332 task.status = 0;
333 gen = g_lun.pr_generation;
334 /* Host A acquires the reservation */
335 rc = spdk_scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
336 0xa, 0, 0, 0);
337 SPDK_CU_ASSERT_FATAL(rc == 0);
338 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
339 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
340 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
341
342 /* Test Case: Host B premmpts Host A, Check condition is expected
343 * for zeroed service action reservation key */
344 task.initiator_port = &g_i_port_b;
345 task.status = 0;
346 rc = spdk_scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
347 SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
348 0xb, 0);
349 SPDK_CU_ASSERT_FATAL(rc < 0);
350 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
351
352 /* Test Case: Host B preempts Host A, Host A is unregisted */
353 task.status = 0;
354 gen = g_lun.pr_generation;
355 rc = spdk_scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
356 SPDK_SCSI_PR_WRITE_EXCLUSIVE,
357 0xb, 0xa);
358 SPDK_CU_ASSERT_FATAL(rc == 0);
359 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
360 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
361 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
362 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
363 SPDK_CU_ASSERT_FATAL(reg == NULL);
364
365 /* Test Case: Host B preempts itself */
366 task.status = 0;
367 gen = g_lun.pr_generation;
368 rc = spdk_scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
369 SPDK_SCSI_PR_WRITE_EXCLUSIVE,
370 0xb, 0xb);
371 SPDK_CU_ASSERT_FATAL(rc == 0);
372 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
373 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
374 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
375
376 /* Test Case: Host B preempts itself and remove registrants */
377 task.status = 0;
378 gen = g_lun.pr_generation;
379 rc = spdk_scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
380 SPDK_SCSI_PR_WRITE_EXCLUSIVE,
381 0xb, 0xc);
382 SPDK_CU_ASSERT_FATAL(rc == 0);
383 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
384 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
385 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
386 SPDK_CU_ASSERT_FATAL(reg == NULL);
387 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
388
389 ut_deinit_reservation_test();
390 }
391
392 static void
393 test_reservation_preempt_all_regs(void)
394 {
395 struct spdk_scsi_pr_registrant *reg;
396 struct spdk_scsi_task task = {0};
397 uint32_t gen;
398 int rc;
399
400 task.lun = &g_lun;
401 task.target_port = &g_t_port_0;
402
403 ut_init_reservation_test();
404 test_build_registrants();
405
406 /* Test Case: No reservation yet, Host B removes Host C's registrant */
407 task.initiator_port = &g_i_port_b;
408 task.status = 0;
409 gen = g_lun.pr_generation;
410 rc = spdk_scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
411 SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
412 0xb, 0xc);
413 SPDK_CU_ASSERT_FATAL(rc == 0);
414 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
415 SPDK_CU_ASSERT_FATAL(reg == NULL);
416 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
417
418 task.initiator_port = &g_i_port_a;
419 task.status = 0;
420 gen = g_lun.pr_generation;
421 /* Host A acquires the reservation */
422 rc = spdk_scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
423 0xa, 0, 0, 0);
424 SPDK_CU_ASSERT_FATAL(rc == 0);
425 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
426 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
427
428 /* Test Case: Host B removes Host A's registrant and preempt */
429 task.initiator_port = &g_i_port_b;
430 task.status = 0;
431 gen = g_lun.pr_generation;
432 rc = spdk_scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
433 SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS,
434 0xb, 0x0);
435 SPDK_CU_ASSERT_FATAL(rc == 0);
436 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
437 SPDK_CU_ASSERT_FATAL(reg == NULL);
438 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS);
439 SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
440
441 ut_deinit_reservation_test();
442 }
443
444 static void
445 test_reservation_cmds_conflict(void)
446 {
447 struct spdk_scsi_pr_registrant *reg;
448 struct spdk_scsi_task task = {0};
449 uint8_t cdb[32];
450 int rc;
451
452 task.lun = &g_lun;
453 task.target_port = &g_t_port_0;
454 task.cdb = cdb;
455
456 ut_init_reservation_test();
457 test_build_registrants();
458
459 /* Host A acquires the reservation */
460 task.initiator_port = &g_i_port_a;
461 rc = spdk_scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
462 0xa, 0, 0, 0);
463 SPDK_CU_ASSERT_FATAL(rc == 0);
464 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
465 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
466
467 /* Remove Host B registrant */
468 task.initiator_port = &g_i_port_b;
469 task.status = 0;
470 rc = spdk_scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
471 0xb, 0, 0, 0, 0);
472 SPDK_CU_ASSERT_FATAL(rc == 0);
473 reg = spdk_scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
474 SPDK_CU_ASSERT_FATAL(reg == NULL);
475
476 /* Test Case: Host B sends Read/Write commands,
477 * reservation conflict is expected.
478 */
479 task.cdb[0] = SPDK_SBC_READ_10;
480 task.status = 0;
481 rc = spdk_scsi_pr_check(&task);
482 SPDK_CU_ASSERT_FATAL(rc == 0);
483 task.cdb[0] = SPDK_SBC_WRITE_10;
484 task.status = 0;
485 rc = spdk_scsi_pr_check(&task);
486 SPDK_CU_ASSERT_FATAL(rc < 0);
487 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
488
489 /* Test Case: Host C sends Read/Write commands */
490 task.initiator_port = &g_i_port_c;
491 task.cdb[0] = SPDK_SBC_READ_10;
492 task.status = 0;
493 rc = spdk_scsi_pr_check(&task);
494 SPDK_CU_ASSERT_FATAL(rc == 0);
495 task.cdb[0] = SPDK_SBC_WRITE_10;
496 task.status = 0;
497 rc = spdk_scsi_pr_check(&task);
498 SPDK_CU_ASSERT_FATAL(rc == 0);
499
500 /* Host A preempts itself with SPDK_SCSI_PR_EXCLUSIVE_ACCESS */
501 task.initiator_port = &g_i_port_a;
502 rc = spdk_scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
503 SPDK_SCSI_PR_EXCLUSIVE_ACCESS,
504 0xa, 0xa);
505 SPDK_CU_ASSERT_FATAL(rc == 0);
506 SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS);
507 SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
508
509 /* Test Case: Host C sends Read/Write commands */
510 task.initiator_port = &g_i_port_c;
511 task.cdb[0] = SPDK_SBC_READ_10;
512 task.status = 0;
513 rc = spdk_scsi_pr_check(&task);
514 SPDK_CU_ASSERT_FATAL(rc < 0);
515 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
516 task.cdb[0] = SPDK_SBC_WRITE_10;
517 task.status = 0;
518 rc = spdk_scsi_pr_check(&task);
519 SPDK_CU_ASSERT_FATAL(rc < 0);
520 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
521
522 /* Test Case: Host B sends Read/Write commands */
523 task.initiator_port = &g_i_port_b;
524 task.cdb[0] = SPDK_SBC_READ_10;
525 task.status = 0;
526 rc = spdk_scsi_pr_check(&task);
527 SPDK_CU_ASSERT_FATAL(rc < 0);
528 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
529 task.cdb[0] = SPDK_SBC_WRITE_10;
530 task.status = 0;
531 rc = spdk_scsi_pr_check(&task);
532 SPDK_CU_ASSERT_FATAL(rc < 0);
533 SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
534
535 ut_deinit_reservation_test();
536 }
537
538 int
539 main(int argc, char **argv)
540 {
541 CU_pSuite suite = NULL;
542 unsigned int num_failures;
543
544 if (CU_initialize_registry() != CUE_SUCCESS) {
545 return CU_get_error();
546 }
547
548 suite = CU_add_suite("reservation_suite", NULL, NULL);
549 if (suite == NULL) {
550 CU_cleanup_registry();
551 return CU_get_error();
552 }
553
554 if (CU_add_test(suite, "register", test_reservation_register) == NULL ||
555 CU_add_test(suite, "reserve", test_reservation_reserve) == NULL ||
556 CU_add_test(suite, "preempt", test_reservation_preempt_non_all_regs) == NULL ||
557 CU_add_test(suite, "preempt all regs", test_reservation_preempt_all_regs) == NULL ||
558 CU_add_test(suite, "conflict", test_reservation_cmds_conflict) == NULL) {
559 CU_cleanup_registry();
560 return CU_get_error();
561 }
562
563 CU_basic_set_mode(CU_BRM_VERBOSE);
564 CU_basic_run_tests();
565 num_failures = CU_get_number_of_failures();
566 CU_cleanup_registry();
567 return num_failures;
568
569 }