LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/scsi/scsi_pr.c - scsi_pr_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 473 473 100.0 %
Date: 2024-07-10 18:23:29 Functions: 18 18 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 167 330 50.6 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2019 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "scsi/port.c"
       9                 :            : #include "scsi/scsi_pr.c"
      10                 :            : 
      11                 :            : #include "spdk_internal/cunit.h"
      12                 :            : 
      13                 :            : #include "spdk_internal/mock.h"
      14                 :            : 
      15                 :          6 : SPDK_LOG_REGISTER_COMPONENT(scsi)
      16                 :            : 
      17                 :            : void
      18                 :        120 : spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
      19                 :            :                           int asc, int ascq)
      20                 :            : {
      21                 :        120 :         task->status = sc;
      22                 :        120 : }
      23                 :            : 
      24                 :            : /*
      25                 :            :  * Reservation Unit Test Configuration
      26                 :            :  *
      27                 :            :  *  --------      --------      -------
      28                 :            :  * | Host A |    | Host B |    | Host C|
      29                 :            :  *  --------      --------      -------
      30                 :            :  *     |             |             |
      31                 :            :  *   ------        ------        ------
      32                 :            :  *  |Port A|      |Port B|      |Port C|
      33                 :            :  *   ------        ------        ------
      34                 :            :  *      \            |             /
      35                 :            :  *       \           |            /
      36                 :            :  *        \          |           /
      37                 :            :  *        ------------------------
      38                 :            :  *       |  Target Node 1 Port 0  |
      39                 :            :  *        ------------------------
      40                 :            :  *                   |
      41                 :            :  *   ----------------------------------
      42                 :            :  *  |           Target Node            |
      43                 :            :  *   ----------------------------------
      44                 :            :  *                  |
      45                 :            :  *                -----
      46                 :            :  *               |LUN 0|
      47                 :            :  *                -----
      48                 :            :  *
      49                 :            :  */
      50                 :            : 
      51                 :            : static struct spdk_scsi_lun g_lun;
      52                 :            : static struct spdk_scsi_port g_i_port_a;
      53                 :            : static struct spdk_scsi_port g_i_port_b;
      54                 :            : static struct spdk_scsi_port g_i_port_c;
      55                 :            : static struct spdk_scsi_port g_t_port_0;
      56                 :            : 
      57                 :            : static void
      58                 :         54 : ut_lun_deinit(void)
      59                 :            : {
      60                 :            :         struct spdk_scsi_pr_registrant *reg, *tmp;
      61                 :            : 
      62         [ +  + ]:        144 :         TAILQ_FOREACH_SAFE(reg, &g_lun.reg_head, link, tmp) {
      63         [ +  + ]:         90 :                 TAILQ_REMOVE(&g_lun.reg_head, reg, link);
      64                 :         90 :                 free(reg);
      65                 :            :         }
      66                 :         54 :         g_lun.reservation.rtype = 0;
      67                 :         54 :         g_lun.reservation.crkey = 0;
      68                 :         54 :         g_lun.reservation.holder = NULL;
      69                 :         54 :         g_lun.pr_generation = 0;
      70                 :         54 : }
      71                 :            : 
      72                 :            : static void
      73                 :         54 : ut_port_init(void)
      74                 :            : {
      75                 :            :         int rc;
      76                 :            : 
      77                 :            :         /* g_i_port_a */
      78                 :         54 :         rc = scsi_port_construct(&g_i_port_a, 0xa, 0,
      79                 :            :                                  "iqn.2016-06.io.spdk:fe5aacf7420a,i,0x00023d00000a");
      80         [ -  + ]:         54 :         SPDK_CU_ASSERT_FATAL(rc == 0);
      81                 :         54 :         spdk_scsi_port_set_iscsi_transport_id(&g_i_port_a,
      82                 :            :                                               "iqn.2016-06.io.spdk:fe5aacf7420a", 0x00023d00000a);
      83                 :            :         /* g_i_port_b */
      84                 :         54 :         rc = scsi_port_construct(&g_i_port_b, 0xb, 0,
      85                 :            :                                  "iqn.2016-06.io.spdk:fe5aacf7420b,i,0x00023d00000b");
      86         [ -  + ]:         54 :         SPDK_CU_ASSERT_FATAL(rc == 0);
      87                 :         54 :         spdk_scsi_port_set_iscsi_transport_id(&g_i_port_b,
      88                 :            :                                               "iqn.2016-06.io.spdk:fe5aacf7420b", 0x00023d00000b);
      89                 :            :         /* g_i_port_c */
      90                 :         54 :         rc = scsi_port_construct(&g_i_port_c, 0xc, 0,
      91                 :            :                                  "iqn.2016-06.io.spdk:fe5aacf7420c,i,0x00023d00000c");
      92         [ -  + ]:         54 :         SPDK_CU_ASSERT_FATAL(rc == 0);
      93                 :         54 :         spdk_scsi_port_set_iscsi_transport_id(&g_i_port_c,
      94                 :            :                                               "iqn.2016-06.io.spdk:fe5aacf7420c", 0x00023d00000c);
      95                 :            :         /* g_t_port_0 */
      96                 :         54 :         rc = scsi_port_construct(&g_t_port_0, 0x0, 1,
      97                 :            :                                  "iqn.2016-06.io.spdk:fe5aacf74200,t,0x00023d000000");
      98         [ -  + ]:         54 :         SPDK_CU_ASSERT_FATAL(rc == 0);
      99                 :         54 :         spdk_scsi_port_set_iscsi_transport_id(&g_t_port_0,
     100                 :            :                                               "iqn.2016-06.io.spdk:fe5aacf74200", 0x00023d000000);
     101                 :         54 : }
     102                 :            : 
     103                 :            : static void
     104                 :        108 : ut_lun_init(void)
     105                 :            : {
     106                 :        108 :         TAILQ_INIT(&g_lun.reg_head);
     107                 :        108 : }
     108                 :            : 
     109                 :            : static void
     110                 :         54 : ut_init_reservation_test(void)
     111                 :            : {
     112                 :         54 :         ut_lun_init();
     113                 :         54 :         ut_port_init();
     114                 :         54 :         ut_lun_init();
     115                 :         54 : }
     116                 :            : 
     117                 :            : static void
     118                 :         54 : ut_deinit_reservation_test(void)
     119                 :            : {
     120                 :         54 :         ut_lun_deinit();
     121                 :         54 : }
     122                 :            : 
     123                 :            : /* Host A: register with key 0xa.
     124                 :            :  * Host B: register with key 0xb.
     125                 :            :  * Host C: register with key 0xc.
     126                 :            :  */
     127                 :            : static void
     128                 :         48 : test_build_registrants(void)
     129                 :            : {
     130                 :            :         struct spdk_scsi_pr_registrant *reg;
     131                 :         48 :         struct spdk_scsi_task task = {0};
     132                 :            :         uint32_t gen;
     133                 :            :         int rc;
     134                 :            : 
     135                 :         48 :         task.lun = &g_lun;
     136                 :         48 :         task.target_port = &g_t_port_0;
     137                 :            : 
     138                 :         48 :         gen = g_lun.pr_generation;
     139                 :            : 
     140                 :            :         /* I_T nexus: Initiator Port A to Target Port 0 */
     141                 :         48 :         task.initiator_port = &g_i_port_a;
     142                 :            :         /* Test Case: Host A registers with a new key */
     143                 :         48 :         task.status = 0;
     144                 :         48 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     145                 :            :                                   0x0, 0xa1, 0, 0, 0);
     146         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     147                 :         48 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     148         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     149         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
     150         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     151                 :            : 
     152                 :            :         /* Test Case: Host A replaces with a new key */
     153                 :         48 :         task.status = 0;
     154                 :         48 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     155                 :            :                                   0xa1, 0xa, 0, 0, 0);
     156         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     157                 :         48 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     158         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     159         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa);
     160         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 2);
     161                 :            : 
     162                 :            :         /* Test Case: Host A replaces with a new key, reservation conflict is expected */
     163                 :         48 :         task.status = 0;
     164                 :         48 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     165                 :            :                                   0xa1, 0xdead, 0, 0, 0);
     166         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     167                 :         48 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     168         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     169         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa);
     170         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 2);
     171         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     172                 :            : 
     173                 :            :         /* I_T nexus: Initiator Port B to Target Port 0 */
     174                 :         48 :         task.initiator_port = &g_i_port_b;
     175                 :            :         /* Test Case: Host B registers with a new key */
     176                 :         48 :         task.status = 0;
     177                 :         48 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     178                 :            :                                   0x0, 0xb, 0, 0, 0);
     179         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     180                 :         48 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
     181         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     182         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb);
     183         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 3);
     184                 :            : 
     185                 :            :         /* I_T nexus: Initiator Port C to Target Port 0 */
     186                 :         48 :         task.initiator_port = &g_i_port_c;
     187                 :            :         /* Test Case: Host C registers with a new key */
     188                 :         48 :         task.status = 0;
     189                 :         48 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     190                 :            :                                   0x0, 0xc, 0, 0, 0);
     191         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     192                 :         48 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
     193         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     194         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc);
     195         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 4);
     196                 :         48 : }
     197                 :            : 
     198                 :            : static void
     199                 :          6 : test_reservation_register(void)
     200                 :            : {
     201                 :          6 :         ut_init_reservation_test();
     202                 :            : 
     203                 :          6 :         test_build_registrants();
     204                 :            : 
     205                 :          6 :         ut_deinit_reservation_test();
     206                 :          6 : }
     207                 :            : 
     208                 :            : static void
     209                 :          6 : test_all_registrant_reservation_reserve(void)
     210                 :            : {
     211                 :            :         struct spdk_scsi_pr_registrant *reg;
     212                 :          6 :         struct spdk_scsi_task task = {0};
     213                 :            :         uint32_t gen;
     214                 :            :         int rc;
     215                 :            : 
     216                 :          6 :         task.lun = &g_lun;
     217                 :          6 :         task.target_port = &g_t_port_0;
     218                 :            : 
     219                 :          6 :         ut_init_reservation_test();
     220                 :            : 
     221                 :          6 :         test_build_registrants();
     222                 :          6 :         gen = g_lun.pr_generation;
     223                 :            :         /* Test Case: Host A takes all registrant reservation */
     224                 :          6 :         task.initiator_port = &g_i_port_a;
     225                 :          6 :         task.status = 0;
     226                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
     227                 :            :                                  0xa, 0, 0, 0);
     228         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     229         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == 0);
     230         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     231         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     232         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     233                 :            : 
     234                 :            :         /* Test case: Host A release reservation - which should pass to next inline -> Host B */
     235                 :          6 :         task.initiator_port = &g_i_port_a;
     236                 :          6 :         task.status = 0;
     237                 :          6 :         rc = scsi_pr_out_release(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS, 0xa);
     238         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     239         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == 0);
     240         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     241         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
     242         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     243                 :            : 
     244                 :            :         /* Test case: Host A unregister + Host C unregister: Host B left alone.
     245                 :            :          * Host B than releases reservation - lun should not have any reservation holder *
     246                 :            :          */
     247                 :          6 :         task.initiator_port = &g_i_port_a;
     248                 :          6 :         task.status = 0;
     249                 :          6 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     250                 :            :                                   0xa, 0, 0, 0, 0);
     251         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     252         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == 0);
     253                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     254         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     255         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == ++gen);
     256                 :            : 
     257                 :          6 :         task.initiator_port = &g_i_port_c;
     258                 :          6 :         task.status = 0;
     259                 :          6 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     260                 :            :                                   0xc, 0, 0, 0, 0);
     261         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     262         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == 0);
     263                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
     264         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     265         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == ++gen);
     266                 :            : 
     267                 :          6 :         task.initiator_port = &g_i_port_b;
     268                 :          6 :         task.status = 0;
     269                 :          6 :         rc = scsi_pr_out_release(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS, 0xb);
     270         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     271         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == 0);
     272         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == 0x0);
     273         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0x0);
     274         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder == NULL);
     275         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     276                 :            : 
     277                 :          6 :         ut_deinit_reservation_test();
     278                 :          6 : }
     279                 :            : 
     280                 :            : static void
     281                 :          6 : test_all_registrant_reservation_access(void)
     282                 :            : {
     283                 :            :         struct spdk_scsi_pr_registrant *reg;
     284                 :          6 :         struct spdk_scsi_task task = {0};
     285                 :          6 :         uint8_t cdb[32] = {0};
     286                 :            :         uint32_t gen;
     287                 :            :         int rc;
     288                 :            : 
     289                 :          6 :         task.lun = &g_lun;
     290                 :          6 :         task.target_port = &g_t_port_0;
     291                 :          6 :         task.cdb = cdb;
     292                 :            : 
     293                 :          6 :         ut_init_reservation_test();
     294                 :            : 
     295                 :          6 :         test_build_registrants();
     296                 :          6 :         gen = g_lun.pr_generation;
     297                 :            : 
     298                 :            :         /* Test case: registered host A takes EXCLUSIVE_ACCESS_ALL_REGS reservation */
     299                 :          6 :         task.initiator_port = &g_i_port_a;
     300                 :          6 :         task.status = 0;
     301                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS,
     302                 :            :                                  0xa, 0, 0, 0);
     303         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     304         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == 0);
     305         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS);
     306         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     307         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     308                 :            : 
     309                 :            :         /* Test case: registered host B tries getting read access */
     310                 :          6 :         task.initiator_port = &g_i_port_b;
     311                 :          6 :         task.status = 0;
     312                 :          6 :         task.cdb[0] = SPDK_SBC_READ_6;
     313                 :          6 :         rc = scsi_pr_check(&task);
     314         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     315                 :            : 
     316                 :            :         /* Test case: registered host B tries getting write access */
     317                 :          6 :         task.initiator_port = &g_i_port_b;
     318                 :          6 :         task.status = 0;
     319                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_12;
     320                 :          6 :         rc = scsi_pr_check(&task);
     321         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     322                 :            : 
     323                 :            :         /* Test case: B unregisters */
     324                 :          6 :         task.initiator_port = &g_i_port_b;
     325                 :          6 :         task.status = 0;
     326                 :          6 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     327                 :            :                                   0xb, 0, 0, 0, 0);
     328         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     329         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == 0);
     330         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == ++gen);
     331                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
     332         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     333                 :            : 
     334                 :            :         /* Test case: un register host B tries getting read access */
     335                 :          6 :         task.initiator_port = &g_i_port_b;
     336                 :          6 :         task.status = 0;
     337                 :          6 :         task.cdb[0] = SPDK_SBC_READ_6;
     338                 :          6 :         rc = scsi_pr_check(&task);
     339         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     340                 :            : 
     341                 :            :         /* Test case: un register host B tries getting write access */
     342                 :          6 :         task.initiator_port = &g_i_port_b;
     343                 :          6 :         task.status = 0;
     344                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_12;
     345                 :          6 :         rc = scsi_pr_check(&task);
     346         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     347                 :            : 
     348                 :          6 :         ut_deinit_reservation_test();
     349                 :          6 : }
     350                 :            : 
     351                 :            : static void
     352                 :          6 : test_reservation_reserve(void)
     353                 :            : {
     354                 :            :         struct spdk_scsi_pr_registrant *reg;
     355                 :          6 :         struct spdk_scsi_task task = {0};
     356                 :            :         uint32_t gen;
     357                 :            :         int rc;
     358                 :            : 
     359                 :          6 :         task.lun = &g_lun;
     360                 :          6 :         task.target_port = &g_t_port_0;
     361                 :            : 
     362                 :          6 :         ut_init_reservation_test();
     363                 :            :         /* Test Case: call Release without a reservation */
     364                 :          6 :         rc = scsi2_release(&task);
     365                 :          6 :         CU_ASSERT(rc == -EINVAL);
     366                 :          6 :         CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     367                 :            : 
     368                 :          6 :         test_build_registrants();
     369                 :            : 
     370                 :          6 :         gen = g_lun.pr_generation;
     371                 :            : 
     372                 :          6 :         task.initiator_port = &g_i_port_a;
     373                 :          6 :         task.status = 0;
     374                 :            :         /* Test Case: Host A acquires the reservation */
     375                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     376                 :            :                                  0xa, 0, 0, 0);
     377         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     378         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     379         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     380         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     381                 :            : 
     382                 :            :         /* Test Case: Host B acquires the reservation, reservation
     383                 :            :          * conflict is expected.
     384                 :            :          */
     385                 :          6 :         task.initiator_port = &g_i_port_b;
     386                 :          6 :         task.status = 0;
     387                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     388                 :            :                                  0xb, 0, 0, 0);
     389         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     390         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     391         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     392         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     393         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     394                 :            : 
     395                 :            :         /* Test Case: Host A unregister with reservation */
     396                 :          6 :         task.initiator_port = &g_i_port_a;
     397                 :          6 :         task.status = 0;
     398                 :          6 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     399                 :            :                                   0xa, 0, 0, 0, 0);
     400         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     401         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == 0);
     402         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0);
     403         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     404                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     405         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     406                 :            : 
     407                 :            :         /* Test Case: Host B acquires the reservation */
     408                 :          6 :         task.initiator_port = &g_i_port_b;
     409                 :          6 :         task.status = 0;
     410                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
     411                 :            :                                  0xb, 0, 0, 0);
     412         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     413         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     414         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     415                 :            : 
     416                 :            :         /* Test Case: Host C acquires the reservation with invalid type */
     417                 :          6 :         task.initiator_port = &g_i_port_c;
     418                 :          6 :         task.status = 0;
     419                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     420                 :            :                                  0xc, 0, 0, 0);
     421         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     422         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     423         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     424         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     425                 :            : 
     426                 :            :         /* Test Case: Host C acquires the reservation, all registrants type */
     427                 :          6 :         task.status = 0;
     428                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
     429                 :            :                                  0xc, 0, 0, 0);
     430         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     431         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     432         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     433                 :            : 
     434                 :          6 :         ut_deinit_reservation_test();
     435                 :          6 : }
     436                 :            : 
     437                 :            : static void
     438                 :          6 : test_reservation_preempt_non_all_regs(void)
     439                 :            : {
     440                 :            :         struct spdk_scsi_pr_registrant *reg;
     441                 :          6 :         struct spdk_scsi_task task = {0};
     442                 :            :         uint32_t gen;
     443                 :            :         int rc;
     444                 :            : 
     445                 :          6 :         task.lun = &g_lun;
     446                 :          6 :         task.target_port = &g_t_port_0;
     447                 :            : 
     448                 :          6 :         ut_init_reservation_test();
     449                 :          6 :         test_build_registrants();
     450                 :            : 
     451                 :          6 :         task.initiator_port = &g_i_port_a;
     452                 :          6 :         task.status = 0;
     453                 :          6 :         gen = g_lun.pr_generation;
     454                 :            :         /* Host A acquires the reservation */
     455                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     456                 :            :                                  0xa, 0, 0, 0);
     457         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     458         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     459         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     460         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     461                 :            : 
     462                 :            :         /* Test Case: Host B preempts Host A, Check condition is expected
     463                 :            :          * for zeroed service action reservation key */
     464                 :          6 :         task.initiator_port = &g_i_port_b;
     465                 :          6 :         task.status = 0;
     466                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     467                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     468                 :            :                                  0xb, 0);
     469         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     470         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     471                 :            : 
     472                 :            :         /* Test Case: Host B preempts Host A, Host A is unregistered */
     473                 :          6 :         task.status = 0;
     474                 :          6 :         gen = g_lun.pr_generation;
     475                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     476                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     477                 :            :                                  0xb, 0xa);
     478         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     479         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     480         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
     481         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     482                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     483         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     484                 :            : 
     485                 :            :         /* Test Case: Host B preempts itself */
     486                 :          6 :         task.status = 0;
     487                 :          6 :         gen = g_lun.pr_generation;
     488                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     489                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     490                 :            :                                  0xb, 0xb);
     491         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     492         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     493         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
     494         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     495                 :            : 
     496                 :            :         /* Test Case: Host B preempts itself and remove registrants */
     497                 :          6 :         task.status = 0;
     498                 :          6 :         gen = g_lun.pr_generation;
     499                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     500                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     501                 :            :                                  0xb, 0xc);
     502         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     503         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     504         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
     505                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
     506         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     507         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     508                 :            : 
     509                 :          6 :         ut_deinit_reservation_test();
     510                 :          6 : }
     511                 :            : 
     512                 :            : static void
     513                 :          6 : test_reservation_preempt_all_regs(void)
     514                 :            : {
     515                 :            :         struct spdk_scsi_pr_registrant *reg;
     516                 :          6 :         struct spdk_scsi_task task = {0};
     517                 :            :         uint32_t gen;
     518                 :            :         int rc;
     519                 :            : 
     520                 :          6 :         task.lun = &g_lun;
     521                 :          6 :         task.target_port = &g_t_port_0;
     522                 :            : 
     523                 :          6 :         ut_init_reservation_test();
     524                 :          6 :         test_build_registrants();
     525                 :            : 
     526                 :            :         /* Test Case: No reservation yet, Host B removes Host C's registrant */
     527                 :          6 :         task.initiator_port = &g_i_port_b;
     528                 :          6 :         task.status = 0;
     529                 :          6 :         gen = g_lun.pr_generation;
     530                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     531                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     532                 :            :                                  0xb, 0xc);
     533         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     534                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
     535         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     536         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     537                 :            : 
     538                 :          6 :         task.initiator_port = &g_i_port_a;
     539                 :          6 :         task.status = 0;
     540                 :          6 :         gen = g_lun.pr_generation;
     541                 :            :         /* Host A acquires the reservation */
     542                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
     543                 :            :                                  0xa, 0, 0, 0);
     544         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     545         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     546         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     547                 :            : 
     548                 :            :         /* Test Case: Host B removes Host A's registrant and preempt */
     549                 :          6 :         task.initiator_port = &g_i_port_b;
     550                 :          6 :         task.status = 0;
     551                 :          6 :         gen = g_lun.pr_generation;
     552                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     553                 :            :                                  SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS,
     554                 :            :                                  0xb, 0x0);
     555         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     556                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     557         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     558         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS);
     559         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     560                 :            : 
     561                 :          6 :         ut_deinit_reservation_test();
     562                 :          6 : }
     563                 :            : 
     564                 :            : static void
     565                 :          6 : test_reservation_cmds_conflict(void)
     566                 :            : {
     567                 :            :         struct spdk_scsi_pr_registrant *reg;
     568                 :          6 :         struct spdk_scsi_task task = {0};
     569                 :          5 :         uint8_t cdb[32];
     570                 :            :         int rc;
     571                 :            : 
     572                 :          6 :         task.lun = &g_lun;
     573                 :          6 :         task.target_port = &g_t_port_0;
     574                 :          6 :         task.cdb = cdb;
     575                 :            : 
     576                 :          6 :         ut_init_reservation_test();
     577                 :          6 :         test_build_registrants();
     578                 :            : 
     579                 :            :         /* Host A acquires the reservation */
     580                 :          6 :         task.initiator_port = &g_i_port_a;
     581                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     582                 :            :                                  0xa, 0, 0, 0);
     583         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     584         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     585         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     586                 :            : 
     587                 :            :         /* Remove Host B registrant */
     588                 :          6 :         task.initiator_port = &g_i_port_b;
     589                 :          6 :         task.status = 0;
     590                 :          6 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     591                 :            :                                   0xb, 0, 0, 0, 0);
     592         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     593                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
     594         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     595                 :            : 
     596                 :            :         /* Test Case: Host B sends Read/Write commands,
     597                 :            :          * reservation conflict is expected.
     598                 :            :          */
     599                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     600                 :          6 :         task.status = 0;
     601                 :          6 :         rc = scsi_pr_check(&task);
     602         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     603                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_10;
     604                 :          6 :         task.status = 0;
     605                 :          6 :         rc = scsi_pr_check(&task);
     606         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     607         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     608                 :            : 
     609                 :            :         /* Test Case: Host C sends Read/Write commands */
     610                 :          6 :         task.initiator_port = &g_i_port_c;
     611                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     612                 :          6 :         task.status = 0;
     613                 :          6 :         rc = scsi_pr_check(&task);
     614         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     615                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_10;
     616                 :          6 :         task.status = 0;
     617                 :          6 :         rc = scsi_pr_check(&task);
     618         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     619                 :            : 
     620                 :            :         /* Host A preempts itself with SPDK_SCSI_PR_EXCLUSIVE_ACCESS */
     621                 :          6 :         task.initiator_port = &g_i_port_a;
     622                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     623                 :            :                                  SPDK_SCSI_PR_EXCLUSIVE_ACCESS,
     624                 :            :                                  0xa, 0xa);
     625         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     626         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS);
     627         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     628                 :            : 
     629                 :            :         /* Test Case: Host C sends Read/Write commands */
     630                 :          6 :         task.initiator_port = &g_i_port_c;
     631                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     632                 :          6 :         task.status = 0;
     633                 :          6 :         rc = scsi_pr_check(&task);
     634         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     635         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     636                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_10;
     637                 :          6 :         task.status = 0;
     638                 :          6 :         rc = scsi_pr_check(&task);
     639         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     640         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     641                 :            : 
     642                 :            :         /* Test Case: Host B sends Read/Write commands */
     643                 :          6 :         task.initiator_port = &g_i_port_b;
     644                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     645                 :          6 :         task.status = 0;
     646                 :          6 :         rc = scsi_pr_check(&task);
     647         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     648         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     649                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_10;
     650                 :          6 :         task.status = 0;
     651                 :          6 :         rc = scsi_pr_check(&task);
     652         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     653         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     654                 :            : 
     655                 :          6 :         ut_deinit_reservation_test();
     656                 :          6 : }
     657                 :            : 
     658                 :            : static void
     659                 :          6 : test_scsi2_reserve_release(void)
     660                 :            : {
     661                 :          6 :         struct spdk_scsi_task task = {0};
     662                 :          6 :         uint8_t cdb[32] = {};
     663                 :            :         int rc;
     664                 :            : 
     665                 :          6 :         task.lun = &g_lun;
     666                 :          6 :         task.target_port = &g_t_port_0;
     667                 :          6 :         task.cdb = cdb;
     668                 :            : 
     669                 :          6 :         ut_init_reservation_test();
     670                 :            : 
     671                 :            :         /* Test Case: SPC2 RESERVE from Host A */
     672                 :          6 :         task.initiator_port = &g_i_port_a;
     673                 :          6 :         task.cdb[0] = SPDK_SPC2_RESERVE_10;
     674                 :          6 :         rc = scsi2_reserve(&task, task.cdb);
     675         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     676         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
     677         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == SCSI_SPC2_RESERVE);
     678                 :            : 
     679                 :            :         /* Test Case: READ command from Host B */
     680                 :          6 :         task.initiator_port = &g_i_port_b;
     681                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     682                 :          6 :         task.status = 0;
     683                 :          6 :         rc = scsi2_reserve_check(&task);
     684         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     685         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     686                 :            : 
     687                 :            :         /* Test Case: SPDK_SPC2_RELEASE10 command from Host B */
     688                 :          6 :         task.initiator_port = &g_i_port_b;
     689                 :          6 :         task.cdb[0] = SPDK_SPC2_RELEASE_10;
     690                 :          6 :         task.status = 0;
     691                 :          6 :         rc = scsi2_reserve_check(&task);
     692         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     693                 :            : 
     694                 :          6 :         rc = scsi2_release(&task);
     695         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     696         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder == NULL);
     697         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == 0);
     698                 :            : 
     699                 :            :         /* Test Case: SPC2 RESERVE from Host B */
     700                 :          6 :         task.initiator_port = &g_i_port_b;
     701                 :          6 :         task.cdb[0] = SPDK_SPC2_RESERVE_10;
     702                 :          6 :         rc = scsi2_reserve(&task, task.cdb);
     703         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     704         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
     705         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == SCSI_SPC2_RESERVE);
     706                 :            : 
     707                 :            :         /* Test Case: READ command from Host B */
     708                 :          6 :         task.initiator_port = &g_i_port_b;
     709                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     710                 :          6 :         rc = scsi2_reserve_check(&task);
     711         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     712                 :            : 
     713                 :            :         /* Test Case: SPDK_SPC2_RELEASE10 command from Host A */
     714                 :          6 :         task.initiator_port = &g_i_port_a;
     715                 :          6 :         task.cdb[0] = SPDK_SPC2_RELEASE_10;
     716                 :            : 
     717                 :          6 :         rc = scsi2_release(&task);
     718         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     719         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder == NULL);
     720         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == 0);
     721                 :            : 
     722                 :          6 :         ut_deinit_reservation_test();
     723                 :          6 : }
     724                 :            : 
     725                 :            : static void
     726                 :          6 : test_pr_with_scsi2_reserve_release(void)
     727                 :            : {
     728                 :          6 :         struct spdk_scsi_task task = {0};
     729                 :          6 :         uint8_t cdb[32] = {};
     730                 :            :         int rc;
     731                 :            : 
     732                 :          6 :         task.lun = &g_lun;
     733                 :          6 :         task.target_port = &g_t_port_0;
     734                 :          6 :         task.cdb = cdb;
     735                 :            : 
     736                 :          6 :         ut_init_reservation_test();
     737                 :          6 :         test_build_registrants();
     738                 :            : 
     739                 :          6 :         task.initiator_port = &g_i_port_a;
     740                 :          6 :         task.status = 0;
     741                 :            :         /* Test Case: Host A acquires the reservation */
     742                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     743                 :            :                                  0xa, 0, 0, 0);
     744         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     745         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     746         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     747                 :            : 
     748                 :            :         /* Test Case: SPDK_SPC2_RESERVE_10 command from Host B */
     749                 :          6 :         task.initiator_port = &g_i_port_b;
     750                 :          6 :         task.cdb[0] = SPDK_SPC2_RESERVE_10;
     751                 :            :         /* SPC2 RESERVE/RELEASE will pass to scsi2_reserve/release */
     752                 :          6 :         rc = scsi_pr_check(&task);
     753         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     754                 :            : 
     755                 :            :         /* do nothing with PR but have good status */
     756                 :          6 :         rc = scsi2_reserve(&task, task.cdb);
     757         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     758         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
     759         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     760                 :            : 
     761                 :          6 :         rc = scsi2_release(&task);
     762         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     763         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
     764         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     765                 :            : 
     766                 :          6 :         ut_deinit_reservation_test();
     767                 :          6 : }
     768                 :            : 
     769                 :            : int
     770                 :          6 : main(int argc, char **argv)
     771                 :            : {
     772                 :          6 :         CU_pSuite       suite = NULL;
     773                 :            :         unsigned int    num_failures;
     774                 :            : 
     775                 :          6 :         CU_initialize_registry();
     776                 :            : 
     777                 :          6 :         suite = CU_add_suite("reservation_suite", NULL, NULL);
     778                 :          6 :         CU_ADD_TEST(suite, test_reservation_register);
     779                 :          6 :         CU_ADD_TEST(suite, test_reservation_reserve);
     780                 :          6 :         CU_ADD_TEST(suite, test_all_registrant_reservation_reserve);
     781                 :          6 :         CU_ADD_TEST(suite, test_all_registrant_reservation_access);
     782                 :          6 :         CU_ADD_TEST(suite, test_reservation_preempt_non_all_regs);
     783                 :          6 :         CU_ADD_TEST(suite, test_reservation_preempt_all_regs);
     784                 :          6 :         CU_ADD_TEST(suite, test_reservation_cmds_conflict);
     785                 :          6 :         CU_ADD_TEST(suite, test_scsi2_reserve_release);
     786                 :          6 :         CU_ADD_TEST(suite, test_pr_with_scsi2_reserve_release);
     787                 :            : 
     788                 :          6 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     789                 :          6 :         CU_cleanup_registry();
     790                 :          6 :         return num_failures;
     791                 :            : 
     792                 :            : }

Generated by: LCOV version 1.14