1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse * Copyright (C) 2019 Intel Corporation.
3d7d44988SChangpeng Liu * All rights reserved.
4d7d44988SChangpeng Liu */
5d7d44988SChangpeng Liu
6d7d44988SChangpeng Liu #include "spdk/stdinc.h"
7d7d44988SChangpeng Liu
8d7d44988SChangpeng Liu #include "scsi/port.c"
9d7d44988SChangpeng Liu #include "scsi/scsi_pr.c"
10d7d44988SChangpeng Liu
11ae431e31SKonrad Sztyber #include "spdk_internal/cunit.h"
12d7d44988SChangpeng Liu
13d7d44988SChangpeng Liu #include "spdk_internal/mock.h"
14d7d44988SChangpeng Liu
SPDK_LOG_REGISTER_COMPONENT(scsi)152172c432STomasz Zawadzki SPDK_LOG_REGISTER_COMPONENT(scsi)
16d7d44988SChangpeng Liu
17d7d44988SChangpeng Liu void
18d7d44988SChangpeng Liu spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
19d7d44988SChangpeng Liu int asc, int ascq)
20d7d44988SChangpeng Liu {
21d7d44988SChangpeng Liu task->status = sc;
22d7d44988SChangpeng Liu }
23d7d44988SChangpeng Liu
24d7d44988SChangpeng Liu /*
25d7d44988SChangpeng Liu * Reservation Unit Test Configuration
26d7d44988SChangpeng Liu *
27d7d44988SChangpeng Liu * -------- -------- -------
28d7d44988SChangpeng Liu * | Host A | | Host B | | Host C|
29d7d44988SChangpeng Liu * -------- -------- -------
30d7d44988SChangpeng Liu * | | |
31d7d44988SChangpeng Liu * ------ ------ ------
32d7d44988SChangpeng Liu * |Port A| |Port B| |Port C|
33d7d44988SChangpeng Liu * ------ ------ ------
34d7d44988SChangpeng Liu * \ | /
35d7d44988SChangpeng Liu * \ | /
36d7d44988SChangpeng Liu * \ | /
37d7d44988SChangpeng Liu * ------------------------
38d7d44988SChangpeng Liu * | Target Node 1 Port 0 |
39d7d44988SChangpeng Liu * ------------------------
40d7d44988SChangpeng Liu * |
41d7d44988SChangpeng Liu * ----------------------------------
42d7d44988SChangpeng Liu * | Target Node |
43d7d44988SChangpeng Liu * ----------------------------------
44d7d44988SChangpeng Liu * |
45d7d44988SChangpeng Liu * -----
46d7d44988SChangpeng Liu * |LUN 0|
47d7d44988SChangpeng Liu * -----
48d7d44988SChangpeng Liu *
49d7d44988SChangpeng Liu */
50d7d44988SChangpeng Liu
51d7d44988SChangpeng Liu static struct spdk_scsi_lun g_lun;
52d7d44988SChangpeng Liu static struct spdk_scsi_port g_i_port_a;
53d7d44988SChangpeng Liu static struct spdk_scsi_port g_i_port_b;
54d7d44988SChangpeng Liu static struct spdk_scsi_port g_i_port_c;
55d7d44988SChangpeng Liu static struct spdk_scsi_port g_t_port_0;
56d7d44988SChangpeng Liu
57d7d44988SChangpeng Liu static void
ut_lun_deinit(void)58d7d44988SChangpeng Liu ut_lun_deinit(void)
59d7d44988SChangpeng Liu {
60d7d44988SChangpeng Liu struct spdk_scsi_pr_registrant *reg, *tmp;
61d7d44988SChangpeng Liu
62d7d44988SChangpeng Liu TAILQ_FOREACH_SAFE(reg, &g_lun.reg_head, link, tmp) {
63d7d44988SChangpeng Liu TAILQ_REMOVE(&g_lun.reg_head, reg, link);
64d7d44988SChangpeng Liu free(reg);
65d7d44988SChangpeng Liu }
66d7d44988SChangpeng Liu g_lun.reservation.rtype = 0;
67d7d44988SChangpeng Liu g_lun.reservation.crkey = 0;
68d7d44988SChangpeng Liu g_lun.reservation.holder = NULL;
69d7d44988SChangpeng Liu g_lun.pr_generation = 0;
70d7d44988SChangpeng Liu }
71d7d44988SChangpeng Liu
72d7d44988SChangpeng Liu static void
ut_port_init(void)73d7d44988SChangpeng Liu ut_port_init(void)
74d7d44988SChangpeng Liu {
75d7d44988SChangpeng Liu int rc;
76d7d44988SChangpeng Liu
77d7d44988SChangpeng Liu /* g_i_port_a */
7818dec401SShuhei Matsumoto rc = scsi_port_construct(&g_i_port_a, 0xa, 0,
79d7d44988SChangpeng Liu "iqn.2016-06.io.spdk:fe5aacf7420a,i,0x00023d00000a");
80d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
81d7d44988SChangpeng Liu spdk_scsi_port_set_iscsi_transport_id(&g_i_port_a,
82d7d44988SChangpeng Liu "iqn.2016-06.io.spdk:fe5aacf7420a", 0x00023d00000a);
83d7d44988SChangpeng Liu /* g_i_port_b */
8418dec401SShuhei Matsumoto rc = scsi_port_construct(&g_i_port_b, 0xb, 0,
85d7d44988SChangpeng Liu "iqn.2016-06.io.spdk:fe5aacf7420b,i,0x00023d00000b");
86d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
87d7d44988SChangpeng Liu spdk_scsi_port_set_iscsi_transport_id(&g_i_port_b,
88d7d44988SChangpeng Liu "iqn.2016-06.io.spdk:fe5aacf7420b", 0x00023d00000b);
89d7d44988SChangpeng Liu /* g_i_port_c */
9018dec401SShuhei Matsumoto rc = scsi_port_construct(&g_i_port_c, 0xc, 0,
91d7d44988SChangpeng Liu "iqn.2016-06.io.spdk:fe5aacf7420c,i,0x00023d00000c");
92d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
93d7d44988SChangpeng Liu spdk_scsi_port_set_iscsi_transport_id(&g_i_port_c,
94d7d44988SChangpeng Liu "iqn.2016-06.io.spdk:fe5aacf7420c", 0x00023d00000c);
95d7d44988SChangpeng Liu /* g_t_port_0 */
9618dec401SShuhei Matsumoto rc = scsi_port_construct(&g_t_port_0, 0x0, 1,
97d7d44988SChangpeng Liu "iqn.2016-06.io.spdk:fe5aacf74200,t,0x00023d000000");
98d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
99d7d44988SChangpeng Liu spdk_scsi_port_set_iscsi_transport_id(&g_t_port_0,
100d7d44988SChangpeng Liu "iqn.2016-06.io.spdk:fe5aacf74200", 0x00023d000000);
101d7d44988SChangpeng Liu }
102d7d44988SChangpeng Liu
103d7d44988SChangpeng Liu static void
ut_lun_init(void)104d7d44988SChangpeng Liu ut_lun_init(void)
105d7d44988SChangpeng Liu {
106d7d44988SChangpeng Liu TAILQ_INIT(&g_lun.reg_head);
107d7d44988SChangpeng Liu }
108d7d44988SChangpeng Liu
109d7d44988SChangpeng Liu static void
ut_init_reservation_test(void)110d7d44988SChangpeng Liu ut_init_reservation_test(void)
111d7d44988SChangpeng Liu {
112d7d44988SChangpeng Liu ut_lun_init();
113d7d44988SChangpeng Liu ut_port_init();
114d7d44988SChangpeng Liu ut_lun_init();
115d7d44988SChangpeng Liu }
116d7d44988SChangpeng Liu
117d7d44988SChangpeng Liu static void
ut_deinit_reservation_test(void)118d7d44988SChangpeng Liu ut_deinit_reservation_test(void)
119d7d44988SChangpeng Liu {
120d7d44988SChangpeng Liu ut_lun_deinit();
121d7d44988SChangpeng Liu }
122d7d44988SChangpeng Liu
123d7d44988SChangpeng Liu /* Host A: register with key 0xa.
124d7d44988SChangpeng Liu * Host B: register with key 0xb.
125d7d44988SChangpeng Liu * Host C: register with key 0xc.
126d7d44988SChangpeng Liu */
127d7d44988SChangpeng Liu static void
test_build_registrants(void)128d7d44988SChangpeng Liu test_build_registrants(void)
129d7d44988SChangpeng Liu {
130d7d44988SChangpeng Liu struct spdk_scsi_pr_registrant *reg;
131d7d44988SChangpeng Liu struct spdk_scsi_task task = {0};
132d7d44988SChangpeng Liu uint32_t gen;
133d7d44988SChangpeng Liu int rc;
134d7d44988SChangpeng Liu
135d7d44988SChangpeng Liu task.lun = &g_lun;
136d7d44988SChangpeng Liu task.target_port = &g_t_port_0;
137d7d44988SChangpeng Liu
138d7d44988SChangpeng Liu gen = g_lun.pr_generation;
139d7d44988SChangpeng Liu
140d7d44988SChangpeng Liu /* I_T nexus: Initiator Port A to Target Port 0 */
141d7d44988SChangpeng Liu task.initiator_port = &g_i_port_a;
142d7d44988SChangpeng Liu /* Test Case: Host A registers with a new key */
143d7d44988SChangpeng Liu task.status = 0;
14433a29747SShuhei Matsumoto rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
145d7d44988SChangpeng Liu 0x0, 0xa1, 0, 0, 0);
146d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
14733a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
148d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg != NULL);
149d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
150d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
151d7d44988SChangpeng Liu
152d7d44988SChangpeng Liu /* Test Case: Host A replaces with a new key */
153d7d44988SChangpeng Liu task.status = 0;
15433a29747SShuhei Matsumoto rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
155d7d44988SChangpeng Liu 0xa1, 0xa, 0, 0, 0);
156d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
15733a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
158d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg != NULL);
159d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa);
160d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 2);
161d7d44988SChangpeng Liu
162d7d44988SChangpeng Liu /* Test Case: Host A replaces with a new key, reservation conflict is expected */
163d7d44988SChangpeng Liu task.status = 0;
16433a29747SShuhei Matsumoto rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
165d7d44988SChangpeng Liu 0xa1, 0xdead, 0, 0, 0);
166d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
16733a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
168d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg != NULL);
169d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa);
170d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 2);
171d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
172d7d44988SChangpeng Liu
173d7d44988SChangpeng Liu /* I_T nexus: Initiator Port B to Target Port 0 */
174d7d44988SChangpeng Liu task.initiator_port = &g_i_port_b;
175d7d44988SChangpeng Liu /* Test Case: Host B registers with a new key */
176d7d44988SChangpeng Liu task.status = 0;
17733a29747SShuhei Matsumoto rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
178d7d44988SChangpeng Liu 0x0, 0xb, 0, 0, 0);
179d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
18033a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
181d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg != NULL);
182d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb);
183d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 3);
184d7d44988SChangpeng Liu
185d7d44988SChangpeng Liu /* I_T nexus: Initiator Port C to Target Port 0 */
186d7d44988SChangpeng Liu task.initiator_port = &g_i_port_c;
187d7d44988SChangpeng Liu /* Test Case: Host C registers with a new key */
188d7d44988SChangpeng Liu task.status = 0;
18933a29747SShuhei Matsumoto rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
190d7d44988SChangpeng Liu 0x0, 0xc, 0, 0, 0);
191d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
19233a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
193d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg != NULL);
194d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc);
195d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 4);
196d7d44988SChangpeng Liu }
197d7d44988SChangpeng Liu
198d7d44988SChangpeng Liu static void
test_reservation_register(void)199d7d44988SChangpeng Liu test_reservation_register(void)
200d7d44988SChangpeng Liu {
201d7d44988SChangpeng Liu ut_init_reservation_test();
202d7d44988SChangpeng Liu
203d7d44988SChangpeng Liu test_build_registrants();
204d7d44988SChangpeng Liu
205d7d44988SChangpeng Liu ut_deinit_reservation_test();
206d7d44988SChangpeng Liu }
207d7d44988SChangpeng Liu
208d7d44988SChangpeng Liu static void
test_all_registrant_reservation_reserve(void)209be633ff1SOded Mashbach test_all_registrant_reservation_reserve(void)
210be633ff1SOded Mashbach {
211be633ff1SOded Mashbach struct spdk_scsi_pr_registrant *reg;
212be633ff1SOded Mashbach struct spdk_scsi_task task = {0};
213be633ff1SOded Mashbach uint32_t gen;
214be633ff1SOded Mashbach int rc;
215be633ff1SOded Mashbach
216be633ff1SOded Mashbach task.lun = &g_lun;
217be633ff1SOded Mashbach task.target_port = &g_t_port_0;
218be633ff1SOded Mashbach
219be633ff1SOded Mashbach ut_init_reservation_test();
220be633ff1SOded Mashbach
221be633ff1SOded Mashbach test_build_registrants();
222be633ff1SOded Mashbach gen = g_lun.pr_generation;
223be633ff1SOded Mashbach /* Test Case: Host A takes all registrant reservation */
224be633ff1SOded Mashbach task.initiator_port = &g_i_port_a;
225be633ff1SOded Mashbach task.status = 0;
226be633ff1SOded Mashbach rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
227be633ff1SOded Mashbach 0xa, 0, 0, 0);
228be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
229be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(task.status == 0);
230be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
231be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
232be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
233be633ff1SOded Mashbach
234be633ff1SOded Mashbach /* Test case: Host A release reservation - which should pass to next inline -> Host B */
235be633ff1SOded Mashbach task.initiator_port = &g_i_port_a;
236be633ff1SOded Mashbach task.status = 0;
237be633ff1SOded Mashbach rc = scsi_pr_out_release(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS, 0xa);
238be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
239be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(task.status == 0);
240be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
241be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
242be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
243be633ff1SOded Mashbach
244be633ff1SOded Mashbach /* Test case: Host A unregister + Host C unregister: Host B left alone.
245be633ff1SOded Mashbach * Host B than releases reservation - lun should not have any reservation holder *
246be633ff1SOded Mashbach */
247be633ff1SOded Mashbach task.initiator_port = &g_i_port_a;
248be633ff1SOded Mashbach task.status = 0;
249be633ff1SOded Mashbach rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
250be633ff1SOded Mashbach 0xa, 0, 0, 0, 0);
251be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
252be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(task.status == 0);
253be633ff1SOded Mashbach reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
254be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(reg == NULL);
255be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == ++gen);
256be633ff1SOded Mashbach
257be633ff1SOded Mashbach task.initiator_port = &g_i_port_c;
258be633ff1SOded Mashbach task.status = 0;
259be633ff1SOded Mashbach rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
260be633ff1SOded Mashbach 0xc, 0, 0, 0, 0);
261be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
262be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(task.status == 0);
263be633ff1SOded Mashbach reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
264be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(reg == NULL);
265be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == ++gen);
266be633ff1SOded Mashbach
267be633ff1SOded Mashbach task.initiator_port = &g_i_port_b;
268be633ff1SOded Mashbach task.status = 0;
269be633ff1SOded Mashbach rc = scsi_pr_out_release(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS, 0xb);
270be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
271be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(task.status == 0);
272be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == 0x0);
273be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0x0);
274be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder == NULL);
275be633ff1SOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
276be633ff1SOded Mashbach
277be633ff1SOded Mashbach ut_deinit_reservation_test();
278be633ff1SOded Mashbach }
279be633ff1SOded Mashbach
280be633ff1SOded Mashbach static void
test_all_registrant_reservation_access(void)281*cde2142cSOded Mashbach test_all_registrant_reservation_access(void)
282*cde2142cSOded Mashbach {
283*cde2142cSOded Mashbach struct spdk_scsi_pr_registrant *reg;
284*cde2142cSOded Mashbach struct spdk_scsi_task task = {0};
285*cde2142cSOded Mashbach uint8_t cdb[32] = {0};
286*cde2142cSOded Mashbach uint32_t gen;
287*cde2142cSOded Mashbach int rc;
288*cde2142cSOded Mashbach
289*cde2142cSOded Mashbach task.lun = &g_lun;
290*cde2142cSOded Mashbach task.target_port = &g_t_port_0;
291*cde2142cSOded Mashbach task.cdb = cdb;
292*cde2142cSOded Mashbach
293*cde2142cSOded Mashbach ut_init_reservation_test();
294*cde2142cSOded Mashbach
295*cde2142cSOded Mashbach test_build_registrants();
296*cde2142cSOded Mashbach gen = g_lun.pr_generation;
297*cde2142cSOded Mashbach
298*cde2142cSOded Mashbach /* Test case: registered host A takes EXCLUSIVE_ACCESS_ALL_REGS reservation */
299*cde2142cSOded Mashbach task.initiator_port = &g_i_port_a;
300*cde2142cSOded Mashbach task.status = 0;
301*cde2142cSOded Mashbach rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS,
302*cde2142cSOded Mashbach 0xa, 0, 0, 0);
303*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
304*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(task.status == 0);
305*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS);
306*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
307*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
308*cde2142cSOded Mashbach
309*cde2142cSOded Mashbach /* Test case: registered host B tries getting read access */
310*cde2142cSOded Mashbach task.initiator_port = &g_i_port_b;
311*cde2142cSOded Mashbach task.status = 0;
312*cde2142cSOded Mashbach task.cdb[0] = SPDK_SBC_READ_6;
313*cde2142cSOded Mashbach rc = scsi_pr_check(&task);
314*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
315*cde2142cSOded Mashbach
316*cde2142cSOded Mashbach /* Test case: registered host B tries getting write access */
317*cde2142cSOded Mashbach task.initiator_port = &g_i_port_b;
318*cde2142cSOded Mashbach task.status = 0;
319*cde2142cSOded Mashbach task.cdb[0] = SPDK_SBC_WRITE_12;
320*cde2142cSOded Mashbach rc = scsi_pr_check(&task);
321*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
322*cde2142cSOded Mashbach
323*cde2142cSOded Mashbach /* Test case: B unregisters */
324*cde2142cSOded Mashbach task.initiator_port = &g_i_port_b;
325*cde2142cSOded Mashbach task.status = 0;
326*cde2142cSOded Mashbach rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
327*cde2142cSOded Mashbach 0xb, 0, 0, 0, 0);
328*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(rc == 0);
329*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(task.status == 0);
330*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == ++gen);
331*cde2142cSOded Mashbach reg = scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
332*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(reg == NULL);
333*cde2142cSOded Mashbach
334*cde2142cSOded Mashbach /* Test case: un register host B tries getting read access */
335*cde2142cSOded Mashbach task.initiator_port = &g_i_port_b;
336*cde2142cSOded Mashbach task.status = 0;
337*cde2142cSOded Mashbach task.cdb[0] = SPDK_SBC_READ_6;
338*cde2142cSOded Mashbach rc = scsi_pr_check(&task);
339*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(rc < 0);
340*cde2142cSOded Mashbach
341*cde2142cSOded Mashbach /* Test case: un register host B tries getting write access */
342*cde2142cSOded Mashbach task.initiator_port = &g_i_port_b;
343*cde2142cSOded Mashbach task.status = 0;
344*cde2142cSOded Mashbach task.cdb[0] = SPDK_SBC_WRITE_12;
345*cde2142cSOded Mashbach rc = scsi_pr_check(&task);
346*cde2142cSOded Mashbach SPDK_CU_ASSERT_FATAL(rc < 0);
347*cde2142cSOded Mashbach
348*cde2142cSOded Mashbach ut_deinit_reservation_test();
349*cde2142cSOded Mashbach }
350*cde2142cSOded Mashbach
351*cde2142cSOded Mashbach static void
test_reservation_reserve(void)352d7d44988SChangpeng Liu test_reservation_reserve(void)
353d7d44988SChangpeng Liu {
354d7d44988SChangpeng Liu struct spdk_scsi_pr_registrant *reg;
355d7d44988SChangpeng Liu struct spdk_scsi_task task = {0};
356d7d44988SChangpeng Liu uint32_t gen;
357d7d44988SChangpeng Liu int rc;
358d7d44988SChangpeng Liu
359d7d44988SChangpeng Liu task.lun = &g_lun;
360d7d44988SChangpeng Liu task.target_port = &g_t_port_0;
361d7d44988SChangpeng Liu
362d7d44988SChangpeng Liu ut_init_reservation_test();
36344c70f82SChangpeng Liu /* Test Case: call Release without a reservation */
36444c70f82SChangpeng Liu rc = scsi2_release(&task);
36544c70f82SChangpeng Liu CU_ASSERT(rc == -EINVAL);
36644c70f82SChangpeng Liu CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
36744c70f82SChangpeng Liu
368d7d44988SChangpeng Liu test_build_registrants();
369d7d44988SChangpeng Liu
370d7d44988SChangpeng Liu gen = g_lun.pr_generation;
371d7d44988SChangpeng Liu
372d7d44988SChangpeng Liu task.initiator_port = &g_i_port_a;
373d7d44988SChangpeng Liu task.status = 0;
374d7d44988SChangpeng Liu /* Test Case: Host A acquires the reservation */
37533a29747SShuhei Matsumoto rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
376d7d44988SChangpeng Liu 0xa, 0, 0, 0);
377d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
378d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
379d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
380d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
381d7d44988SChangpeng Liu
382d7d44988SChangpeng Liu /* Test Case: Host B acquires the reservation, reservation
383d7d44988SChangpeng Liu * conflict is expected.
384d7d44988SChangpeng Liu */
385d7d44988SChangpeng Liu task.initiator_port = &g_i_port_b;
386d7d44988SChangpeng Liu task.status = 0;
38733a29747SShuhei Matsumoto rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
388d7d44988SChangpeng Liu 0xb, 0, 0, 0);
389d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
390d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
391d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
392d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
393d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
394d7d44988SChangpeng Liu
395d7d44988SChangpeng Liu /* Test Case: Host A unregister with reservation */
396d7d44988SChangpeng Liu task.initiator_port = &g_i_port_a;
397d7d44988SChangpeng Liu task.status = 0;
39833a29747SShuhei Matsumoto rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
399d7d44988SChangpeng Liu 0xa, 0, 0, 0, 0);
400d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
401d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == 0);
402d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0);
403d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
40433a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
405d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg == NULL);
406d7d44988SChangpeng Liu
407d7d44988SChangpeng Liu /* Test Case: Host B acquires the reservation */
408d7d44988SChangpeng Liu task.initiator_port = &g_i_port_b;
409d7d44988SChangpeng Liu task.status = 0;
41033a29747SShuhei Matsumoto rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
411d7d44988SChangpeng Liu 0xb, 0, 0, 0);
412d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
413d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
414d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
415d7d44988SChangpeng Liu
416d7d44988SChangpeng Liu /* Test Case: Host C acquires the reservation with invalid type */
417d7d44988SChangpeng Liu task.initiator_port = &g_i_port_c;
418d7d44988SChangpeng Liu task.status = 0;
41933a29747SShuhei Matsumoto rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
420d7d44988SChangpeng Liu 0xc, 0, 0, 0);
421d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
422d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
423d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
424d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
425d7d44988SChangpeng Liu
426d7d44988SChangpeng Liu /* Test Case: Host C acquires the reservation, all registrants type */
427d7d44988SChangpeng Liu task.status = 0;
42833a29747SShuhei Matsumoto rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
429d7d44988SChangpeng Liu 0xc, 0, 0, 0);
430d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
431d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
432d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
433d7d44988SChangpeng Liu
434d7d44988SChangpeng Liu ut_deinit_reservation_test();
435d7d44988SChangpeng Liu }
436d7d44988SChangpeng Liu
437d7d44988SChangpeng Liu static void
test_reservation_preempt_non_all_regs(void)438d7d44988SChangpeng Liu test_reservation_preempt_non_all_regs(void)
439d7d44988SChangpeng Liu {
440d7d44988SChangpeng Liu struct spdk_scsi_pr_registrant *reg;
441d7d44988SChangpeng Liu struct spdk_scsi_task task = {0};
442d7d44988SChangpeng Liu uint32_t gen;
443d7d44988SChangpeng Liu int rc;
444d7d44988SChangpeng Liu
445d7d44988SChangpeng Liu task.lun = &g_lun;
446d7d44988SChangpeng Liu task.target_port = &g_t_port_0;
447d7d44988SChangpeng Liu
448d7d44988SChangpeng Liu ut_init_reservation_test();
449d7d44988SChangpeng Liu test_build_registrants();
450d7d44988SChangpeng Liu
451d7d44988SChangpeng Liu task.initiator_port = &g_i_port_a;
452d7d44988SChangpeng Liu task.status = 0;
453d7d44988SChangpeng Liu gen = g_lun.pr_generation;
454d7d44988SChangpeng Liu /* Host A acquires the reservation */
45533a29747SShuhei Matsumoto rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
456d7d44988SChangpeng Liu 0xa, 0, 0, 0);
457d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
458d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
459d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
460d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
461d7d44988SChangpeng Liu
462c9c7c281SJosh Soref /* Test Case: Host B preempts Host A, Check condition is expected
463d7d44988SChangpeng Liu * for zeroed service action reservation key */
464d7d44988SChangpeng Liu task.initiator_port = &g_i_port_b;
465d7d44988SChangpeng Liu task.status = 0;
46633a29747SShuhei Matsumoto rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
467d7d44988SChangpeng Liu SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
468d7d44988SChangpeng Liu 0xb, 0);
469d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
470d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
471d7d44988SChangpeng Liu
472c9c7c281SJosh Soref /* Test Case: Host B preempts Host A, Host A is unregistered */
473d7d44988SChangpeng Liu task.status = 0;
474d7d44988SChangpeng Liu gen = g_lun.pr_generation;
47533a29747SShuhei Matsumoto rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
476d7d44988SChangpeng Liu SPDK_SCSI_PR_WRITE_EXCLUSIVE,
477d7d44988SChangpeng Liu 0xb, 0xa);
478d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
479d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
480d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
481d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
48233a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
483d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg == NULL);
484d7d44988SChangpeng Liu
485d7d44988SChangpeng Liu /* Test Case: Host B preempts itself */
486d7d44988SChangpeng Liu task.status = 0;
487d7d44988SChangpeng Liu gen = g_lun.pr_generation;
48833a29747SShuhei Matsumoto rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
489d7d44988SChangpeng Liu SPDK_SCSI_PR_WRITE_EXCLUSIVE,
490d7d44988SChangpeng Liu 0xb, 0xb);
491d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
492d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
493d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
494d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
495d7d44988SChangpeng Liu
496d7d44988SChangpeng Liu /* Test Case: Host B preempts itself and remove registrants */
497d7d44988SChangpeng Liu task.status = 0;
498d7d44988SChangpeng Liu gen = g_lun.pr_generation;
49933a29747SShuhei Matsumoto rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
500d7d44988SChangpeng Liu SPDK_SCSI_PR_WRITE_EXCLUSIVE,
501d7d44988SChangpeng Liu 0xb, 0xc);
502d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
503d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
504d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
50533a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
506d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg == NULL);
507d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
508d7d44988SChangpeng Liu
509d7d44988SChangpeng Liu ut_deinit_reservation_test();
510d7d44988SChangpeng Liu }
511d7d44988SChangpeng Liu
512d7d44988SChangpeng Liu static void
test_reservation_preempt_all_regs(void)513d7d44988SChangpeng Liu test_reservation_preempt_all_regs(void)
514d7d44988SChangpeng Liu {
515d7d44988SChangpeng Liu struct spdk_scsi_pr_registrant *reg;
516d7d44988SChangpeng Liu struct spdk_scsi_task task = {0};
517d7d44988SChangpeng Liu uint32_t gen;
518d7d44988SChangpeng Liu int rc;
519d7d44988SChangpeng Liu
520d7d44988SChangpeng Liu task.lun = &g_lun;
521d7d44988SChangpeng Liu task.target_port = &g_t_port_0;
522d7d44988SChangpeng Liu
523d7d44988SChangpeng Liu ut_init_reservation_test();
524d7d44988SChangpeng Liu test_build_registrants();
525d7d44988SChangpeng Liu
526d7d44988SChangpeng Liu /* Test Case: No reservation yet, Host B removes Host C's registrant */
527d7d44988SChangpeng Liu task.initiator_port = &g_i_port_b;
528d7d44988SChangpeng Liu task.status = 0;
529d7d44988SChangpeng Liu gen = g_lun.pr_generation;
53033a29747SShuhei Matsumoto rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
531d7d44988SChangpeng Liu SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
532d7d44988SChangpeng Liu 0xb, 0xc);
533d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
53433a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
535d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg == NULL);
536d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
537d7d44988SChangpeng Liu
538d7d44988SChangpeng Liu task.initiator_port = &g_i_port_a;
539d7d44988SChangpeng Liu task.status = 0;
540d7d44988SChangpeng Liu gen = g_lun.pr_generation;
541d7d44988SChangpeng Liu /* Host A acquires the reservation */
54233a29747SShuhei Matsumoto rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
543d7d44988SChangpeng Liu 0xa, 0, 0, 0);
544d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
545d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
546d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
547d7d44988SChangpeng Liu
548d7d44988SChangpeng Liu /* Test Case: Host B removes Host A's registrant and preempt */
549d7d44988SChangpeng Liu task.initiator_port = &g_i_port_b;
550d7d44988SChangpeng Liu task.status = 0;
551d7d44988SChangpeng Liu gen = g_lun.pr_generation;
55233a29747SShuhei Matsumoto rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
553d7d44988SChangpeng Liu SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS,
554d7d44988SChangpeng Liu 0xb, 0x0);
555d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
55633a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
557d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg == NULL);
558d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS);
559d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
560d7d44988SChangpeng Liu
561d7d44988SChangpeng Liu ut_deinit_reservation_test();
562d7d44988SChangpeng Liu }
563d7d44988SChangpeng Liu
564d7d44988SChangpeng Liu static void
test_reservation_cmds_conflict(void)565d7d44988SChangpeng Liu test_reservation_cmds_conflict(void)
566d7d44988SChangpeng Liu {
567d7d44988SChangpeng Liu struct spdk_scsi_pr_registrant *reg;
568d7d44988SChangpeng Liu struct spdk_scsi_task task = {0};
569d7d44988SChangpeng Liu uint8_t cdb[32];
570d7d44988SChangpeng Liu int rc;
571d7d44988SChangpeng Liu
572d7d44988SChangpeng Liu task.lun = &g_lun;
573d7d44988SChangpeng Liu task.target_port = &g_t_port_0;
574d7d44988SChangpeng Liu task.cdb = cdb;
575d7d44988SChangpeng Liu
576d7d44988SChangpeng Liu ut_init_reservation_test();
577d7d44988SChangpeng Liu test_build_registrants();
578d7d44988SChangpeng Liu
579d7d44988SChangpeng Liu /* Host A acquires the reservation */
580d7d44988SChangpeng Liu task.initiator_port = &g_i_port_a;
58133a29747SShuhei Matsumoto rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
582d7d44988SChangpeng Liu 0xa, 0, 0, 0);
583d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
584d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
585d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
586d7d44988SChangpeng Liu
587d7d44988SChangpeng Liu /* Remove Host B registrant */
588d7d44988SChangpeng Liu task.initiator_port = &g_i_port_b;
589d7d44988SChangpeng Liu task.status = 0;
59033a29747SShuhei Matsumoto rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
591d7d44988SChangpeng Liu 0xb, 0, 0, 0, 0);
592d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
59333a29747SShuhei Matsumoto reg = scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
594d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(reg == NULL);
595d7d44988SChangpeng Liu
596d7d44988SChangpeng Liu /* Test Case: Host B sends Read/Write commands,
597d7d44988SChangpeng Liu * reservation conflict is expected.
598d7d44988SChangpeng Liu */
599d7d44988SChangpeng Liu task.cdb[0] = SPDK_SBC_READ_10;
600d7d44988SChangpeng Liu task.status = 0;
60118dec401SShuhei Matsumoto rc = scsi_pr_check(&task);
602d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
603d7d44988SChangpeng Liu task.cdb[0] = SPDK_SBC_WRITE_10;
604d7d44988SChangpeng Liu task.status = 0;
60518dec401SShuhei Matsumoto rc = scsi_pr_check(&task);
606d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
607d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
608d7d44988SChangpeng Liu
609d7d44988SChangpeng Liu /* Test Case: Host C sends Read/Write commands */
610d7d44988SChangpeng Liu task.initiator_port = &g_i_port_c;
611d7d44988SChangpeng Liu task.cdb[0] = SPDK_SBC_READ_10;
612d7d44988SChangpeng Liu task.status = 0;
61318dec401SShuhei Matsumoto rc = scsi_pr_check(&task);
614d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
615d7d44988SChangpeng Liu task.cdb[0] = SPDK_SBC_WRITE_10;
616d7d44988SChangpeng Liu task.status = 0;
61718dec401SShuhei Matsumoto rc = scsi_pr_check(&task);
618d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
619d7d44988SChangpeng Liu
620d7d44988SChangpeng Liu /* Host A preempts itself with SPDK_SCSI_PR_EXCLUSIVE_ACCESS */
621d7d44988SChangpeng Liu task.initiator_port = &g_i_port_a;
62233a29747SShuhei Matsumoto rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
623d7d44988SChangpeng Liu SPDK_SCSI_PR_EXCLUSIVE_ACCESS,
624d7d44988SChangpeng Liu 0xa, 0xa);
625d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
626d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS);
627d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
628d7d44988SChangpeng Liu
629d7d44988SChangpeng Liu /* Test Case: Host C sends Read/Write commands */
630d7d44988SChangpeng Liu task.initiator_port = &g_i_port_c;
631d7d44988SChangpeng Liu task.cdb[0] = SPDK_SBC_READ_10;
632d7d44988SChangpeng Liu task.status = 0;
63318dec401SShuhei Matsumoto rc = scsi_pr_check(&task);
634d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
635d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
636d7d44988SChangpeng Liu task.cdb[0] = SPDK_SBC_WRITE_10;
637d7d44988SChangpeng Liu task.status = 0;
63818dec401SShuhei Matsumoto rc = scsi_pr_check(&task);
639d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
640d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
641d7d44988SChangpeng Liu
642d7d44988SChangpeng Liu /* Test Case: Host B sends Read/Write commands */
643d7d44988SChangpeng Liu task.initiator_port = &g_i_port_b;
644d7d44988SChangpeng Liu task.cdb[0] = SPDK_SBC_READ_10;
645d7d44988SChangpeng Liu task.status = 0;
64618dec401SShuhei Matsumoto rc = scsi_pr_check(&task);
647d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
648d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
649d7d44988SChangpeng Liu task.cdb[0] = SPDK_SBC_WRITE_10;
650d7d44988SChangpeng Liu task.status = 0;
65118dec401SShuhei Matsumoto rc = scsi_pr_check(&task);
652d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
653d7d44988SChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
654d7d44988SChangpeng Liu
655d7d44988SChangpeng Liu ut_deinit_reservation_test();
656d7d44988SChangpeng Liu }
657d7d44988SChangpeng Liu
65851fe275fSChangpeng Liu static void
test_scsi2_reserve_release(void)65951fe275fSChangpeng Liu test_scsi2_reserve_release(void)
66051fe275fSChangpeng Liu {
66151fe275fSChangpeng Liu struct spdk_scsi_task task = {0};
66251fe275fSChangpeng Liu uint8_t cdb[32] = {};
66351fe275fSChangpeng Liu int rc;
66451fe275fSChangpeng Liu
66551fe275fSChangpeng Liu task.lun = &g_lun;
66651fe275fSChangpeng Liu task.target_port = &g_t_port_0;
66751fe275fSChangpeng Liu task.cdb = cdb;
66851fe275fSChangpeng Liu
66951fe275fSChangpeng Liu ut_init_reservation_test();
67051fe275fSChangpeng Liu
67151fe275fSChangpeng Liu /* Test Case: SPC2 RESERVE from Host A */
67251fe275fSChangpeng Liu task.initiator_port = &g_i_port_a;
67351fe275fSChangpeng Liu task.cdb[0] = SPDK_SPC2_RESERVE_10;
67451fe275fSChangpeng Liu rc = scsi2_reserve(&task, task.cdb);
67551fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
67651fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
67751fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == SCSI_SPC2_RESERVE);
67851fe275fSChangpeng Liu
67951fe275fSChangpeng Liu /* Test Case: READ command from Host B */
68051fe275fSChangpeng Liu task.initiator_port = &g_i_port_b;
68151fe275fSChangpeng Liu task.cdb[0] = SPDK_SBC_READ_10;
68251fe275fSChangpeng Liu task.status = 0;
68351fe275fSChangpeng Liu rc = scsi2_reserve_check(&task);
68451fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(rc < 0);
68551fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
68651fe275fSChangpeng Liu
68751fe275fSChangpeng Liu /* Test Case: SPDK_SPC2_RELEASE10 command from Host B */
68851fe275fSChangpeng Liu task.initiator_port = &g_i_port_b;
68951fe275fSChangpeng Liu task.cdb[0] = SPDK_SPC2_RELEASE_10;
69051fe275fSChangpeng Liu task.status = 0;
69151fe275fSChangpeng Liu rc = scsi2_reserve_check(&task);
69251fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
69351fe275fSChangpeng Liu
69451fe275fSChangpeng Liu rc = scsi2_release(&task);
69551fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
69651fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder == NULL);
69751fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == 0);
69851fe275fSChangpeng Liu
69951fe275fSChangpeng Liu /* Test Case: SPC2 RESERVE from Host B */
70051fe275fSChangpeng Liu task.initiator_port = &g_i_port_b;
70151fe275fSChangpeng Liu task.cdb[0] = SPDK_SPC2_RESERVE_10;
70251fe275fSChangpeng Liu rc = scsi2_reserve(&task, task.cdb);
70351fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
70451fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
70551fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == SCSI_SPC2_RESERVE);
70651fe275fSChangpeng Liu
70751fe275fSChangpeng Liu /* Test Case: READ command from Host B */
70851fe275fSChangpeng Liu task.initiator_port = &g_i_port_b;
70951fe275fSChangpeng Liu task.cdb[0] = SPDK_SBC_READ_10;
71051fe275fSChangpeng Liu rc = scsi2_reserve_check(&task);
71151fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
71251fe275fSChangpeng Liu
71351fe275fSChangpeng Liu /* Test Case: SPDK_SPC2_RELEASE10 command from Host A */
71451fe275fSChangpeng Liu task.initiator_port = &g_i_port_a;
71551fe275fSChangpeng Liu task.cdb[0] = SPDK_SPC2_RELEASE_10;
71651fe275fSChangpeng Liu
71751fe275fSChangpeng Liu rc = scsi2_release(&task);
71851fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
71951fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder == NULL);
72051fe275fSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == 0);
72151fe275fSChangpeng Liu
72251fe275fSChangpeng Liu ut_deinit_reservation_test();
72351fe275fSChangpeng Liu }
72451fe275fSChangpeng Liu
725b18895d0SChangpeng Liu static void
test_pr_with_scsi2_reserve_release(void)726b18895d0SChangpeng Liu test_pr_with_scsi2_reserve_release(void)
727b18895d0SChangpeng Liu {
728b18895d0SChangpeng Liu struct spdk_scsi_task task = {0};
729b18895d0SChangpeng Liu uint8_t cdb[32] = {};
730b18895d0SChangpeng Liu int rc;
731b18895d0SChangpeng Liu
732b18895d0SChangpeng Liu task.lun = &g_lun;
733b18895d0SChangpeng Liu task.target_port = &g_t_port_0;
734b18895d0SChangpeng Liu task.cdb = cdb;
735b18895d0SChangpeng Liu
736b18895d0SChangpeng Liu ut_init_reservation_test();
737b18895d0SChangpeng Liu test_build_registrants();
738b18895d0SChangpeng Liu
739b18895d0SChangpeng Liu task.initiator_port = &g_i_port_a;
740b18895d0SChangpeng Liu task.status = 0;
741b18895d0SChangpeng Liu /* Test Case: Host A acquires the reservation */
742b18895d0SChangpeng Liu rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
743b18895d0SChangpeng Liu 0xa, 0, 0, 0);
744b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
745b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
746b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
747b18895d0SChangpeng Liu
748b18895d0SChangpeng Liu /* Test Case: SPDK_SPC2_RESERVE_10 command from Host B */
749b18895d0SChangpeng Liu task.initiator_port = &g_i_port_b;
750b18895d0SChangpeng Liu task.cdb[0] = SPDK_SPC2_RESERVE_10;
751b18895d0SChangpeng Liu /* SPC2 RESERVE/RELEASE will pass to scsi2_reserve/release */
752b18895d0SChangpeng Liu rc = scsi_pr_check(&task);
753b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
754b18895d0SChangpeng Liu
755b18895d0SChangpeng Liu /* do nothing with PR but have good status */
756b18895d0SChangpeng Liu rc = scsi2_reserve(&task, task.cdb);
757b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
758b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
759b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
760b18895d0SChangpeng Liu
761b18895d0SChangpeng Liu rc = scsi2_release(&task);
762b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(rc == 0);
763b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
764b18895d0SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
765b18895d0SChangpeng Liu
766b18895d0SChangpeng Liu ut_deinit_reservation_test();
767b18895d0SChangpeng Liu }
768b18895d0SChangpeng Liu
769d7d44988SChangpeng Liu int
main(int argc,char ** argv)770d7d44988SChangpeng Liu main(int argc, char **argv)
771d7d44988SChangpeng Liu {
772d7d44988SChangpeng Liu CU_pSuite suite = NULL;
773d7d44988SChangpeng Liu unsigned int num_failures;
774d7d44988SChangpeng Liu
77578b696bcSVitaliy Mysak CU_initialize_registry();
776d7d44988SChangpeng Liu
777d7d44988SChangpeng Liu suite = CU_add_suite("reservation_suite", NULL, NULL);
778dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, test_reservation_register);
779dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, test_reservation_reserve);
780be633ff1SOded Mashbach CU_ADD_TEST(suite, test_all_registrant_reservation_reserve);
781*cde2142cSOded Mashbach CU_ADD_TEST(suite, test_all_registrant_reservation_access);
782dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, test_reservation_preempt_non_all_regs);
783dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, test_reservation_preempt_all_regs);
784dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, test_reservation_cmds_conflict);
78551fe275fSChangpeng Liu CU_ADD_TEST(suite, test_scsi2_reserve_release);
786b18895d0SChangpeng Liu CU_ADD_TEST(suite, test_pr_with_scsi2_reserve_release);
787d7d44988SChangpeng Liu
788ea941caeSKonrad Sztyber num_failures = spdk_ut_run_tests(argc, argv, NULL);
789d7d44988SChangpeng Liu CU_cleanup_registry();
790d7d44988SChangpeng Liu return num_failures;
791d7d44988SChangpeng Liu
792d7d44988SChangpeng Liu }
793