Print this page
NEX-4433 Deadlock among txg_wait_synced(), sbd_pgr_remove_it_handle(), and ppt_sess_lookup_create() after HA failover
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
NEX-3111 Comstar does not pass cstyle and hdrchk
        Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
        Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
        Reviewed by: Tony Nguyen <tony.nguyen@nexenta.com>
SUP-765 When a Windows Clustered Shared Volume is placed on a pool under Nexenta HA Cluster control the clustered shared disk looses its PGR3 reservation to the presented zvol.
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Tony Nguyen <tony.nguyen@nexenta.com>
Reviewed by: Josef Sipek <josef.sipek@nexenta.com>
Re #6790 backspace should perform delete on console
VAAI (XXX ATS support for COMSTAR, YYY Block-copy support for COMSTAR)


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.


  23  */
  24 
  25 #include <sys/atomic.h>
  26 #include <sys/conf.h>
  27 #include <sys/byteorder.h>
  28 #include <sys/scsi/scsi_types.h>
  29 #include <sys/scsi/generic/persist.h>
  30 
  31 #include <sys/lpif.h>
  32 #include <sys/stmf.h>
  33 #include <sys/stmf_ioctl.h>
  34 #include <sys/portif.h>
  35 #include <sys/stmf_sbd_ioctl.h>
  36 
  37 #include "stmf_sbd.h"
  38 #include "sbd_impl.h"
  39 
  40 #define MAX_PGR_PARAM_LIST_LENGTH       (256 * 1024)
  41 
  42 int  sbd_pgr_reservation_conflict(scsi_task_t *);
  43 void sbd_pgr_reset(sbd_lu_t *);
  44 void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
  45 void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
  46 void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *);
  47 void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
  48 void sbd_pgr_keylist_dealloc(sbd_lu_t *);
  49 char *sbd_get_devid_string(sbd_lu_t *);
  50 
  51 sbd_status_t sbd_pgr_meta_init(sbd_lu_t *);
  52 sbd_status_t sbd_pgr_meta_load(sbd_lu_t *);
  53 sbd_status_t sbd_pgr_meta_write(sbd_lu_t *);
  54 static void sbd_swap_pgr_info(sbd_pgr_info_t *);
  55 static void sbd_swap_pgrkey_info(sbd_pgr_key_info_t *);
  56 static void sbd_pgr_key_free(sbd_pgr_key_t *);
  57 static void sbd_pgr_remove_key(sbd_lu_t *, sbd_pgr_key_t *);
  58 static uint32_t sbd_pgr_remove_keys(sbd_lu_t *, sbd_it_data_t *,
  59         sbd_pgr_key_t *, uint64_t, boolean_t);
  60 static boolean_t sbd_pgr_key_compare(sbd_pgr_key_t *, scsi_devid_desc_t *,
  61         stmf_remote_port_t *);
  62 static sbd_pgr_key_t *sbd_pgr_key_alloc(scsi_devid_desc_t *,


  65 static void sbd_pgr_set_pgr_check_flag(sbd_lu_t *, boolean_t);
  66 static void sbd_pgr_set_ua_conditions(sbd_lu_t *, sbd_it_data_t *, uint8_t);
  67 static void sbd_pgr_in_read_keys(scsi_task_t *, stmf_data_buf_t *);
  68 static void sbd_pgr_in_report_capabilities(scsi_task_t *, stmf_data_buf_t *);
  69 static void sbd_pgr_in_read_reservation(scsi_task_t *, stmf_data_buf_t *);
  70 static void sbd_pgr_in_read_full_status(scsi_task_t *, stmf_data_buf_t *);
  71 static void sbd_pgr_out_register(scsi_task_t *, stmf_data_buf_t *);
  72 static void sbd_pgr_out_reserve(scsi_task_t *);
  73 static void sbd_pgr_out_release(scsi_task_t *);
  74 static void sbd_pgr_out_clear(scsi_task_t *);
  75 static void sbd_pgr_out_preempt(scsi_task_t *, stmf_data_buf_t *);
  76 static void sbd_pgr_out_register_and_move(scsi_task_t *, stmf_data_buf_t *);
  77 
  78 static sbd_pgr_key_t *sbd_pgr_do_register(sbd_lu_t *, sbd_it_data_t *,
  79         scsi_devid_desc_t *, stmf_remote_port_t *, uint8_t, uint64_t);
  80 static void sbd_pgr_do_unregister(sbd_lu_t *, sbd_it_data_t *, sbd_pgr_key_t *);
  81 static void sbd_pgr_do_release(sbd_lu_t *, sbd_it_data_t *, uint8_t);
  82 static void sbd_pgr_do_reserve(sbd_pgr_t *, sbd_pgr_key_t *, sbd_it_data_t *it,
  83         stmf_scsi_session_t *, scsi_cdb_prout_t *);
  84 

  85 extern sbd_status_t sbd_write_meta_section(sbd_lu_t *, sm_section_hdr_t *);
  86 extern sbd_status_t sbd_read_meta_section(sbd_lu_t *, sm_section_hdr_t **,
  87         uint16_t);
  88 extern void sbd_swap_section_hdr(sm_section_hdr_t *);
  89 extern void sbd_handle_short_write_transfers(scsi_task_t *task,
  90         stmf_data_buf_t *dbuf, uint32_t cdb_xfer_size);
  91 extern void sbd_handle_short_read_transfers(scsi_task_t *task,
  92         stmf_data_buf_t *dbuf, uint8_t *p, uint32_t cdb_xfer_size,
  93         uint32_t cmd_xfer_size);
  94 extern uint16_t stmf_scsilib_get_lport_rtid(scsi_devid_desc_t *devid);
  95 extern scsi_devid_desc_t *stmf_scsilib_get_devid_desc(uint16_t rtpid);
  96 extern char sbd_ctoi(char c);
  97 
  98 /*
  99  *
 100  *
 101  *   +-----------+
 102  *   |           |sl_it_list
 103  *   |           |---------------------------------------+
 104  *   |           |                                       |


 278 
 279 sbd_status_t
 280 sbd_pgr_meta_init(sbd_lu_t *slu)
 281 {
 282         sbd_pgr_info_t  *spi = NULL;
 283         uint32_t        sz;
 284         sbd_status_t    ret;
 285 
 286         sz = sizeof (sbd_pgr_info_t);
 287         spi = (sbd_pgr_info_t *)kmem_zalloc(sz, KM_SLEEP);
 288         spi->pgr_data_order = SMS_DATA_ORDER;
 289         spi->pgr_sms_header.sms_size = sz;
 290         spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
 291         spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
 292 
 293         ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
 294         kmem_free(spi, sz);
 295         return (ret);
 296 }
 297 
















 298 sbd_status_t
 299 sbd_pgr_meta_load(sbd_lu_t *slu)
 300 {
 301         sbd_pgr_t               *pgr = slu->sl_pgr;
 302         sbd_pgr_info_t          *spi = NULL;
 303         sbd_pgr_key_t           *key, *last_key = NULL;
 304         sbd_pgr_key_info_t      *spi_key;
 305         sbd_status_t            ret = SBD_SUCCESS;
 306         scsi_devid_desc_t       *lpt;
 307         uint8_t                 *ptr, *keyoffset,  *endoffset;
 308         uint32_t                i, sz;
 309 
 310         ret = sbd_read_meta_section(slu, (sm_section_hdr_t **)&spi,
 311             SMS_ID_PGR_INFO);
 312         if (ret != SBD_SUCCESS) {
 313                 /* No PGR section found, means volume made before PGR support */
 314                 if (ret == SBD_NOT_FOUND) {
 315                         /* So just create a default PGR section */
 316                         ret = sbd_pgr_meta_init(slu);
 317                 }
 318                 return (ret);
 319         }
 320 
 321         if (spi->pgr_data_order != SMS_DATA_ORDER) {
 322                 sbd_swap_pgr_info(spi);
 323         }
 324 
 325         pgr->pgr_flags = spi->pgr_flags;
 326         if (pgr->pgr_flags & SBD_PGR_APTPL) {





 327                 pgr->pgr_rsv_type = spi->pgr_rsv_type;
 328                 pgr->pgr_rsv_scope = spi->pgr_rsv_scope;
 329         } else {
 330                 PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
 331         }
 332 
 333         PGR_CLEAR_FLAG(slu->sl_pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
 334 
 335         endoffset       = (uint8_t *)spi;
 336         endoffset       += spi->pgr_sms_header.sms_size;
 337         keyoffset       = (uint8_t *)(spi + 1);
 338         for (i = 1; i <= spi->pgr_numkeys; i++) {
 339 
 340                 spi_key = (sbd_pgr_key_info_t *)keyoffset;
 341                 if (spi->pgr_data_order != SMS_DATA_ORDER) {
 342                         sbd_swap_pgrkey_info(spi_key);
 343                 }
 344 
 345                 /* Calculate the size and next offset */
 346                 sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (sbd_pgr_key_info_t) - 1 +


 396                 key->pgr_key_flags   = spi_key->pgr_key_flags;
 397                 key->pgr_key_prev    = last_key;
 398 
 399                 if (last_key) {
 400                         last_key->pgr_key_next = key;
 401                 } else {
 402                         pgr->pgr_keylist = key;
 403                 }
 404                 last_key = key;
 405 
 406                 if ((pgr->pgr_flags & SBD_PGR_RSVD_ONE) &&
 407                     (i == spi->pgr_rsvholder_indx)) {
 408                         pgr->pgr_rsvholder = key;
 409                 }
 410         }
 411 
 412         kmem_free(spi, spi->pgr_sms_header.sms_size);
 413         return (ret);
 414 
 415 sbd_pgr_meta_load_failed:

 416         {
 417         char *lun_name = sbd_get_devid_string(slu);
 418         sbd_pgr_keylist_dealloc(slu);
 419         kmem_free(spi, spi->pgr_sms_header.sms_size);
 420         cmn_err(CE_WARN, "sbd_pgr_meta_load: Failed to load PGR meta data "
 421             "for lun %s.", lun_name);
 422         kmem_free(lun_name, strlen(lun_name) + 1);
 423         return (ret);
 424         }
 425 }
 426 
 427 sbd_status_t
 428 sbd_pgr_meta_write(sbd_lu_t *slu)
 429 {
 430         sbd_pgr_key_t           *key;
 431         sbd_pgr_info_t          *spi;
 432         sbd_pgr_key_info_t      *spi_key;
 433         sbd_pgr_t               *pgr = slu->sl_pgr;
 434         sbd_status_t            ret = SBD_SUCCESS;
 435         uint32_t                sz, totalsz;
 436 
 437         /* Calculate total pgr meta section size needed */
 438         sz = sizeof (sbd_pgr_info_t);
 439         if (pgr->pgr_flags & SBD_PGR_APTPL) {
 440                 key = pgr->pgr_keylist;
 441                 while (key != NULL) {
 442                         sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
 443                             sizeof (sbd_pgr_key_info_t) - 1 +
 444                             key->pgr_key_lpt_len + key->pgr_key_rpt_len);
 445                         key = key->pgr_key_next;
 446                 }
 447         }
 448         totalsz = sz;
 449 
 450         spi = (sbd_pgr_info_t *)kmem_zalloc(totalsz, KM_SLEEP);
 451         spi->pgr_flags               = pgr->pgr_flags;
 452         spi->pgr_rsv_type    = pgr->pgr_rsv_type;
 453         spi->pgr_rsv_scope   = pgr->pgr_rsv_scope;
 454         spi->pgr_data_order  = SMS_DATA_ORDER;
 455         spi->pgr_numkeys     = 0;
 456 
 457         spi->pgr_sms_header.sms_size = totalsz;
 458         spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
 459         spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
 460 
 461         if (pgr->pgr_flags & SBD_PGR_APTPL) {
 462                 uint8_t *ptr;
 463                 key = pgr->pgr_keylist;
 464                 sz = sizeof (sbd_pgr_info_t);
 465                 while (key != NULL) {
 466                         spi_key = (sbd_pgr_key_info_t *)((uint8_t *)spi + sz);
 467                         spi_key->pgr_key = key->pgr_key;
 468                         spi_key->pgr_key_flags = key->pgr_key_flags;
 469                         spi_key->pgr_key_lpt_len = key->pgr_key_lpt_len;
 470                         spi_key->pgr_key_rpt_len = key->pgr_key_rpt_len;
 471                         ptr = spi_key->pgr_key_it;
 472                         bcopy(key->pgr_key_lpt_id, ptr, key->pgr_key_lpt_len);
 473                         ptr += key->pgr_key_lpt_len;
 474                         bcopy(key->pgr_key_rpt_id, ptr, key->pgr_key_rpt_len);
 475 
 476                         spi->pgr_numkeys++;
 477                         if (key == pgr->pgr_rsvholder) {
 478                                 spi->pgr_rsvholder_indx = spi->pgr_numkeys;
 479                         }
 480 
 481                         sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
 482                             sizeof (sbd_pgr_key_info_t) - 1 +
 483                             key->pgr_key_lpt_len + key->pgr_key_rpt_len);
 484                         key = key->pgr_key_next;
 485                 }
 486         }
 487 
 488         ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);




 489         kmem_free(spi, totalsz);
 490         if (ret != SBD_SUCCESS) {
 491                 sbd_pgr_key_t   *tmp_list;
 492                 tmp_list = pgr->pgr_keylist;
 493                 pgr->pgr_keylist = NULL;
 494                 if (sbd_pgr_meta_load(slu) != SBD_SUCCESS) {
 495                         char *lun_name = sbd_get_devid_string(slu);
 496                         cmn_err(CE_WARN, "sbd_pgr_meta_write: Failed to revert "
 497                             "back to existing PGR state after meta write "
 498                             "failure, may cause PGR inconsistancy for lun %s.",
 499                             lun_name);
 500                         kmem_free(lun_name, strlen(lun_name) + 1);
 501                         pgr->pgr_keylist = tmp_list;
 502                 } else {
 503                         key = pgr->pgr_keylist;
 504                         pgr->pgr_keylist = tmp_list;
 505                         sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
 506                         sbd_pgr_keylist_dealloc(slu);
 507                         pgr->pgr_keylist = key;
 508                 }


 561                 it->pgr_key_ptr = NULL;
 562         }
 563         mutex_exit(&slu->sl_lock);
 564 
 565         while (pgr->pgr_keylist != NULL) {
 566                 key = pgr->pgr_keylist;
 567                 pgr->pgr_keylist = key->pgr_key_next;
 568                 sbd_pgr_key_free(key);
 569         }
 570 }
 571 
 572 /*
 573  * Reset and clear the keys, Can be used in the case of Lun Reset
 574  */
 575 void
 576 sbd_pgr_reset(sbd_lu_t *slu)
 577 {
 578         sbd_pgr_t       *pgr  = slu->sl_pgr;
 579 
 580         rw_enter(&pgr->pgr_lock, RW_WRITER);
 581         if (!(pgr->pgr_flags & SBD_PGR_APTPL)) {

 582                 sbd_pgr_keylist_dealloc(slu);
 583                 pgr->pgr_PRgeneration        = 0;
 584                 pgr->pgr_rsvholder   = NULL;
 585                 pgr->pgr_rsv_type    = 0;
 586                 pgr->pgr_flags               = 0;
 587         }
 588         rw_exit(&pgr->pgr_lock);
 589 }
 590 
 591 static void
 592 sbd_pgr_remove_key(sbd_lu_t *slu, sbd_pgr_key_t *key)
 593 {
 594         sbd_pgr_t *pgr  = slu->sl_pgr;
 595         sbd_it_data_t *it;
 596 
 597         ASSERT(key);
 598 
 599         mutex_enter(&slu->sl_lock);
 600         if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
 601                 for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {


 795                                 }
 796                         }
 797 
 798                 } else {
 799                         key->pgr_key_it = it;
 800                 }
 801 
 802                 mutex_enter(&slu->sl_lock);
 803                 it->pgr_key_ptr = key;
 804                 mutex_exit(&slu->sl_lock);
 805                 rw_exit(&pgr->pgr_lock);
 806                 return;
 807         }
 808         rw_exit(&pgr->pgr_lock);
 809 }
 810 
 811 /*
 812  * Check for any PGR Reservation conflict. return 0 if access allowed
 813  */
 814 int
 815 sbd_pgr_reservation_conflict(scsi_task_t *task)
 816 {
 817         sbd_lu_t        *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
 818         sbd_pgr_t       *pgr = slu->sl_pgr;
 819         sbd_it_data_t   *it  = (sbd_it_data_t *)task->task_lu_itl_handle;
 820 
 821         /* If Registered */
 822         if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS && it->pgr_key_ptr)
 823                         return (0);
 824 
 825         /* If you are registered */
 826         if (pgr->pgr_flags & SBD_PGR_RSVD_ONE) {
 827                 rw_enter(&pgr->pgr_lock, RW_READER);
 828 
 829                 /*
 830                  * Note: it->pgr_key_ptr is protected by sl_lock. Also,
 831                  *    it is expected to change its value only with pgr_lock
 832                  *    held. Hence we are safe to read its value without
 833                  *    grabbing sl_lock. But make sure that the value used is
 834                  *    not from registers by using "volatile" keyword.
 835                  *    Since this funtion is in performance path, we may want
 836                  *    to avoid grabbing sl_lock.
 837                  */


1369                             sizeof (stmf_remote_port_t) * max_tpdnum);
1370                         stmf_scsilib_send_status(task, STATUS_CHECK,
1371                             STMF_SAA_INVALID_FIELD_IN_CDB);
1372                         return;
1373                 }
1374 
1375                 for (i = 0; i < tpdnum; i++) {
1376                         (void) sbd_pgr_do_register(slu, NULL, lpt, &rpt_ary[i],
1377                             keyflag, svc_key);
1378                 }
1379                 kmem_free(rpt_ary, sizeof (stmf_remote_port_t) * max_tpdnum);
1380         }
1381 
1382         rport.rport_tptid = ses->ss_rport->rport_tptid;
1383         rport.rport_tptid_sz = ses->ss_rport->rport_tptid_sz;
1384 
1385         (void) sbd_pgr_do_register(slu, it, lpt, &rport, keyflag, svc_key);
1386 
1387 sbd_pgr_reg_done:
1388 
1389         if (pgr->pgr_flags & SBD_PGR_APTPL || plist->aptpl) {
1390                 if (plist->aptpl)
1391                         PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1392                 else
1393                         PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1394 
1395                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1396                         stmf_scsilib_send_status(task, STATUS_CHECK,
1397                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1398                         return;
1399                 }
1400         }
1401 
1402         pgr->pgr_PRgeneration++;
1403         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1404 }
1405 
1406 static sbd_pgr_key_t *
1407 sbd_pgr_do_register(sbd_lu_t *slu, sbd_it_data_t *it, scsi_devid_desc_t *lpt,
1408                 stmf_remote_port_t *rpt, uint8_t keyflag, uint64_t svc_key)
1409 {


1474                 return;
1475         }
1476 
1477         if (SBD_PGR_RSVD(pgr)) {
1478                 if (PGR_RESERVATION_HOLDER(pgr, key, it)) {
1479                         if (pgr->pgr_rsv_type != pr_out->type ||
1480                             pgr->pgr_rsv_scope != pr_out->scope) {
1481                                 stmf_scsilib_send_status(task,
1482                                     STATUS_RESERVATION_CONFLICT, 0);
1483                                 return;
1484                         }
1485                 } else {
1486                         stmf_scsilib_send_status(task,
1487                             STATUS_RESERVATION_CONFLICT, 0);
1488                         return;
1489 
1490                 }
1491         /* In case there is no reservation exist */
1492         } else {
1493                 sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
1494                 if (pgr->pgr_flags & SBD_PGR_APTPL) {
1495                         if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1496                                 stmf_scsilib_send_status(task, STATUS_CHECK,
1497                                     STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1498                                 return;
1499                         }
1500                 }
1501         }
1502 
1503         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1504 }
1505 
1506 static void
1507 sbd_pgr_do_reserve(sbd_pgr_t *pgr, sbd_pgr_key_t *key, sbd_it_data_t *it,
1508                         stmf_scsi_session_t *ses, scsi_cdb_prout_t *pr_out)
1509 {
1510         scsi_devid_desc_t       *lpt;
1511         uint16_t                lpt_len;
1512 
1513         pgr->pgr_rsv_type = pr_out->type;
1514         pgr->pgr_rsv_scope = pr_out->scope;


1531                         bcopy(lpt, key->pgr_key_lpt_id, lpt_len);
1532                         key->pgr_key_it = it;
1533                 }
1534 
1535                 PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_RSVD_ONE);
1536                 pgr->pgr_rsvholder = key;
1537         }
1538 }
1539 
1540 static void
1541 sbd_pgr_out_release(scsi_task_t *task)
1542 {
1543         sbd_lu_t        *slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
1544         scsi_cdb_prout_t        *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1545         sbd_it_data_t           *it     = task->task_lu_itl_handle;
1546         sbd_pgr_t               *pgr    = slu->sl_pgr;
1547         sbd_pgr_key_t           *key    = it->pgr_key_ptr;
1548 
1549         ASSERT(key);
1550 





1551         if (SBD_PGR_RSVD(pgr)) {
1552                 if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS ||
1553                     pgr->pgr_rsvholder == key) {
1554                         if (pgr->pgr_rsv_type != pr_out->type ||
1555                             pgr->pgr_rsv_scope != pr_out->scope) {
1556                                 stmf_scsilib_send_status(task, STATUS_CHECK,
1557                                     STMF_SAA_INVALID_RELEASE_OF_PR);
1558                                 return;
1559                         }
1560                         sbd_pgr_do_release(slu, it,
1561                             SBD_UA_RESERVATIONS_RELEASED);



















1562                 }
1563         }


1564         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1565 }
1566 
1567 static void
1568 sbd_pgr_do_release(sbd_lu_t *slu, sbd_it_data_t *it, uint8_t ua_condition)
1569 {
1570 
1571         sbd_pgr_t *pgr    =  slu->sl_pgr;
1572 
1573         /* Reset pgr_flags */
1574         PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
1575         pgr->pgr_rsvholder = NULL;
1576 
1577         /* set unit attention condition if necessary */
1578         if (pgr->pgr_rsv_type != PGR_TYPE_WR_EX &&
1579             pgr->pgr_rsv_type != PGR_TYPE_EX_AC) {
1580                 sbd_pgr_set_ua_conditions(slu, it, ua_condition);
1581         }
1582         pgr->pgr_rsv_type = 0;
1583 }


1585 static void
1586 sbd_pgr_out_clear(scsi_task_t *task)
1587 {
1588         sbd_lu_t        *slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
1589         sbd_it_data_t           *it     = task->task_lu_itl_handle;
1590         sbd_pgr_t               *pgr    = slu->sl_pgr;
1591 
1592         ASSERT(it->pgr_key_ptr);
1593 
1594         PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
1595         pgr->pgr_rsvholder = NULL;
1596         pgr->pgr_rsv_type = 0;
1597         mutex_enter(&slu->sl_lock);
1598         /* Remove all pointers from IT to pgr keys */
1599         for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
1600                 it->pgr_key_ptr = NULL;
1601         }
1602         mutex_exit(&slu->sl_lock);
1603         sbd_pgr_keylist_dealloc(slu);
1604         sbd_pgr_set_ua_conditions(slu, it, SBD_UA_RESERVATIONS_PREEMPTED);
1605         if (pgr->pgr_flags & SBD_PGR_APTPL) {
1606                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1607                         stmf_scsilib_send_status(task, STATUS_CHECK,
1608                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1609                         return;
1610                 }
1611         }
1612         pgr->pgr_PRgeneration++;
1613         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1614 }
1615 
1616 static void
1617 sbd_pgr_out_preempt(scsi_task_t *task, stmf_data_buf_t *dbuf)
1618 {
1619         sbd_lu_t        *slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
1620         stmf_scsi_session_t     *ses    = task->task_session;
1621         scsi_cdb_prout_t        *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1622         sbd_it_data_t           *it     = task->task_lu_itl_handle;
1623         sbd_pgr_t               *pgr    = slu->sl_pgr;
1624         sbd_pgr_key_t           *key    = it->pgr_key_ptr;
1625         scsi_prout_plist_t      *plist;


1700                         if (!(PGR_VALID_SCOPE(pr_out->scope) &&
1701                             PGR_VALID_TYPE(pr_out->type))) {
1702                                 stmf_scsilib_send_status(task, STATUS_CHECK,
1703                                     STMF_SAA_INVALID_FIELD_IN_CDB);
1704                                 return;
1705                         }
1706                         sbd_pgr_do_release(slu, it,
1707                             SBD_UA_REGISTRATIONS_PREEMPTED);
1708                         (void) sbd_pgr_remove_keys(slu, it, key, 0, B_FALSE);
1709                         sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
1710                 } else {
1711                         if (sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE)
1712                             == 0) {
1713                                 stmf_scsilib_send_status(task,
1714                                     STATUS_RESERVATION_CONFLICT, 0);
1715                                 return;
1716                         }
1717                 }
1718         }
1719 
1720         if (pgr->pgr_flags & SBD_PGR_APTPL) {
1721                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1722                         stmf_scsilib_send_status(task, STATUS_CHECK,
1723                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1724                         return;
1725                 }
1726         }
1727 
1728         pgr->pgr_PRgeneration++;
1729 
1730         if (pr_out->action == PR_OUT_PREEMPT_ABORT) {
1731                 stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
1732                     (void *)slu->sl_lu);
1733         }
1734         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1735 }
1736 
1737 static void
1738 sbd_pgr_out_register_and_move(scsi_task_t *task, stmf_data_buf_t *dbuf)
1739 {
1740         sbd_lu_t        *slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;


1814                             kmem_zalloc(lpt_len, KM_SLEEP);
1815                         bcopy(lpt, newkey->pgr_key_lpt_id, lpt_len);
1816                 }
1817                 /* No IT nexus information, hence set PGR_CHEK flag */
1818                 sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
1819         } else  {
1820                 newkey = sbd_pgr_do_register(slu, NULL, lpt, &rport,
1821                     SBD_PGR_KEY_TPT_ID_FLAG, svc_key);
1822         }
1823 
1824         kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
1825 
1826         /* Now reserve the key corresponding to the specified IT nexus */
1827         pgr->pgr_rsvholder = newkey;
1828 
1829         if (plist->unreg) {
1830                 sbd_pgr_do_unregister(slu, it, key);
1831         }
1832 
1833 
1834         /* Write to disk if currenty aptpl is set or given task is setting it */
1835         if (pgr->pgr_flags & SBD_PGR_APTPL || plist->aptpl) {
1836                 if (plist->aptpl)
1837                         PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1838                 else
1839                         PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1840 
1841                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1842                         stmf_scsilib_send_status(task, STATUS_CHECK,
1843                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1844                         return;
1845                 }
1846         }
1847 
1848         pgr->pgr_PRgeneration++;
1849         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1850 }
1851 
1852 void
1853 sbd_pgr_remove_it_handle(sbd_lu_t *sl, sbd_it_data_t *my_it) {
1854         sbd_it_data_t *it;
1855 




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *
  24  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <sys/atomic.h>
  28 #include <sys/conf.h>
  29 #include <sys/byteorder.h>
  30 #include <sys/scsi/scsi_types.h>
  31 #include <sys/scsi/generic/persist.h>
  32 
  33 #include <sys/lpif.h>
  34 #include <sys/stmf.h>
  35 #include <sys/stmf_ioctl.h>
  36 #include <sys/portif.h>
  37 #include <sys/stmf_sbd_ioctl.h>
  38 
  39 #include "stmf_sbd.h"
  40 #include "sbd_impl.h"
  41 
  42 #define MAX_PGR_PARAM_LIST_LENGTH       (256 * 1024)
  43 
  44 int  sbd_pgr_reservation_conflict(scsi_task_t *, struct sbd_lu *sl);
  45 void sbd_pgr_reset(sbd_lu_t *);
  46 void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
  47 void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
  48 void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *);
  49 void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
  50 void sbd_pgr_keylist_dealloc(sbd_lu_t *);
  51 char *sbd_get_devid_string(sbd_lu_t *);
  52 
  53 sbd_status_t sbd_pgr_meta_init(sbd_lu_t *);
  54 sbd_status_t sbd_pgr_meta_load(sbd_lu_t *);
  55 sbd_status_t sbd_pgr_meta_write(sbd_lu_t *);
  56 static void sbd_swap_pgr_info(sbd_pgr_info_t *);
  57 static void sbd_swap_pgrkey_info(sbd_pgr_key_info_t *);
  58 static void sbd_pgr_key_free(sbd_pgr_key_t *);
  59 static void sbd_pgr_remove_key(sbd_lu_t *, sbd_pgr_key_t *);
  60 static uint32_t sbd_pgr_remove_keys(sbd_lu_t *, sbd_it_data_t *,
  61         sbd_pgr_key_t *, uint64_t, boolean_t);
  62 static boolean_t sbd_pgr_key_compare(sbd_pgr_key_t *, scsi_devid_desc_t *,
  63         stmf_remote_port_t *);
  64 static sbd_pgr_key_t *sbd_pgr_key_alloc(scsi_devid_desc_t *,


  67 static void sbd_pgr_set_pgr_check_flag(sbd_lu_t *, boolean_t);
  68 static void sbd_pgr_set_ua_conditions(sbd_lu_t *, sbd_it_data_t *, uint8_t);
  69 static void sbd_pgr_in_read_keys(scsi_task_t *, stmf_data_buf_t *);
  70 static void sbd_pgr_in_report_capabilities(scsi_task_t *, stmf_data_buf_t *);
  71 static void sbd_pgr_in_read_reservation(scsi_task_t *, stmf_data_buf_t *);
  72 static void sbd_pgr_in_read_full_status(scsi_task_t *, stmf_data_buf_t *);
  73 static void sbd_pgr_out_register(scsi_task_t *, stmf_data_buf_t *);
  74 static void sbd_pgr_out_reserve(scsi_task_t *);
  75 static void sbd_pgr_out_release(scsi_task_t *);
  76 static void sbd_pgr_out_clear(scsi_task_t *);
  77 static void sbd_pgr_out_preempt(scsi_task_t *, stmf_data_buf_t *);
  78 static void sbd_pgr_out_register_and_move(scsi_task_t *, stmf_data_buf_t *);
  79 
  80 static sbd_pgr_key_t *sbd_pgr_do_register(sbd_lu_t *, sbd_it_data_t *,
  81         scsi_devid_desc_t *, stmf_remote_port_t *, uint8_t, uint64_t);
  82 static void sbd_pgr_do_unregister(sbd_lu_t *, sbd_it_data_t *, sbd_pgr_key_t *);
  83 static void sbd_pgr_do_release(sbd_lu_t *, sbd_it_data_t *, uint8_t);
  84 static void sbd_pgr_do_reserve(sbd_pgr_t *, sbd_pgr_key_t *, sbd_it_data_t *it,
  85         stmf_scsi_session_t *, scsi_cdb_prout_t *);
  86 
  87 static boolean_t sbd_pgr_should_save(sbd_lu_t *);
  88 extern sbd_status_t sbd_write_meta_section(sbd_lu_t *, sm_section_hdr_t *);
  89 extern sbd_status_t sbd_read_meta_section(sbd_lu_t *, sm_section_hdr_t **,
  90         uint16_t);
  91 extern void sbd_swap_section_hdr(sm_section_hdr_t *);
  92 extern void sbd_handle_short_write_transfers(scsi_task_t *task,
  93         stmf_data_buf_t *dbuf, uint32_t cdb_xfer_size);
  94 extern void sbd_handle_short_read_transfers(scsi_task_t *task,
  95         stmf_data_buf_t *dbuf, uint8_t *p, uint32_t cdb_xfer_size,
  96         uint32_t cmd_xfer_size);
  97 extern uint16_t stmf_scsilib_get_lport_rtid(scsi_devid_desc_t *devid);
  98 extern scsi_devid_desc_t *stmf_scsilib_get_devid_desc(uint16_t rtpid);
  99 extern char sbd_ctoi(char c);
 100 
 101 /*
 102  *
 103  *
 104  *   +-----------+
 105  *   |           |sl_it_list
 106  *   |           |---------------------------------------+
 107  *   |           |                                       |


 281 
 282 sbd_status_t
 283 sbd_pgr_meta_init(sbd_lu_t *slu)
 284 {
 285         sbd_pgr_info_t  *spi = NULL;
 286         uint32_t        sz;
 287         sbd_status_t    ret;
 288 
 289         sz = sizeof (sbd_pgr_info_t);
 290         spi = (sbd_pgr_info_t *)kmem_zalloc(sz, KM_SLEEP);
 291         spi->pgr_data_order = SMS_DATA_ORDER;
 292         spi->pgr_sms_header.sms_size = sz;
 293         spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
 294         spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
 295 
 296         ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
 297         kmem_free(spi, sz);
 298         return (ret);
 299 }
 300 
 301 /*
 302  * Evaluate common cases where a PERSISTENT RESERVE OUT CDB handler should call
 303  * sbd_pgr_meta_write().
 304  */
 305 static boolean_t
 306 sbd_pgr_should_save(sbd_lu_t *slu)
 307 {
 308         sbd_pgr_t               *pgr = slu->sl_pgr;
 309 
 310         if (stmf_is_pgr_aptpl_always() == B_TRUE ||
 311             (pgr->pgr_flags & (SBD_PGR_APTPL)))
 312                 return (B_TRUE);
 313         else
 314                 return (B_FALSE);
 315 }
 316 
 317 sbd_status_t
 318 sbd_pgr_meta_load(sbd_lu_t *slu)
 319 {
 320         sbd_pgr_t               *pgr = slu->sl_pgr;
 321         sbd_pgr_info_t          *spi = NULL;
 322         sbd_pgr_key_t           *key, *last_key = NULL;
 323         sbd_pgr_key_info_t      *spi_key;
 324         sbd_status_t            ret = SBD_SUCCESS;
 325         scsi_devid_desc_t       *lpt;
 326         uint8_t                 *ptr, *keyoffset,  *endoffset;
 327         uint32_t                i, sz;
 328 
 329         ret = sbd_read_meta_section(slu, (sm_section_hdr_t **)&spi,
 330             SMS_ID_PGR_INFO);
 331         if (ret != SBD_SUCCESS) {
 332                 /* No PGR section found, means volume made before PGR support */
 333                 if (ret == SBD_NOT_FOUND) {
 334                         /* So just create a default PGR section */
 335                         ret = sbd_pgr_meta_init(slu);
 336                 }
 337                 return (ret);
 338         }
 339 
 340         if (spi->pgr_data_order != SMS_DATA_ORDER) {
 341                 sbd_swap_pgr_info(spi);
 342         }
 343 
 344         pgr->pgr_flags = spi->pgr_flags;
 345         /*
 346          * We reload APTPL reservations when:
 347          *  1. Global override is enabled
 348          *  2. APTPL was explicitly asserted in the PERSISTENT RESERVE OUT CDB
 349          */
 350         if (stmf_is_pgr_aptpl_always() || (pgr->pgr_flags & SBD_PGR_APTPL)) {
 351                 pgr->pgr_rsv_type = spi->pgr_rsv_type;
 352                 pgr->pgr_rsv_scope = spi->pgr_rsv_scope;
 353         } else {
 354                 PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
 355         }
 356 
 357         PGR_CLEAR_FLAG(slu->sl_pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
 358 
 359         endoffset       = (uint8_t *)spi;
 360         endoffset       += spi->pgr_sms_header.sms_size;
 361         keyoffset       = (uint8_t *)(spi + 1);
 362         for (i = 1; i <= spi->pgr_numkeys; i++) {
 363 
 364                 spi_key = (sbd_pgr_key_info_t *)keyoffset;
 365                 if (spi->pgr_data_order != SMS_DATA_ORDER) {
 366                         sbd_swap_pgrkey_info(spi_key);
 367                 }
 368 
 369                 /* Calculate the size and next offset */
 370                 sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (sbd_pgr_key_info_t) - 1 +


 420                 key->pgr_key_flags   = spi_key->pgr_key_flags;
 421                 key->pgr_key_prev    = last_key;
 422 
 423                 if (last_key) {
 424                         last_key->pgr_key_next = key;
 425                 } else {
 426                         pgr->pgr_keylist = key;
 427                 }
 428                 last_key = key;
 429 
 430                 if ((pgr->pgr_flags & SBD_PGR_RSVD_ONE) &&
 431                     (i == spi->pgr_rsvholder_indx)) {
 432                         pgr->pgr_rsvholder = key;
 433                 }
 434         }
 435 
 436         kmem_free(spi, spi->pgr_sms_header.sms_size);
 437         return (ret);
 438 
 439 sbd_pgr_meta_load_failed:
 440         /* CSTYLED */
 441         {
 442         char *lun_name = sbd_get_devid_string(slu);
 443         sbd_pgr_keylist_dealloc(slu);
 444         kmem_free(spi, spi->pgr_sms_header.sms_size);
 445         cmn_err(CE_WARN, "sbd_pgr_meta_load: Failed to load PGR meta data "
 446             "for lun %s.", lun_name);
 447         kmem_free(lun_name, strlen(lun_name) + 1);
 448         return (ret);
 449         }
 450 }
 451 
 452 sbd_status_t
 453 sbd_pgr_meta_write(sbd_lu_t *slu)
 454 {
 455         sbd_pgr_key_t           *key;
 456         sbd_pgr_info_t          *spi;
 457         sbd_pgr_key_info_t      *spi_key;
 458         sbd_pgr_t               *pgr = slu->sl_pgr;
 459         sbd_status_t            ret = SBD_SUCCESS;
 460         uint32_t                sz, totalsz;
 461 
 462         /* Calculate total pgr meta section size needed */
 463         sz = sizeof (sbd_pgr_info_t);
 464         if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) {
 465                 key = pgr->pgr_keylist;
 466                 while (key != NULL) {
 467                         sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
 468                             sizeof (sbd_pgr_key_info_t) - 1 +
 469                             key->pgr_key_lpt_len + key->pgr_key_rpt_len);
 470                         key = key->pgr_key_next;
 471                 }
 472         }
 473         totalsz = sz;
 474 
 475         spi = (sbd_pgr_info_t *)kmem_zalloc(totalsz, KM_SLEEP);
 476         spi->pgr_flags               = pgr->pgr_flags;
 477         spi->pgr_rsv_type    = pgr->pgr_rsv_type;
 478         spi->pgr_rsv_scope   = pgr->pgr_rsv_scope;
 479         spi->pgr_data_order  = SMS_DATA_ORDER;
 480         spi->pgr_numkeys     = 0;
 481 
 482         spi->pgr_sms_header.sms_size = totalsz;
 483         spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
 484         spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
 485 
 486         if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) {
 487                 uint8_t *ptr;
 488                 key = pgr->pgr_keylist;
 489                 sz = sizeof (sbd_pgr_info_t);
 490                 while (key != NULL) {
 491                         spi_key = (sbd_pgr_key_info_t *)((uint8_t *)spi + sz);
 492                         spi_key->pgr_key = key->pgr_key;
 493                         spi_key->pgr_key_flags = key->pgr_key_flags;
 494                         spi_key->pgr_key_lpt_len = key->pgr_key_lpt_len;
 495                         spi_key->pgr_key_rpt_len = key->pgr_key_rpt_len;
 496                         ptr = spi_key->pgr_key_it;
 497                         bcopy(key->pgr_key_lpt_id, ptr, key->pgr_key_lpt_len);
 498                         ptr += key->pgr_key_lpt_len;
 499                         bcopy(key->pgr_key_rpt_id, ptr, key->pgr_key_rpt_len);
 500 
 501                         spi->pgr_numkeys++;
 502                         if (key == pgr->pgr_rsvholder) {
 503                                 spi->pgr_rsvholder_indx = spi->pgr_numkeys;
 504                         }
 505 
 506                         sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
 507                             sizeof (sbd_pgr_key_info_t) - 1 +
 508                             key->pgr_key_lpt_len + key->pgr_key_rpt_len);
 509                         key = key->pgr_key_next;
 510                 }
 511         }
 512         rw_downgrade(&pgr->pgr_lock);
 513         ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
 514         if (!rw_tryupgrade(&pgr->pgr_lock)) {
 515                 rw_exit(&pgr->pgr_lock);
 516                 rw_enter(&pgr->pgr_lock, RW_WRITER);
 517         }
 518         kmem_free(spi, totalsz);
 519         if (ret != SBD_SUCCESS) {
 520                 sbd_pgr_key_t   *tmp_list;
 521                 tmp_list = pgr->pgr_keylist;
 522                 pgr->pgr_keylist = NULL;
 523                 if (sbd_pgr_meta_load(slu) != SBD_SUCCESS) {
 524                         char *lun_name = sbd_get_devid_string(slu);
 525                         cmn_err(CE_WARN, "sbd_pgr_meta_write: Failed to revert "
 526                             "back to existing PGR state after meta write "
 527                             "failure, may cause PGR inconsistancy for lun %s.",
 528                             lun_name);
 529                         kmem_free(lun_name, strlen(lun_name) + 1);
 530                         pgr->pgr_keylist = tmp_list;
 531                 } else {
 532                         key = pgr->pgr_keylist;
 533                         pgr->pgr_keylist = tmp_list;
 534                         sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
 535                         sbd_pgr_keylist_dealloc(slu);
 536                         pgr->pgr_keylist = key;
 537                 }


 590                 it->pgr_key_ptr = NULL;
 591         }
 592         mutex_exit(&slu->sl_lock);
 593 
 594         while (pgr->pgr_keylist != NULL) {
 595                 key = pgr->pgr_keylist;
 596                 pgr->pgr_keylist = key->pgr_key_next;
 597                 sbd_pgr_key_free(key);
 598         }
 599 }
 600 
 601 /*
 602  * Reset and clear the keys, Can be used in the case of Lun Reset
 603  */
 604 void
 605 sbd_pgr_reset(sbd_lu_t *slu)
 606 {
 607         sbd_pgr_t       *pgr  = slu->sl_pgr;
 608 
 609         rw_enter(&pgr->pgr_lock, RW_WRITER);
 610         if (!(pgr->pgr_flags & SBD_PGR_APTPL) &&
 611             stmf_is_pgr_aptpl_always() == B_FALSE) {
 612                 sbd_pgr_keylist_dealloc(slu);
 613                 pgr->pgr_PRgeneration        = 0;
 614                 pgr->pgr_rsvholder   = NULL;
 615                 pgr->pgr_rsv_type    = 0;
 616                 pgr->pgr_flags               = 0;
 617         }
 618         rw_exit(&pgr->pgr_lock);
 619 }
 620 
 621 static void
 622 sbd_pgr_remove_key(sbd_lu_t *slu, sbd_pgr_key_t *key)
 623 {
 624         sbd_pgr_t *pgr  = slu->sl_pgr;
 625         sbd_it_data_t *it;
 626 
 627         ASSERT(key);
 628 
 629         mutex_enter(&slu->sl_lock);
 630         if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
 631                 for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {


 825                                 }
 826                         }
 827 
 828                 } else {
 829                         key->pgr_key_it = it;
 830                 }
 831 
 832                 mutex_enter(&slu->sl_lock);
 833                 it->pgr_key_ptr = key;
 834                 mutex_exit(&slu->sl_lock);
 835                 rw_exit(&pgr->pgr_lock);
 836                 return;
 837         }
 838         rw_exit(&pgr->pgr_lock);
 839 }
 840 
 841 /*
 842  * Check for any PGR Reservation conflict. return 0 if access allowed
 843  */
 844 int
 845 sbd_pgr_reservation_conflict(scsi_task_t *task, sbd_lu_t *slu)
 846 {

 847         sbd_pgr_t       *pgr = slu->sl_pgr;
 848         sbd_it_data_t   *it  = (sbd_it_data_t *)task->task_lu_itl_handle;
 849 
 850         /* If Registered */
 851         if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS && it->pgr_key_ptr)
 852                         return (0);
 853 
 854         /* If you are registered */
 855         if (pgr->pgr_flags & SBD_PGR_RSVD_ONE) {
 856                 rw_enter(&pgr->pgr_lock, RW_READER);
 857 
 858                 /*
 859                  * Note: it->pgr_key_ptr is protected by sl_lock. Also,
 860                  *    it is expected to change its value only with pgr_lock
 861                  *    held. Hence we are safe to read its value without
 862                  *    grabbing sl_lock. But make sure that the value used is
 863                  *    not from registers by using "volatile" keyword.
 864                  *    Since this funtion is in performance path, we may want
 865                  *    to avoid grabbing sl_lock.
 866                  */


1398                             sizeof (stmf_remote_port_t) * max_tpdnum);
1399                         stmf_scsilib_send_status(task, STATUS_CHECK,
1400                             STMF_SAA_INVALID_FIELD_IN_CDB);
1401                         return;
1402                 }
1403 
1404                 for (i = 0; i < tpdnum; i++) {
1405                         (void) sbd_pgr_do_register(slu, NULL, lpt, &rpt_ary[i],
1406                             keyflag, svc_key);
1407                 }
1408                 kmem_free(rpt_ary, sizeof (stmf_remote_port_t) * max_tpdnum);
1409         }
1410 
1411         rport.rport_tptid = ses->ss_rport->rport_tptid;
1412         rport.rport_tptid_sz = ses->ss_rport->rport_tptid_sz;
1413 
1414         (void) sbd_pgr_do_register(slu, it, lpt, &rport, keyflag, svc_key);
1415 
1416 sbd_pgr_reg_done:
1417 
1418         if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) {
1419                 if (plist->aptpl)
1420                         PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1421                 else
1422                         PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1423 
1424                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1425                         stmf_scsilib_send_status(task, STATUS_CHECK,
1426                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1427                         return;
1428                 }
1429         }
1430 
1431         pgr->pgr_PRgeneration++;
1432         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1433 }
1434 
1435 static sbd_pgr_key_t *
1436 sbd_pgr_do_register(sbd_lu_t *slu, sbd_it_data_t *it, scsi_devid_desc_t *lpt,
1437                 stmf_remote_port_t *rpt, uint8_t keyflag, uint64_t svc_key)
1438 {


1503                 return;
1504         }
1505 
1506         if (SBD_PGR_RSVD(pgr)) {
1507                 if (PGR_RESERVATION_HOLDER(pgr, key, it)) {
1508                         if (pgr->pgr_rsv_type != pr_out->type ||
1509                             pgr->pgr_rsv_scope != pr_out->scope) {
1510                                 stmf_scsilib_send_status(task,
1511                                     STATUS_RESERVATION_CONFLICT, 0);
1512                                 return;
1513                         }
1514                 } else {
1515                         stmf_scsilib_send_status(task,
1516                             STATUS_RESERVATION_CONFLICT, 0);
1517                         return;
1518 
1519                 }
1520         /* In case there is no reservation exist */
1521         } else {
1522                 sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
1523                 if (sbd_pgr_should_save(slu) == B_TRUE) {
1524                         if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1525                                 stmf_scsilib_send_status(task, STATUS_CHECK,
1526                                     STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1527                                 return;
1528                         }
1529                 }
1530         }
1531 
1532         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1533 }
1534 
1535 static void
1536 sbd_pgr_do_reserve(sbd_pgr_t *pgr, sbd_pgr_key_t *key, sbd_it_data_t *it,
1537                         stmf_scsi_session_t *ses, scsi_cdb_prout_t *pr_out)
1538 {
1539         scsi_devid_desc_t       *lpt;
1540         uint16_t                lpt_len;
1541 
1542         pgr->pgr_rsv_type = pr_out->type;
1543         pgr->pgr_rsv_scope = pr_out->scope;


1560                         bcopy(lpt, key->pgr_key_lpt_id, lpt_len);
1561                         key->pgr_key_it = it;
1562                 }
1563 
1564                 PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_RSVD_ONE);
1565                 pgr->pgr_rsvholder = key;
1566         }
1567 }
1568 
1569 static void
1570 sbd_pgr_out_release(scsi_task_t *task)
1571 {
1572         sbd_lu_t        *slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
1573         scsi_cdb_prout_t        *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1574         sbd_it_data_t           *it     = task->task_lu_itl_handle;
1575         sbd_pgr_t               *pgr    = slu->sl_pgr;
1576         sbd_pgr_key_t           *key    = it->pgr_key_ptr;
1577 
1578         ASSERT(key);
1579 
1580         /*
1581          * XXX this does not honor APTPL
1582          * (i.e., changes made to a formerly-persistent reservation are not
1583          *  updated here!!!)
1584          */
1585         if (SBD_PGR_RSVD(pgr)) {
1586                 if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS ||
1587                     pgr->pgr_rsvholder == key) {
1588                         if (pgr->pgr_rsv_type != pr_out->type ||
1589                             pgr->pgr_rsv_scope != pr_out->scope) {
1590                                 stmf_scsilib_send_status(task, STATUS_CHECK,
1591                                     STMF_SAA_INVALID_RELEASE_OF_PR);
1592                                 return;
1593                         }
1594                         sbd_pgr_do_release(slu, it,
1595                             SBD_UA_RESERVATIONS_RELEASED);
1596 
1597                         /*
1598                          * XXX T10 SPC-3 5.6.10.2 says nothing about what to
1599                          * do in the event of a failure updating the
1600                          * PGR nvram store for a reservation associated with
1601                          * an APTPL-enabled (see SPC-3 5.6.4.1) I_T
1602                          * registration during a RELEASE service action.
1603                          *
1604                          * Technically, the CDB completed successfully, as per
1605                          * the spec, but at some point we may need to enter
1606                          * a recovery mode on the initiator(s) if we power cycle
1607                          * the target at the wrong instant...
1608                          */
1609                         if (sbd_pgr_should_save(slu) == B_TRUE) {
1610                                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1611                                         stmf_scsilib_send_status(task,
1612                                             STATUS_CHECK, /* CSTYLED */
1613                                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1614                                         return;
1615                                 }
1616                         }
1617                 }
1618         }
1619         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1620 }
1621 
1622 static void
1623 sbd_pgr_do_release(sbd_lu_t *slu, sbd_it_data_t *it, uint8_t ua_condition)
1624 {
1625 
1626         sbd_pgr_t *pgr    =  slu->sl_pgr;
1627 
1628         /* Reset pgr_flags */
1629         PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
1630         pgr->pgr_rsvholder = NULL;
1631 
1632         /* set unit attention condition if necessary */
1633         if (pgr->pgr_rsv_type != PGR_TYPE_WR_EX &&
1634             pgr->pgr_rsv_type != PGR_TYPE_EX_AC) {
1635                 sbd_pgr_set_ua_conditions(slu, it, ua_condition);
1636         }
1637         pgr->pgr_rsv_type = 0;
1638 }


1640 static void
1641 sbd_pgr_out_clear(scsi_task_t *task)
1642 {
1643         sbd_lu_t        *slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
1644         sbd_it_data_t           *it     = task->task_lu_itl_handle;
1645         sbd_pgr_t               *pgr    = slu->sl_pgr;
1646 
1647         ASSERT(it->pgr_key_ptr);
1648 
1649         PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
1650         pgr->pgr_rsvholder = NULL;
1651         pgr->pgr_rsv_type = 0;
1652         mutex_enter(&slu->sl_lock);
1653         /* Remove all pointers from IT to pgr keys */
1654         for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
1655                 it->pgr_key_ptr = NULL;
1656         }
1657         mutex_exit(&slu->sl_lock);
1658         sbd_pgr_keylist_dealloc(slu);
1659         sbd_pgr_set_ua_conditions(slu, it, SBD_UA_RESERVATIONS_PREEMPTED);
1660         if (sbd_pgr_should_save(slu) == B_TRUE) {
1661                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1662                         stmf_scsilib_send_status(task, STATUS_CHECK,
1663                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1664                         return;
1665                 }
1666         }
1667         pgr->pgr_PRgeneration++;
1668         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1669 }
1670 
1671 static void
1672 sbd_pgr_out_preempt(scsi_task_t *task, stmf_data_buf_t *dbuf)
1673 {
1674         sbd_lu_t        *slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
1675         stmf_scsi_session_t     *ses    = task->task_session;
1676         scsi_cdb_prout_t        *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1677         sbd_it_data_t           *it     = task->task_lu_itl_handle;
1678         sbd_pgr_t               *pgr    = slu->sl_pgr;
1679         sbd_pgr_key_t           *key    = it->pgr_key_ptr;
1680         scsi_prout_plist_t      *plist;


1755                         if (!(PGR_VALID_SCOPE(pr_out->scope) &&
1756                             PGR_VALID_TYPE(pr_out->type))) {
1757                                 stmf_scsilib_send_status(task, STATUS_CHECK,
1758                                     STMF_SAA_INVALID_FIELD_IN_CDB);
1759                                 return;
1760                         }
1761                         sbd_pgr_do_release(slu, it,
1762                             SBD_UA_REGISTRATIONS_PREEMPTED);
1763                         (void) sbd_pgr_remove_keys(slu, it, key, 0, B_FALSE);
1764                         sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
1765                 } else {
1766                         if (sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE)
1767                             == 0) {
1768                                 stmf_scsilib_send_status(task,
1769                                     STATUS_RESERVATION_CONFLICT, 0);
1770                                 return;
1771                         }
1772                 }
1773         }
1774 
1775         if (sbd_pgr_should_save(slu) == B_TRUE) {
1776                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1777                         stmf_scsilib_send_status(task, STATUS_CHECK,
1778                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1779                         return;
1780                 }
1781         }
1782 
1783         pgr->pgr_PRgeneration++;
1784 
1785         if (pr_out->action == PR_OUT_PREEMPT_ABORT) {
1786                 stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
1787                     (void *)slu->sl_lu);
1788         }
1789         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1790 }
1791 
1792 static void
1793 sbd_pgr_out_register_and_move(scsi_task_t *task, stmf_data_buf_t *dbuf)
1794 {
1795         sbd_lu_t        *slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;


1869                             kmem_zalloc(lpt_len, KM_SLEEP);
1870                         bcopy(lpt, newkey->pgr_key_lpt_id, lpt_len);
1871                 }
1872                 /* No IT nexus information, hence set PGR_CHEK flag */
1873                 sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
1874         } else  {
1875                 newkey = sbd_pgr_do_register(slu, NULL, lpt, &rport,
1876                     SBD_PGR_KEY_TPT_ID_FLAG, svc_key);
1877         }
1878 
1879         kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
1880 
1881         /* Now reserve the key corresponding to the specified IT nexus */
1882         pgr->pgr_rsvholder = newkey;
1883 
1884         if (plist->unreg) {
1885                 sbd_pgr_do_unregister(slu, it, key);
1886         }
1887 
1888 
1889         /* Write to disk if aptpl is currently set or this task is setting it */
1890         if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) {
1891                 if (plist->aptpl)
1892                         PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1893                 else
1894                         PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1895 
1896                 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1897                         stmf_scsilib_send_status(task, STATUS_CHECK,
1898                             STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1899                         return;
1900                 }
1901         }
1902 
1903         pgr->pgr_PRgeneration++;
1904         stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1905 }
1906 
1907 void
1908 sbd_pgr_remove_it_handle(sbd_lu_t *sl, sbd_it_data_t *my_it) {
1909         sbd_it_data_t *it;
1910