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: 374 374 100.0 %
Date: 2024-07-10 21:01:08 Functions: 16 16 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 130 256 50.8 %

           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                 :         96 : spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
      19                 :            :                           int asc, int ascq)
      20                 :            : {
      21                 :         96 :         task->status = sc;
      22                 :         96 : }
      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                 :         42 : ut_lun_deinit(void)
      59                 :            : {
      60                 :            :         struct spdk_scsi_pr_registrant *reg, *tmp;
      61                 :            : 
      62         [ +  + ]:        114 :         TAILQ_FOREACH_SAFE(reg, &g_lun.reg_head, link, tmp) {
      63         [ +  + ]:         72 :                 TAILQ_REMOVE(&g_lun.reg_head, reg, link);
      64                 :         72 :                 free(reg);
      65                 :            :         }
      66                 :         42 :         g_lun.reservation.rtype = 0;
      67                 :         42 :         g_lun.reservation.crkey = 0;
      68                 :         42 :         g_lun.reservation.holder = NULL;
      69                 :         42 :         g_lun.pr_generation = 0;
      70                 :         42 : }
      71                 :            : 
      72                 :            : static void
      73                 :         42 : ut_port_init(void)
      74                 :            : {
      75                 :            :         int rc;
      76                 :            : 
      77                 :            :         /* g_i_port_a */
      78                 :         42 :         rc = scsi_port_construct(&g_i_port_a, 0xa, 0,
      79                 :            :                                  "iqn.2016-06.io.spdk:fe5aacf7420a,i,0x00023d00000a");
      80         [ -  + ]:         42 :         SPDK_CU_ASSERT_FATAL(rc == 0);
      81                 :         42 :         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                 :         42 :         rc = scsi_port_construct(&g_i_port_b, 0xb, 0,
      85                 :            :                                  "iqn.2016-06.io.spdk:fe5aacf7420b,i,0x00023d00000b");
      86         [ -  + ]:         42 :         SPDK_CU_ASSERT_FATAL(rc == 0);
      87                 :         42 :         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                 :         42 :         rc = scsi_port_construct(&g_i_port_c, 0xc, 0,
      91                 :            :                                  "iqn.2016-06.io.spdk:fe5aacf7420c,i,0x00023d00000c");
      92         [ -  + ]:         42 :         SPDK_CU_ASSERT_FATAL(rc == 0);
      93                 :         42 :         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                 :         42 :         rc = scsi_port_construct(&g_t_port_0, 0x0, 1,
      97                 :            :                                  "iqn.2016-06.io.spdk:fe5aacf74200,t,0x00023d000000");
      98         [ -  + ]:         42 :         SPDK_CU_ASSERT_FATAL(rc == 0);
      99                 :         42 :         spdk_scsi_port_set_iscsi_transport_id(&g_t_port_0,
     100                 :            :                                               "iqn.2016-06.io.spdk:fe5aacf74200", 0x00023d000000);
     101                 :         42 : }
     102                 :            : 
     103                 :            : static void
     104                 :         84 : ut_lun_init(void)
     105                 :            : {
     106                 :         84 :         TAILQ_INIT(&g_lun.reg_head);
     107                 :         84 : }
     108                 :            : 
     109                 :            : static void
     110                 :         42 : ut_init_reservation_test(void)
     111                 :            : {
     112                 :         42 :         ut_lun_init();
     113                 :         42 :         ut_port_init();
     114                 :         42 :         ut_lun_init();
     115                 :         42 : }
     116                 :            : 
     117                 :            : static void
     118                 :         42 : ut_deinit_reservation_test(void)
     119                 :            : {
     120                 :         42 :         ut_lun_deinit();
     121                 :         42 : }
     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                 :         36 : test_build_registrants(void)
     129                 :            : {
     130                 :            :         struct spdk_scsi_pr_registrant *reg;
     131                 :         36 :         struct spdk_scsi_task task = {0};
     132                 :            :         uint32_t gen;
     133                 :            :         int rc;
     134                 :            : 
     135                 :         36 :         task.lun = &g_lun;
     136                 :         36 :         task.target_port = &g_t_port_0;
     137                 :            : 
     138                 :         36 :         gen = g_lun.pr_generation;
     139                 :            : 
     140                 :            :         /* I_T nexus: Initiator Port A to Target Port 0 */
     141                 :         36 :         task.initiator_port = &g_i_port_a;
     142                 :            :         /* Test Case: Host A registers with a new key */
     143                 :         36 :         task.status = 0;
     144                 :         36 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     145                 :            :                                   0x0, 0xa1, 0, 0, 0);
     146         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     147                 :         36 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     148         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     149         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
     150         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     151                 :            : 
     152                 :            :         /* Test Case: Host A replaces with a new key */
     153                 :         36 :         task.status = 0;
     154                 :         36 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     155                 :            :                                   0xa1, 0xa, 0, 0, 0);
     156         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     157                 :         36 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     158         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     159         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa);
     160         [ -  + ]:         36 :         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                 :         36 :         task.status = 0;
     164                 :         36 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     165                 :            :                                   0xa1, 0xdead, 0, 0, 0);
     166         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     167                 :         36 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     168         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     169         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa);
     170         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 2);
     171         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     172                 :            : 
     173                 :            :         /* I_T nexus: Initiator Port B to Target Port 0 */
     174                 :         36 :         task.initiator_port = &g_i_port_b;
     175                 :            :         /* Test Case: Host B registers with a new key */
     176                 :         36 :         task.status = 0;
     177                 :         36 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     178                 :            :                                   0x0, 0xb, 0, 0, 0);
     179         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     180                 :         36 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
     181         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     182         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb);
     183         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 3);
     184                 :            : 
     185                 :            :         /* I_T nexus: Initiator Port C to Target Port 0 */
     186                 :         36 :         task.initiator_port = &g_i_port_c;
     187                 :            :         /* Test Case: Host C registers with a new key */
     188                 :         36 :         task.status = 0;
     189                 :         36 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     190                 :            :                                   0x0, 0xc, 0, 0, 0);
     191         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     192                 :         36 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
     193         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg != NULL);
     194         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc);
     195         [ -  + ]:         36 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 4);
     196                 :         36 : }
     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_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                 :            :         /* Test Case: call Release without a reservation */
     221                 :          6 :         rc = scsi2_release(&task);
     222                 :          6 :         CU_ASSERT(rc == -EINVAL);
     223                 :          6 :         CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     224                 :            : 
     225                 :          6 :         test_build_registrants();
     226                 :            : 
     227                 :          6 :         gen = g_lun.pr_generation;
     228                 :            : 
     229                 :          6 :         task.initiator_port = &g_i_port_a;
     230                 :          6 :         task.status = 0;
     231                 :            :         /* Test Case: Host A acquires the reservation */
     232                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     233                 :            :                                  0xa, 0, 0, 0);
     234         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     235         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     236         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     237         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     238                 :            : 
     239                 :            :         /* Test Case: Host B acquires the reservation, reservation
     240                 :            :          * conflict is expected.
     241                 :            :          */
     242                 :          6 :         task.initiator_port = &g_i_port_b;
     243                 :          6 :         task.status = 0;
     244                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     245                 :            :                                  0xb, 0, 0, 0);
     246         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     247         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     248         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     249         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     250         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     251                 :            : 
     252                 :            :         /* Test Case: Host A unregister with reservation */
     253                 :          6 :         task.initiator_port = &g_i_port_a;
     254                 :          6 :         task.status = 0;
     255                 :          6 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     256                 :            :                                   0xa, 0, 0, 0, 0);
     257         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     258         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == 0);
     259         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0);
     260         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     261                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     262         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     263                 :            : 
     264                 :            :         /* Test Case: Host B acquires the reservation */
     265                 :          6 :         task.initiator_port = &g_i_port_b;
     266                 :          6 :         task.status = 0;
     267                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
     268                 :            :                                  0xb, 0, 0, 0);
     269         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     270         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     271         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     272                 :            : 
     273                 :            :         /* Test Case: Host C acquires the reservation with invalid type */
     274                 :          6 :         task.initiator_port = &g_i_port_c;
     275                 :          6 :         task.status = 0;
     276                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     277                 :            :                                  0xc, 0, 0, 0);
     278         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     279         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     280         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     281         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     282                 :            : 
     283                 :            :         /* Test Case: Host C acquires the reservation, all registrants type */
     284                 :          6 :         task.status = 0;
     285                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
     286                 :            :                                  0xc, 0, 0, 0);
     287         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     288         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     289         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen + 1);
     290                 :            : 
     291                 :          6 :         ut_deinit_reservation_test();
     292                 :          6 : }
     293                 :            : 
     294                 :            : static void
     295                 :          6 : test_reservation_preempt_non_all_regs(void)
     296                 :            : {
     297                 :            :         struct spdk_scsi_pr_registrant *reg;
     298                 :          6 :         struct spdk_scsi_task task = {0};
     299                 :            :         uint32_t gen;
     300                 :            :         int rc;
     301                 :            : 
     302                 :          6 :         task.lun = &g_lun;
     303                 :          6 :         task.target_port = &g_t_port_0;
     304                 :            : 
     305                 :          6 :         ut_init_reservation_test();
     306                 :          6 :         test_build_registrants();
     307                 :            : 
     308                 :          6 :         task.initiator_port = &g_i_port_a;
     309                 :          6 :         task.status = 0;
     310                 :          6 :         gen = g_lun.pr_generation;
     311                 :            :         /* Host A acquires the reservation */
     312                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     313                 :            :                                  0xa, 0, 0, 0);
     314         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     315         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     316         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     317         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     318                 :            : 
     319                 :            :         /* Test Case: Host B preempts Host A, Check condition is expected
     320                 :            :          * for zeroed service action reservation key */
     321                 :          6 :         task.initiator_port = &g_i_port_b;
     322                 :          6 :         task.status = 0;
     323                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     324                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     325                 :            :                                  0xb, 0);
     326         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     327         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     328                 :            : 
     329                 :            :         /* Test Case: Host B preempts Host A, Host A is unregistered */
     330                 :          6 :         task.status = 0;
     331                 :          6 :         gen = g_lun.pr_generation;
     332                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     333                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     334                 :            :                                  0xb, 0xa);
     335         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     336         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     337         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
     338         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     339                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     340         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     341                 :            : 
     342                 :            :         /* Test Case: Host B preempts itself */
     343                 :          6 :         task.status = 0;
     344                 :          6 :         gen = g_lun.pr_generation;
     345                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     346                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     347                 :            :                                  0xb, 0xb);
     348         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     349         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     350         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
     351         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     352                 :            : 
     353                 :            :         /* Test Case: Host B preempts itself and remove registrants */
     354                 :          6 :         task.status = 0;
     355                 :          6 :         gen = g_lun.pr_generation;
     356                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     357                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE,
     358                 :            :                                  0xb, 0xc);
     359         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     360         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE);
     361         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xb);
     362                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
     363         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     364         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     365                 :            : 
     366                 :          6 :         ut_deinit_reservation_test();
     367                 :          6 : }
     368                 :            : 
     369                 :            : static void
     370                 :          6 : test_reservation_preempt_all_regs(void)
     371                 :            : {
     372                 :            :         struct spdk_scsi_pr_registrant *reg;
     373                 :          6 :         struct spdk_scsi_task task = {0};
     374                 :            :         uint32_t gen;
     375                 :            :         int rc;
     376                 :            : 
     377                 :          6 :         task.lun = &g_lun;
     378                 :          6 :         task.target_port = &g_t_port_0;
     379                 :            : 
     380                 :          6 :         ut_init_reservation_test();
     381                 :          6 :         test_build_registrants();
     382                 :            : 
     383                 :            :         /* Test Case: No reservation yet, Host B removes Host C's registrant */
     384                 :          6 :         task.initiator_port = &g_i_port_b;
     385                 :          6 :         task.status = 0;
     386                 :          6 :         gen = g_lun.pr_generation;
     387                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     388                 :            :                                  SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     389                 :            :                                  0xb, 0xc);
     390         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     391                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_c, &g_t_port_0);
     392         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     393         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     394                 :            : 
     395                 :          6 :         task.initiator_port = &g_i_port_a;
     396                 :          6 :         task.status = 0;
     397                 :          6 :         gen = g_lun.pr_generation;
     398                 :            :         /* Host A acquires the reservation */
     399                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS,
     400                 :            :                                  0xa, 0, 0, 0);
     401         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     402         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS);
     403         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation == gen);
     404                 :            : 
     405                 :            :         /* Test Case: Host B removes Host A's registrant and preempt */
     406                 :          6 :         task.initiator_port = &g_i_port_b;
     407                 :          6 :         task.status = 0;
     408                 :          6 :         gen = g_lun.pr_generation;
     409                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     410                 :            :                                  SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS,
     411                 :            :                                  0xb, 0x0);
     412         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     413                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_a, &g_t_port_0);
     414         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     415         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS);
     416         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.pr_generation > gen);
     417                 :            : 
     418                 :          6 :         ut_deinit_reservation_test();
     419                 :          6 : }
     420                 :            : 
     421                 :            : static void
     422                 :          6 : test_reservation_cmds_conflict(void)
     423                 :            : {
     424                 :            :         struct spdk_scsi_pr_registrant *reg;
     425                 :          6 :         struct spdk_scsi_task task = {0};
     426                 :          5 :         uint8_t cdb[32];
     427                 :            :         int rc;
     428                 :            : 
     429                 :          6 :         task.lun = &g_lun;
     430                 :          6 :         task.target_port = &g_t_port_0;
     431                 :          6 :         task.cdb = cdb;
     432                 :            : 
     433                 :          6 :         ut_init_reservation_test();
     434                 :          6 :         test_build_registrants();
     435                 :            : 
     436                 :            :         /* Host A acquires the reservation */
     437                 :          6 :         task.initiator_port = &g_i_port_a;
     438                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     439                 :            :                                  0xa, 0, 0, 0);
     440         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     441         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     442         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     443                 :            : 
     444                 :            :         /* Remove Host B registrant */
     445                 :          6 :         task.initiator_port = &g_i_port_b;
     446                 :          6 :         task.status = 0;
     447                 :          6 :         rc = scsi_pr_out_register(&task, SPDK_SCSI_PR_OUT_REGISTER,
     448                 :            :                                   0xb, 0, 0, 0, 0);
     449         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     450                 :          6 :         reg = scsi_pr_get_registrant(&g_lun, &g_i_port_b, &g_t_port_0);
     451         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(reg == NULL);
     452                 :            : 
     453                 :            :         /* Test Case: Host B sends Read/Write commands,
     454                 :            :          * reservation conflict is expected.
     455                 :            :          */
     456                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     457                 :          6 :         task.status = 0;
     458                 :          6 :         rc = scsi_pr_check(&task);
     459         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     460                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_10;
     461                 :          6 :         task.status = 0;
     462                 :          6 :         rc = scsi_pr_check(&task);
     463         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     464         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     465                 :            : 
     466                 :            :         /* Test Case: Host C sends Read/Write commands */
     467                 :          6 :         task.initiator_port = &g_i_port_c;
     468                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     469                 :          6 :         task.status = 0;
     470                 :          6 :         rc = scsi_pr_check(&task);
     471         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     472                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_10;
     473                 :          6 :         task.status = 0;
     474                 :          6 :         rc = scsi_pr_check(&task);
     475         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     476                 :            : 
     477                 :            :         /* Host A preempts itself with SPDK_SCSI_PR_EXCLUSIVE_ACCESS */
     478                 :          6 :         task.initiator_port = &g_i_port_a;
     479                 :          6 :         rc = scsi_pr_out_preempt(&task, SPDK_SCSI_PR_OUT_PREEMPT,
     480                 :            :                                  SPDK_SCSI_PR_EXCLUSIVE_ACCESS,
     481                 :            :                                  0xa, 0xa);
     482         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     483         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_EXCLUSIVE_ACCESS);
     484         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     485                 :            : 
     486                 :            :         /* Test Case: Host C sends Read/Write commands */
     487                 :          6 :         task.initiator_port = &g_i_port_c;
     488                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     489                 :          6 :         task.status = 0;
     490                 :          6 :         rc = scsi_pr_check(&task);
     491         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     492         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     493                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_10;
     494                 :          6 :         task.status = 0;
     495                 :          6 :         rc = scsi_pr_check(&task);
     496         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     497         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     498                 :            : 
     499                 :            :         /* Test Case: Host B sends Read/Write commands */
     500                 :          6 :         task.initiator_port = &g_i_port_b;
     501                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     502                 :          6 :         task.status = 0;
     503                 :          6 :         rc = scsi_pr_check(&task);
     504         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     505         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     506                 :          6 :         task.cdb[0] = SPDK_SBC_WRITE_10;
     507                 :          6 :         task.status = 0;
     508                 :          6 :         rc = scsi_pr_check(&task);
     509         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     510         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     511                 :            : 
     512                 :          6 :         ut_deinit_reservation_test();
     513                 :          6 : }
     514                 :            : 
     515                 :            : static void
     516                 :          6 : test_scsi2_reserve_release(void)
     517                 :            : {
     518                 :          6 :         struct spdk_scsi_task task = {0};
     519                 :          6 :         uint8_t cdb[32] = {};
     520                 :            :         int rc;
     521                 :            : 
     522                 :          6 :         task.lun = &g_lun;
     523                 :          6 :         task.target_port = &g_t_port_0;
     524                 :          6 :         task.cdb = cdb;
     525                 :            : 
     526                 :          6 :         ut_init_reservation_test();
     527                 :            : 
     528                 :            :         /* Test Case: SPC2 RESERVE from Host A */
     529                 :          6 :         task.initiator_port = &g_i_port_a;
     530                 :          6 :         task.cdb[0] = SPDK_SPC2_RESERVE_10;
     531                 :          6 :         rc = scsi2_reserve(&task, task.cdb);
     532         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     533         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
     534         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == SCSI_SPC2_RESERVE);
     535                 :            : 
     536                 :            :         /* Test Case: READ command from Host B */
     537                 :          6 :         task.initiator_port = &g_i_port_b;
     538                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     539                 :          6 :         task.status = 0;
     540                 :          6 :         rc = scsi2_reserve_check(&task);
     541         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc < 0);
     542         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(task.status == SPDK_SCSI_STATUS_RESERVATION_CONFLICT);
     543                 :            : 
     544                 :            :         /* Test Case: SPDK_SPC2_RELEASE10 command from Host B */
     545                 :          6 :         task.initiator_port = &g_i_port_b;
     546                 :          6 :         task.cdb[0] = SPDK_SPC2_RELEASE_10;
     547                 :          6 :         task.status = 0;
     548                 :          6 :         rc = scsi2_reserve_check(&task);
     549         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     550                 :            : 
     551                 :          6 :         rc = scsi2_release(&task);
     552         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     553         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder == NULL);
     554         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == 0);
     555                 :            : 
     556                 :            :         /* Test Case: SPC2 RESERVE from Host B */
     557                 :          6 :         task.initiator_port = &g_i_port_b;
     558                 :          6 :         task.cdb[0] = SPDK_SPC2_RESERVE_10;
     559                 :          6 :         rc = scsi2_reserve(&task, task.cdb);
     560         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     561         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
     562         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == SCSI_SPC2_RESERVE);
     563                 :            : 
     564                 :            :         /* Test Case: READ command from Host B */
     565                 :          6 :         task.initiator_port = &g_i_port_b;
     566                 :          6 :         task.cdb[0] = SPDK_SBC_READ_10;
     567                 :          6 :         rc = scsi2_reserve_check(&task);
     568         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     569                 :            : 
     570                 :            :         /* Test Case: SPDK_SPC2_RELEASE10 command from Host A */
     571                 :          6 :         task.initiator_port = &g_i_port_a;
     572                 :          6 :         task.cdb[0] = SPDK_SPC2_RELEASE_10;
     573                 :            : 
     574                 :          6 :         rc = scsi2_release(&task);
     575         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     576         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder == NULL);
     577         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.flags == 0);
     578                 :            : 
     579                 :          6 :         ut_deinit_reservation_test();
     580                 :          6 : }
     581                 :            : 
     582                 :            : static void
     583                 :          6 : test_pr_with_scsi2_reserve_release(void)
     584                 :            : {
     585                 :          6 :         struct spdk_scsi_task task = {0};
     586                 :          6 :         uint8_t cdb[32] = {};
     587                 :            :         int rc;
     588                 :            : 
     589                 :          6 :         task.lun = &g_lun;
     590                 :          6 :         task.target_port = &g_t_port_0;
     591                 :          6 :         task.cdb = cdb;
     592                 :            : 
     593                 :          6 :         ut_init_reservation_test();
     594                 :          6 :         test_build_registrants();
     595                 :            : 
     596                 :          6 :         task.initiator_port = &g_i_port_a;
     597                 :          6 :         task.status = 0;
     598                 :            :         /* Test Case: Host A acquires the reservation */
     599                 :          6 :         rc = scsi_pr_out_reserve(&task, SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY,
     600                 :            :                                  0xa, 0, 0, 0);
     601         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     602         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     603         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.crkey == 0xa);
     604                 :            : 
     605                 :            :         /* Test Case: SPDK_SPC2_RESERVE_10 command from Host B */
     606                 :          6 :         task.initiator_port = &g_i_port_b;
     607                 :          6 :         task.cdb[0] = SPDK_SPC2_RESERVE_10;
     608                 :            :         /* SPC2 RESERVE/RELEASE will pass to scsi2_reserve/release */
     609                 :          6 :         rc = scsi_pr_check(&task);
     610         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     611                 :            : 
     612                 :            :         /* do nothing with PR but have good status */
     613                 :          6 :         rc = scsi2_reserve(&task, task.cdb);
     614         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     615         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
     616         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     617                 :            : 
     618                 :          6 :         rc = scsi2_release(&task);
     619         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     620         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.holder != NULL);
     621         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(g_lun.reservation.rtype == SPDK_SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY);
     622                 :            : 
     623                 :          6 :         ut_deinit_reservation_test();
     624                 :          6 : }
     625                 :            : 
     626                 :            : int
     627                 :          6 : main(int argc, char **argv)
     628                 :            : {
     629                 :          6 :         CU_pSuite       suite = NULL;
     630                 :            :         unsigned int    num_failures;
     631                 :            : 
     632                 :          6 :         CU_initialize_registry();
     633                 :            : 
     634                 :          6 :         suite = CU_add_suite("reservation_suite", NULL, NULL);
     635                 :          6 :         CU_ADD_TEST(suite, test_reservation_register);
     636                 :          6 :         CU_ADD_TEST(suite, test_reservation_reserve);
     637                 :          6 :         CU_ADD_TEST(suite, test_reservation_preempt_non_all_regs);
     638                 :          6 :         CU_ADD_TEST(suite, test_reservation_preempt_all_regs);
     639                 :          6 :         CU_ADD_TEST(suite, test_reservation_cmds_conflict);
     640                 :          6 :         CU_ADD_TEST(suite, test_scsi2_reserve_release);
     641                 :          6 :         CU_ADD_TEST(suite, test_pr_with_scsi2_reserve_release);
     642                 :            : 
     643                 :          6 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     644                 :          6 :         CU_cleanup_registry();
     645                 :          6 :         return num_failures;
     646                 :            : 
     647                 :            : }

Generated by: LCOV version 1.14