Esempio n. 1
0
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 */
	}
}
Esempio n. 2
0
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;
		}
	}
}
Esempio n. 3
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), &reg_seqno, &reg_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
}
Esempio n. 4
0
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);
	}
}
Esempio n. 5
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), &reg_seqno, &reg_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;
}
Esempio n. 6
0
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 = &section_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;
}