static void jnl_oper_krnl_ast(gd_region *reg) { jnl_private_control *jpc; if (!GTM_PROBE(SIZEOF(gd_region), reg, READ) || !reg->open) return; if (!GTM_PROBE(SIZEOF(gd_segment), reg->dyn.addr, READ)) return; if (dba_bg != reg->dyn.addr->acc_meth && dba_mm != reg->dyn.addr->acc_meth) return; if (!GTM_PROBE(SIZEOF(file_control), reg->dyn.addr->file_cntl, READ)) return; if (!GTM_PROBE(SIZEOF(vms_gd_info), reg->dyn.addr->file_cntl->file_info, READ)) return; jpc = FILE_INFO(reg)->s_addrs.jnl; /* since *cs_addrs is a part of vms_gds_info, no additional probe for sgmnt_addrs is needed */ if (!GTM_PROBE(SIZEOF(jnl_private_control), jpc, WRITE)) return; if ((FALSE == jpc->qio_active) && (NOJNL != jpc->channel)) { jpc->old_channel = jpc->channel; jpc->channel = NOJNL; if (!GTM_PROBE(SIZEOF(vms_lock_sb), jpc->jnllsb, WRITE)) return; jpc->status = gtm_deq(jpc->jnllsb->lockid, NULL, PSL$C_USER, 0); sys$dclast(jnl_oper_user_ast, reg, PSL$C_USER); /* if it fails, jnl_ensure_open should cleanup */ } }
void jnl_oper_user_ast(gd_region *reg) { jnl_private_control *jpc; uint4 status; int close_res; if (reg && reg->open) { jpc = FILE_INFO(reg)->s_addrs.jnl; if (SS_NORMAL != jpc->status) { assert(0 != jpc->jnllsb->lockid); status = gtm_deq(jpc->jnllsb->lockid, NULL, PSL$C_USER, 0); assert(SS$_NORMAL == status); jnl_send_oper(jpc, status); } if ((FALSE == jpc->qio_active) && (NOJNL != jpc->old_channel)) { JNL_FD_CLOSE(jpc->old_channel, close_res); /* sets csa->jnl->channel to NOJNL */ jpc->pini_addr = 0; jpc->jnllsb->lockid = 0; } } }
void jnl_file_lost(jnl_private_control *jpc, uint4 jnl_stat) { /* Notify operator and terminate journaling */ unsigned int status; sgmnt_addrs *csa; seq_num reg_seqno, jnlseqno; error_def(ERR_REPLJNLCLOSED); error_def(ERR_JNLCLOSED); switch(jpc->region->dyn.addr->acc_meth) { case dba_mm: case dba_bg: csa = &FILE_INFO(jpc->region)->s_addrs; break; default: GTMASSERT; } #ifdef VMS /* The following assert has been removed as it could be FALSE if the caller is "jnl_file_extend" * assert(0 != memcmp(csa->nl->jnl_file.jnl_file_id.fid, zero_fid, sizeof(zero_fid))); */ #endif assert(csa->now_crit); if (0 != jnl_stat) jnl_send_oper(jpc, jnl_stat); csa->hdr->jnl_state = jnl_closed; jpc->jnl_buff->cycle++; /* increment shared cycle so all future callers of jnl_ensure_open recognize journal switch */ assert(jpc->cycle < jpc->jnl_buff->cycle); if (REPL_ENABLED(csa->hdr)) { csa->hdr->repl_state = repl_was_open; reg_seqno = csa->hdr->reg_seqno; jnlseqno = (NULL != jnlpool.jnlpool_ctl) ? jnlpool.jnlpool_ctl->jnl_seqno : MAX_SEQNO; send_msg(VARLSTCNT(8) ERR_REPLJNLCLOSED, 6, DB_LEN_STR(jpc->region), ®_seqno, ®_seqno, &jnlseqno, &jnlseqno); } else send_msg(VARLSTCNT(5) ERR_JNLCLOSED, 3, DB_LEN_STR(jpc->region), &csa->ti->curr_tn); #ifdef VMS assert(0 != csa->jnl->jnllsb->lockid); status = gtm_enqw(EFN$C_ENF, LCK$K_EXMODE, csa->jnl->jnllsb, LCK$M_CONVERT | LCK$M_NODLCKBLK, NULL, 0, NULL, 0, NULL, PSL$C_USER, 0); if (SS$_NORMAL == status) status = csa->jnl->jnllsb->cond; jnl_file_close(jpc->region, FALSE, FALSE); if (SS$_NORMAL == status) status = gtm_deq(csa->jnl->jnllsb->lockid, NULL, PSL$C_USER, 0); if (SS$_NORMAL != status) GTMASSERT; # else jnl_file_close(jpc->region, FALSE, FALSE); #endif }
void gtm_blkast(gd_region *region) { vms_gds_info *vbi; if (region != NULL) { vbi = FILE_INFO(region); gtm_deq(vbi->file_cntl_lsb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); gtm_enqw(EFN$C_ENF, LCK$K_PWMODE, &vbi->file_cntl_lsb, LCK$M_CONVERT, NULL, 0, NULL, 0, NULL, PSL$C_USER, 0); /* Update the lock value block and reestablish the blocking AST */ vbi->file_cntl_lsb.valblk[0] = region->node; gtm_enq(0, LCK$K_CRMODE, &vbi->file_cntl_lsb, LCK$M_CONVERT | LCK$M_VALBLK, NULL, 0, NULL, region, gtm_blkast, PSL$C_USER, 0); } }
uint4 jnl_file_lost(jnl_private_control *jpc, uint4 jnl_stat) { /* Notify operator and terminate journaling */ unsigned int status; sgmnt_addrs *csa; seq_num reg_seqno, jnlseqno; boolean_t was_lockid = FALSE, instfreeze_environ; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; switch(jpc->region->dyn.addr->acc_meth) { case dba_mm: case dba_bg: csa = &FILE_INFO(jpc->region)->s_addrs; break; default: assertpro(FALSE && jpc->region->dyn.addr->acc_meth); } # ifdef VMS /* The following assert has been removed as it could be FALSE if the caller is "jnl_file_extend" * assert(0 != memcmp(csa->nl->jnl_file.jnl_file_id.fid, zero_fid, SIZEOF(zero_fid))); */ # endif assert(csa->now_crit); /* We issue an rts_error (instead of shutting off journaling) in the following cases : {BYPASSOK} * 1) $gtm_error_on_jnl_file_lost is set to issue runtime error (if not already issued) in case of journaling issues. * 2) The process has the given message set in $gtm_custom_errors (indicative of instance freeze on error setup) * in which case the goal is to never shut-off journaling */ UNIX_ONLY(assert(jnlpool.jnlpool_ctl == jnlpool_ctl)); UNIX_ONLY(instfreeze_environ = INST_FREEZE_ON_MSG_ENABLED(csa, jnl_stat)); VMS_ONLY(instfreeze_environ = FALSE); if ((JNL_FILE_LOST_ERRORS == TREF(error_on_jnl_file_lost)) || instfreeze_environ) { VMS_ONLY(assert(FALSE)); /* Not fully implemented / supported on VMS. */ if (!process_exiting || instfreeze_environ || !csa->jnl->error_reported) { csa->jnl->error_reported = TRUE; in_wcs_recover = FALSE; /* in case we're called in wcs_recover() */ if (SS_NORMAL != jpc->status) rts_error_csa(CSA_ARG(csa) VARLSTCNT(7) jnl_stat, 4, JNL_LEN_STR(csa->hdr), DB_LEN_STR(gv_cur_region), jpc->status); else rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) jnl_stat, 4, JNL_LEN_STR(csa->hdr), DB_LEN_STR(gv_cur_region)); } return jnl_stat; } if (0 != jnl_stat) jnl_send_oper(jpc, jnl_stat); csa->hdr->jnl_state = jnl_closed; jpc->jnl_buff->cycle++; /* increment shared cycle so all future callers of jnl_ensure_open recognize journal switch */ assert(jpc->cycle < jpc->jnl_buff->cycle); if (REPL_ENABLED(csa->hdr)) { csa->hdr->repl_state = repl_was_open; reg_seqno = csa->hdr->reg_seqno; jnlseqno = (NULL != jnlpool.jnlpool_ctl) ? jnlpool.jnlpool_ctl->jnl_seqno : MAX_SEQNO; send_msg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_REPLJNLCLOSED, 6, DB_LEN_STR(jpc->region), ®_seqno, ®_seqno, &jnlseqno, &jnlseqno); } else send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_JNLCLOSED, 3, DB_LEN_STR(jpc->region), &csa->ti->curr_tn); #ifdef VMS /* We can get a jnl_file_lost before the file is even created, so locking is done only if the lock exist */ if (0 != csa->jnl->jnllsb->lockid) { was_lockid = TRUE; status = gtm_enqw(EFN$C_ENF, LCK$K_EXMODE, csa->jnl->jnllsb, LCK$M_CONVERT | LCK$M_NODLCKBLK, NULL, 0, NULL, 0, NULL, PSL$C_USER, 0); if (SS$_NORMAL == status) status = csa->jnl->jnllsb->cond; } jnl_file_close(jpc->region, FALSE, FALSE); if (was_lockid) { if (SS$_NORMAL == status) status = gtm_deq(csa->jnl->jnllsb->lockid, NULL, PSL$C_USER, 0); assertpro(SS$_NORMAL == status); } # else jnl_file_close(jpc->region, FALSE, FALSE); #endif return EXIT_NRM; }
void ccp_close1(ccp_db_header *db) { ccp_db_header *db0, *db1; ccp_que_entry *que_ent; ccp_relque *que_hd; mem_list *ml_ptr, *ml_ptr_hold; sgmnt_addrs *csa; vms_gds_info *gds_info; unsigned char section_name[GLO_NAME_MAXLEN]; uint4 retadr[2], status, outaddrs[2]; struct dsc$descriptor_s name_dsc; if (ccp_stop) ccp_stop_ctr--; if (db->stale_in_progress) sys$cantim(&db->stale_timer_id, PSL$C_USER); ccp_quemin_adjust(CCP_CLOSE_REGION); sys$cantim(&db->tick_timer_id, PSL$C_USER); sys$cantim(&db->quantum_timer_id, PSL$C_USER); db->segment->nl->ccp_state = CCST_CLOSED; db->wmexit_requested = TRUE; /* ignore any blocking ASTs - already releasing */ gds_info = FILE_INFO(db->greg); if (JNL_ENABLED(db->glob_sec)) { if (db->segment->jnl != NULL && db->segment->jnl->channel != 0) { status = sys$setimr(0, delta_1_sec, ccp_close_timeout, &db->close_timer_id, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = ccp_enqw(EFN$C_ENF, LCK$K_EXMODE, &db->wm_iosb, LCK$M_CONVERT | LCK$M_NOQUEUE, NULL, 0, NULL, 0, NULL, PSL$C_USER, 0); if (status == SS$_NOTQUEUED) /* We're not the only node accessing the journal file */ jnl_file_close(db->greg, FALSE, FALSE); else { /***** Check error status here? *****/ if (db->segment->jnl->jnl_buff->before_images && db->segment->ti->curr_tn > db->segment->jnl->jnl_buff->epoch_tn) { csa = db->segment; JNL_SHORT_TIME(jgbl.gbl_jrec_time); /* needed for jnl_put_jrt_pini() and jnl_write_epoch_rec() */ if (0 == csa->jnl->pini_addr) jnl_put_jrt_pini(csa); db->segment->jnl->jnl_buff->epoch_tn = db->segment->ti->curr_tn; jnl_write_epoch_rec(db->segment); } jnl_file_close(db->greg, TRUE, FALSE); } sys$cantim(&db->close_timer_id, PSL$C_USER); status = gtm_deq(gds_info->s_addrs.jnl->jnllsb->lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ } } db->segment = NULL; /* Warn AST's that the segment has been deleted */ status = sys$deq(db->lock_iosb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); if (status != SS$_NORMAL && status != SS$_CANCELGRANT) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$deq(db->refcnt_iosb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); if (status != SS$_NORMAL && status != SS$_CANCELGRANT) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$deq(db->wm_iosb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); if (status != SS$_NORMAL && status != SS$_CANCELGRANT) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$deq(db->flush_iosb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); if (status != SS$_NORMAL && status != SS$_CANCELGRANT) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$cancel(gds_info->fab->fab$l_stv); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$dassgn(gds_info->fab->fab$l_stv); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ csa = &gds_info->s_addrs; outaddrs[0] = csa->db_addrs[0] - OS_PAGE_SIZE; /* header no access page */ outaddrs[1] = csa->db_addrs[1] + OS_PAGE_SIZE; /* trailer no access page */ if (FALSE == is_va_free(outaddrs[0])) gtm_deltva(outaddrs, NULL, PSL$C_USER); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$cretva(csa->db_addrs, retadr, PSL$C_USER); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ assert(retadr[0] == csa->db_addrs[0] && retadr[1] == csa->db_addrs[1]); ml_ptr_hold=db->mem_ptr; if (ml_ptr_hold->prev != NULL) { /* if prior segment is adjacent and free, coalesce the segments */ if (ml_ptr_hold->prev->free && ml_ptr_hold->addr == ml_ptr_hold->prev->addr + OS_PAGELET_SIZE * ml_ptr_hold->prev->pages) { ml_ptr = ml_ptr_hold->prev; ml_ptr->next = ml_ptr_hold->next; if (ml_ptr->next != NULL) ml_ptr->next->prev = ml_ptr; ml_ptr->pages += ml_ptr_hold->pages; free(ml_ptr_hold); ml_ptr_hold = ml_ptr; } } if (ml_ptr_hold->next != NULL) { /* if next segment is adjacent and free, coalesce the segments */ if (ml_ptr_hold->next->free && ml_ptr_hold->next->addr == ml_ptr_hold->addr + OS_PAGELET_SIZE * ml_ptr_hold->pages) { ml_ptr = ml_ptr_hold->next; ml_ptr_hold->next = ml_ptr->next; if (ml_ptr_hold->next != NULL) ml_ptr_hold->next->prev = ml_ptr_hold; ml_ptr_hold->pages += ml_ptr->pages; free(ml_ptr); } } ml_ptr_hold->free = TRUE; global_name("GT$S", &gds_info->file_id, section_name); name_dsc.dsc$a_pointer = §ion_name[1]; name_dsc.dsc$w_length = section_name[0]; name_dsc.dsc$b_dtype = DSC$K_DTYPE_T; name_dsc.dsc$b_class = DSC$K_CLASS_S; status = del_sec(SEC$M_SYSGBL, &name_dsc, NULL); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ /* Dequeue locks after delete section in ccp_close, acquire lock before create section in gvcst_init, release lock after delete section in gds_rundown */ status = gtm_deq(db->lock_iosb.lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = gtm_deq(db->refcnt_iosb.lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = gtm_deq(db->wm_iosb.lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = gtm_deq(db->flush_iosb.lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ que_hd = &ccp_action_que[PRIORITY]; for (que_ent = (char *)que_hd + que_hd->bl; que_ent != que_hd; que_ent = (char *)que_ent + que_ent->q.bl) if (que_ent->value.v.h == db) que_ent->value.v.h = 0; free(gds_info->fab->fab$l_nam); free(gds_info->fab); free(db->greg->dyn.addr); free(db->greg); /* Remove db from list, this list should never be changed in an AST */ for (db0 = ccp_reg_root, db1 = NULL; db0 != db; db1 = db0, db0 = db0->next) ; if (db1 == NULL) ccp_reg_root = db0->next; else db1->next = db0->next; free(db); return; }