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)

*** 18,27 **** --- 18,29 ---- * * CDDL HEADER END */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ #include <sys/atomic.h> #include <sys/conf.h> #include <sys/byteorder.h>
*** 37,47 **** #include "stmf_sbd.h" #include "sbd_impl.h" #define MAX_PGR_PARAM_LIST_LENGTH (256 * 1024) ! int sbd_pgr_reservation_conflict(scsi_task_t *); void sbd_pgr_reset(sbd_lu_t *); void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *); void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *); void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *); void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *); --- 39,49 ---- #include "stmf_sbd.h" #include "sbd_impl.h" #define MAX_PGR_PARAM_LIST_LENGTH (256 * 1024) ! int sbd_pgr_reservation_conflict(scsi_task_t *, struct sbd_lu *sl); void sbd_pgr_reset(sbd_lu_t *); void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *); void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *); void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *); void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
*** 80,89 **** --- 82,92 ---- static void sbd_pgr_do_unregister(sbd_lu_t *, sbd_it_data_t *, sbd_pgr_key_t *); static void sbd_pgr_do_release(sbd_lu_t *, sbd_it_data_t *, uint8_t); static void sbd_pgr_do_reserve(sbd_pgr_t *, sbd_pgr_key_t *, sbd_it_data_t *it, stmf_scsi_session_t *, scsi_cdb_prout_t *); + static boolean_t sbd_pgr_should_save(sbd_lu_t *); extern sbd_status_t sbd_write_meta_section(sbd_lu_t *, sm_section_hdr_t *); extern sbd_status_t sbd_read_meta_section(sbd_lu_t *, sm_section_hdr_t **, uint16_t); extern void sbd_swap_section_hdr(sm_section_hdr_t *); extern void sbd_handle_short_write_transfers(scsi_task_t *task,
*** 293,302 **** --- 296,321 ---- ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi); kmem_free(spi, sz); return (ret); } + /* + * Evaluate common cases where a PERSISTENT RESERVE OUT CDB handler should call + * sbd_pgr_meta_write(). + */ + static boolean_t + sbd_pgr_should_save(sbd_lu_t *slu) + { + sbd_pgr_t *pgr = slu->sl_pgr; + + if (stmf_is_pgr_aptpl_always() == B_TRUE || + (pgr->pgr_flags & (SBD_PGR_APTPL))) + return (B_TRUE); + else + return (B_FALSE); + } + sbd_status_t sbd_pgr_meta_load(sbd_lu_t *slu) { sbd_pgr_t *pgr = slu->sl_pgr; sbd_pgr_info_t *spi = NULL;
*** 321,331 **** if (spi->pgr_data_order != SMS_DATA_ORDER) { sbd_swap_pgr_info(spi); } pgr->pgr_flags = spi->pgr_flags; ! if (pgr->pgr_flags & SBD_PGR_APTPL) { pgr->pgr_rsv_type = spi->pgr_rsv_type; pgr->pgr_rsv_scope = spi->pgr_rsv_scope; } else { PGR_CLEAR_RSV_FLAG(pgr->pgr_flags); } --- 340,355 ---- if (spi->pgr_data_order != SMS_DATA_ORDER) { sbd_swap_pgr_info(spi); } pgr->pgr_flags = spi->pgr_flags; ! /* ! * We reload APTPL reservations when: ! * 1. Global override is enabled ! * 2. APTPL was explicitly asserted in the PERSISTENT RESERVE OUT CDB ! */ ! if (stmf_is_pgr_aptpl_always() || (pgr->pgr_flags & SBD_PGR_APTPL)) { pgr->pgr_rsv_type = spi->pgr_rsv_type; pgr->pgr_rsv_scope = spi->pgr_rsv_scope; } else { PGR_CLEAR_RSV_FLAG(pgr->pgr_flags); }
*** 411,420 **** --- 435,445 ---- kmem_free(spi, spi->pgr_sms_header.sms_size); return (ret); sbd_pgr_meta_load_failed: + /* CSTYLED */ { char *lun_name = sbd_get_devid_string(slu); sbd_pgr_keylist_dealloc(slu); kmem_free(spi, spi->pgr_sms_header.sms_size); cmn_err(CE_WARN, "sbd_pgr_meta_load: Failed to load PGR meta data "
*** 434,444 **** sbd_status_t ret = SBD_SUCCESS; uint32_t sz, totalsz; /* Calculate total pgr meta section size needed */ sz = sizeof (sbd_pgr_info_t); ! if (pgr->pgr_flags & SBD_PGR_APTPL) { key = pgr->pgr_keylist; while (key != NULL) { sz = ALIGNED_TO_8BYTE_BOUNDARY(sz + sizeof (sbd_pgr_key_info_t) - 1 + key->pgr_key_lpt_len + key->pgr_key_rpt_len); --- 459,469 ---- sbd_status_t ret = SBD_SUCCESS; uint32_t sz, totalsz; /* Calculate total pgr meta section size needed */ sz = sizeof (sbd_pgr_info_t); ! if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) { key = pgr->pgr_keylist; while (key != NULL) { sz = ALIGNED_TO_8BYTE_BOUNDARY(sz + sizeof (sbd_pgr_key_info_t) - 1 + key->pgr_key_lpt_len + key->pgr_key_rpt_len);
*** 456,466 **** spi->pgr_sms_header.sms_size = totalsz; spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO; spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER; ! if (pgr->pgr_flags & SBD_PGR_APTPL) { uint8_t *ptr; key = pgr->pgr_keylist; sz = sizeof (sbd_pgr_info_t); while (key != NULL) { spi_key = (sbd_pgr_key_info_t *)((uint8_t *)spi + sz); --- 481,491 ---- spi->pgr_sms_header.sms_size = totalsz; spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO; spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER; ! if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) { uint8_t *ptr; key = pgr->pgr_keylist; sz = sizeof (sbd_pgr_info_t); while (key != NULL) { spi_key = (sbd_pgr_key_info_t *)((uint8_t *)spi + sz);
*** 482,493 **** sizeof (sbd_pgr_key_info_t) - 1 + key->pgr_key_lpt_len + key->pgr_key_rpt_len); key = key->pgr_key_next; } } ! ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi); kmem_free(spi, totalsz); if (ret != SBD_SUCCESS) { sbd_pgr_key_t *tmp_list; tmp_list = pgr->pgr_keylist; pgr->pgr_keylist = NULL; --- 507,522 ---- sizeof (sbd_pgr_key_info_t) - 1 + key->pgr_key_lpt_len + key->pgr_key_rpt_len); key = key->pgr_key_next; } } ! rw_downgrade(&pgr->pgr_lock); ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi); + if (!rw_tryupgrade(&pgr->pgr_lock)) { + rw_exit(&pgr->pgr_lock); + rw_enter(&pgr->pgr_lock, RW_WRITER); + } kmem_free(spi, totalsz); if (ret != SBD_SUCCESS) { sbd_pgr_key_t *tmp_list; tmp_list = pgr->pgr_keylist; pgr->pgr_keylist = NULL;
*** 576,586 **** sbd_pgr_reset(sbd_lu_t *slu) { sbd_pgr_t *pgr = slu->sl_pgr; rw_enter(&pgr->pgr_lock, RW_WRITER); ! if (!(pgr->pgr_flags & SBD_PGR_APTPL)) { sbd_pgr_keylist_dealloc(slu); pgr->pgr_PRgeneration = 0; pgr->pgr_rsvholder = NULL; pgr->pgr_rsv_type = 0; pgr->pgr_flags = 0; --- 605,616 ---- sbd_pgr_reset(sbd_lu_t *slu) { sbd_pgr_t *pgr = slu->sl_pgr; rw_enter(&pgr->pgr_lock, RW_WRITER); ! if (!(pgr->pgr_flags & SBD_PGR_APTPL) && ! stmf_is_pgr_aptpl_always() == B_FALSE) { sbd_pgr_keylist_dealloc(slu); pgr->pgr_PRgeneration = 0; pgr->pgr_rsvholder = NULL; pgr->pgr_rsv_type = 0; pgr->pgr_flags = 0;
*** 810,822 **** /* * Check for any PGR Reservation conflict. return 0 if access allowed */ int ! sbd_pgr_reservation_conflict(scsi_task_t *task) { - sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private; sbd_pgr_t *pgr = slu->sl_pgr; sbd_it_data_t *it = (sbd_it_data_t *)task->task_lu_itl_handle; /* If Registered */ if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS && it->pgr_key_ptr) --- 840,851 ---- /* * Check for any PGR Reservation conflict. return 0 if access allowed */ int ! sbd_pgr_reservation_conflict(scsi_task_t *task, sbd_lu_t *slu) { sbd_pgr_t *pgr = slu->sl_pgr; sbd_it_data_t *it = (sbd_it_data_t *)task->task_lu_itl_handle; /* If Registered */ if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS && it->pgr_key_ptr)
*** 1384,1394 **** (void) sbd_pgr_do_register(slu, it, lpt, &rport, keyflag, svc_key); sbd_pgr_reg_done: ! if (pgr->pgr_flags & SBD_PGR_APTPL || plist->aptpl) { if (plist->aptpl) PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL); else PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL); --- 1413,1423 ---- (void) sbd_pgr_do_register(slu, it, lpt, &rport, keyflag, svc_key); sbd_pgr_reg_done: ! if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) { if (plist->aptpl) PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL); else PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
*** 1489,1499 **** } /* In case there is no reservation exist */ } else { sbd_pgr_do_reserve(pgr, key, it, ses, pr_out); ! if (pgr->pgr_flags & SBD_PGR_APTPL) { if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) { stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INSUFFICIENT_REG_RESOURCES); return; } --- 1518,1528 ---- } /* In case there is no reservation exist */ } else { sbd_pgr_do_reserve(pgr, key, it, ses, pr_out); ! if (sbd_pgr_should_save(slu) == B_TRUE) { if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) { stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INSUFFICIENT_REG_RESOURCES); return; }
*** 1546,1555 **** --- 1575,1589 ---- sbd_pgr_t *pgr = slu->sl_pgr; sbd_pgr_key_t *key = it->pgr_key_ptr; ASSERT(key); + /* + * XXX this does not honor APTPL + * (i.e., changes made to a formerly-persistent reservation are not + * updated here!!!) + */ if (SBD_PGR_RSVD(pgr)) { if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS || pgr->pgr_rsvholder == key) { if (pgr->pgr_rsv_type != pr_out->type || pgr->pgr_rsv_scope != pr_out->scope) {
*** 1557,1568 **** --- 1591,1623 ---- STMF_SAA_INVALID_RELEASE_OF_PR); return; } sbd_pgr_do_release(slu, it, SBD_UA_RESERVATIONS_RELEASED); + + /* + * XXX T10 SPC-3 5.6.10.2 says nothing about what to + * do in the event of a failure updating the + * PGR nvram store for a reservation associated with + * an APTPL-enabled (see SPC-3 5.6.4.1) I_T + * registration during a RELEASE service action. + * + * Technically, the CDB completed successfully, as per + * the spec, but at some point we may need to enter + * a recovery mode on the initiator(s) if we power cycle + * the target at the wrong instant... + */ + if (sbd_pgr_should_save(slu) == B_TRUE) { + if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) { + stmf_scsilib_send_status(task, + STATUS_CHECK, /* CSTYLED */ + STMF_SAA_INSUFFICIENT_REG_RESOURCES); + return; } } + } + } stmf_scsilib_send_status(task, STATUS_GOOD, 0); } static void sbd_pgr_do_release(sbd_lu_t *slu, sbd_it_data_t *it, uint8_t ua_condition)
*** 1600,1610 **** it->pgr_key_ptr = NULL; } mutex_exit(&slu->sl_lock); sbd_pgr_keylist_dealloc(slu); sbd_pgr_set_ua_conditions(slu, it, SBD_UA_RESERVATIONS_PREEMPTED); ! if (pgr->pgr_flags & SBD_PGR_APTPL) { if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) { stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INSUFFICIENT_REG_RESOURCES); return; } --- 1655,1665 ---- it->pgr_key_ptr = NULL; } mutex_exit(&slu->sl_lock); sbd_pgr_keylist_dealloc(slu); sbd_pgr_set_ua_conditions(slu, it, SBD_UA_RESERVATIONS_PREEMPTED); ! if (sbd_pgr_should_save(slu) == B_TRUE) { if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) { stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INSUFFICIENT_REG_RESOURCES); return; }
*** 1715,1725 **** return; } } } ! if (pgr->pgr_flags & SBD_PGR_APTPL) { if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) { stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INSUFFICIENT_REG_RESOURCES); return; } --- 1770,1780 ---- return; } } } ! if (sbd_pgr_should_save(slu) == B_TRUE) { if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) { stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INSUFFICIENT_REG_RESOURCES); return; }
*** 1829,1840 **** if (plist->unreg) { sbd_pgr_do_unregister(slu, it, key); } ! /* Write to disk if currenty aptpl is set or given task is setting it */ ! if (pgr->pgr_flags & SBD_PGR_APTPL || plist->aptpl) { if (plist->aptpl) PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL); else PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL); --- 1884,1895 ---- if (plist->unreg) { sbd_pgr_do_unregister(slu, it, key); } ! /* Write to disk if aptpl is currently set or this task is setting it */ ! if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) { if (plist->aptpl) PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL); else PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);