📄 mscp_conpol.c
字号:
else cp->hst_tmo = cp->cnt_tmo + mscp_htmo_overhead; } mscp_confmtstcon( rp, cp->hst_tmo ); /* If the message is queued successfully, exit to wait for the * end message or timeout. Otherwise, resynch the controller. */ if( mscp_send_msg( rp ) == EV_NULL ) { return( EV_NULL ); } else { return( EV_EXRETRY ); } } } /* The the controller characteristics have been set successfully. * If the controller requires host initiated bad block replacement, * allocate and initialize the BBR work area (BBRB). */ if( cp->classb->flags.disk && !( cp->cnt_flgs & MSCP_CF_REPLC )) { mscp_bbr_init( cp ); } return( EV_CONACTIVE ); }/**//* * * Name: mscp_conmarkopen - Mark the connection open. * * Abstract: * * Inputs: * * Outputs: * * * Return NONE * Values: */u_longmscp_conmarkopen( event, rp ) u_long event; REQB *rp;{ CONNB *cp = rp->connb; /* Initiate polling for units attached to the server on this * connection, and exit. */ mscp_find_controller( cp ); cp->polling_reqb.state_tbl = mscp_pol_states; cp->polling_reqb.state = ST_CMN_INITIAL; mscp_dispatch( EV_INITIAL, &cp->polling_reqb ); return( EV_NULL );}/**//* * * Name: mscp_conrestore - Restore the unit states. * * Abstract: * * Inputs: * * Outputs: * * * Return NONE * Values: */u_longmscp_conrestore( event, rp ) u_long event; register REQB *rp;{ register CONNB *cp = rp->connb; register CLASSB *clp = rp->classb; /* If connection recovery is in progress, initiate a thread to * restore the state of any units that were online when the * connection was lost. */ if( cp->flags.restart ) { cp->polling_reqb.state_tbl = clp->recov_states; cp->polling_reqb.state = ST_CMN_INITIAL; mscp_dispatch( EV_INITIAL, &cp->polling_reqb ); } mscp_polls--; return( EV_NULL );}u_short mscp_force_reset = 0;/**//* * * Name: mscp_conwatchdog - Check activity of an open connection. * * Abstract: * * Inputs: * * Outputs: * * * Return NONE * Values: */u_longmscp_conwatchdog( event, rp ) u_long event; register REQB *rp;{ register CONNB *cp = rp->connb; register REQB *hrp = cp->active.flink; register MSCP *mp = rp->msgptr; register u_long new_event = EV_NULL; if( mscp_force_reset ) { mscp_force_reset = 0; return( EV_EXRETRY ); } /* If the message pointer is NULL, the controller never responded * to the previous GTUNT or GTCMD message. Redispatch to * resynchronize the connection. */ if( mp == NULL ) { new_event = EV_EXRETRY; /* Check to see if there are any requests outstanding in * the active queue. */ } else if( hrp != ( REQB * )&cp->active.flink ) { /* Check to see if the command reference number (RSPID) of the oldest * active command has changed during the timeout interval. If the * RSPIDs are different, at least one command must have completed in * the interval. Update the oldest active RSPID field in the CONNB, * and re-init the command status. */ if( *( u_long * )&hrp->rspid != *( u_long *)&cp->old_rspid ) { cp->old_rspid = hrp->rspid; cp->old_cmd_sts = 0xffffffff; /* The RSPIDs are the same, indicating that the oldest command did not * complete within the previous timeout interval. Check to see if any * progress has been made on the execution of the oldest command by * sending a Get Command Status message out on the connection. */ } else { Init_msg( mp, rp->rspid, NULL ); if( hrp->unitb != NULL ) mp->mscp_unit = hrp->unitb->unit; mp->mscp_opcode = MSCP_OP_GTCMD; mp->mscp_out_ref = *( u_long * )&cp->old_rspid; new_event = mscp_send_msg( rp ); } /* No messages are active on the connection. In order to keep * the controller from timing the host (us) out, send a Get * Unit Status command for unit 0 to give the controller a little * work to do. */ } else { Init_msg( mp, rp->rspid, 0 ); mp->mscp_opcode = MSCP_OP_GTUNT; new_event = mscp_send_msg( rp ); } /* Begin another timeout interval and exit. Any errors encountered * above will cause redispatch to resynchronize the port. */ cp->cmdtmo_intvl = cp->cnt_tmo; return( new_event );}/**//* * * Name: mscp_conendmsg - Process a GTCMD end message. * * Abstract: * * Inputs: * * Outputs: * * * Return NONE * Values: */u_longmscp_conendmsg( event, rp ) u_long event; register REQB *rp;{ register CONNB *cp = rp->connb; register MSCP *mp = rp->msgptr; /* If the command was a GTCMD, check the progress indicator in * the end message. */ if( mp->mscp_endcode == ( MSCP_OP_GTCMD | MSCP_OP_END )) { /* If no progress has been made, error log the end message and * redispatch to break the connection. Otherwise, update the * command status. */ if( cp->old_cmd_sts <= mp->mscp_cmd_sts ) { /* Error log the end message */ return( EV_EXRETRY ); } else cp->old_cmd_sts = mp->mscp_cmd_sts; } mscp_recycle_rspid( rp ); return( EV_NULL );}/**//* * * Name: mscp_conresynch - Resynchronize with a failed (sub-)system. * * Abstract: * * Inputs: * * Outputs: * * * Return NONE * Values: */u_longmscp_conresynch( event, rp ) u_long event; register REQB *rp;{ register CONNB *cp = rp->connb; MSB *msp = ( MSB * )&cp->classb->msb; u_long status; printf( "mscp\t- resynching " ); if( cp->cnt_name != NULL ) { printf( "controller %s%d\n", cp->cnt_name, cp->cnt_number ); } else { printf( "controller ***** at local port %4s ", &cp->lport_name ); printf( "remote port %x\n", cp->rport_addr ); } /* Turn off connection timeouts and fill in the MSB. */ cp->cmdtmo_intvl = 0; msp->lport_name = cp->lport_name; Move_scaaddr( cp->rport_addr, msp->rport_addr ); Move_name( cp->classb->cmsb.lproc_name, msp->Lproc_name ) /* Crash the path to the remote system. If the remote system is a * hardware server, reset and restart it. If the reset or restart * fails, check the reason for the failure. RET_NOLPORT and RET_NOPATH * represent internal errors and result in panic. Other errors may * represent transient lack of a resource and are retried indefinitely. */ status = scs_crash_path( msp ); if( cp->cnt_id.model != MSCP_CM_VMS && cp->cnt_id.model != MSCP_CM_TOPS && cp->cnt_id.model != MSCP_CM_ULTRIX32 ) { msp->Force = 1; if(( status = scs_reset( msp )) != RET_SUCCESS ) { if( status == RET_NOLPORT || status == RET_NOPATH ) { panic( "mscp_conresynch: scs_reset failure.\n" ); } else { cp->cmdtmo_intvl = MAINT_TMO; } } else { msp->Startaddr = 0; if(( status = scs_restart( msp )) != RET_SUCCESS ) { if( status == RET_NOLPORT || status == RET_NOPATH ) { panic( "mscp_conresynch: scs_restart failure.\n" ); } else { cp->cmdtmo_intvl = MAINT_TMO; } } } } return( EV_NULL );}/**//* * * Name: mscp_concleanup - Clean up after a lost connection. * * Abstract: This routine is entered when connection management is notified * that a virtual path has failed or a disconnect has been * received. Deallocate all resources held by REQBs on the * connection, and funnel the REQBs onto the restart queue. Then * attempt to restore the connection. * * Inputs: * * Outputs: * * * Return NONE * Values: */u_longmscp_concleanup( event, rp ) u_long event; REQB *rp;{ register UNITB *up = rp->unitb; register CONNB *cp = rp->connb; register REQB *wrp, *savwrp; CLASSB *clp = rp->classb; CMSB cmsb; u_long status; u_long new_event = EV_NULL; /* Turn off connection timeouts. */ cp->cmdtmo_intvl = 0; /* Bump the resource wait reason count for each UNITB attached to * this CONNB in order to stall all new requests on the connection. */ for( up = cp->unit.flink; (( up != ( UNITB * )&cp->unit.flink ) && ( !up->flags.wait_bump )); up = up->flink ) { up->flags.wait_bump = 1; up->rwaitct++; } /* Return resources held by the permanent request blocks. */ mscp_dealloc_all( &cp->timeout_reqb ); mscp_dealloc_all( &cp->polling_reqb ); /* ***** NEED TO ADD CODE TO SCAN BBR WAIT QUEUE ***** */ /* Scan the RSPID wait queue looking for REQBs for the current * connection. Requeue each REQB in the restart queue. */ for( wrp = ( REQB * )mscp_rspid_wait_lh.flink; wrp != ( REQB * )&mscp_rspid_wait_lh; wrp = savwrp ) { /* save off flink because of wrp requeue on restart queue */ savwrp = wrp->flink; /* If the REQB is for the current connection, remove it from * the wait queue, decrement the wait reasons counter, and * queue it on the restart queue. */ if( cp == wrp->connb ) { Remove_entry( wrp->flink ); Decr_rwait( wrp ); mscp_conqrestart( wrp ); } } /* Drain the buffer, credit, and mapping wait queues into the * restart queue. For each REQB encountered, decrement the * appropriate resource wait reasons counter before requeueing. */ for( wrp = cp->buffer_wq.flink; wrp != (REQB *)&cp->buffer_wq; wrp = cp->buffer_wq.flink ) { Remove_entry( wrp->flink ); Decr_rwait( wrp ); mscp_conqrestart( wrp ); } for( wrp = cp->credit_wq.flink; wrp != (REQB *)&cp->credit_wq; wrp = cp->credit_wq.flink ) { Remove_entry( wrp->flink ); Decr_rwait( wrp ); mscp_conqrestart( wrp ); } for( wrp = cp->map_wq.flink; wrp != (REQB *)&cp->map_wq; wrp = cp->map_wq.flink ) { Remove_entry( wrp->flink ); Decr_rwait( wrp ); mscp_conqrestart( wrp ); } /* Drain the queue of requests active in the controller into * the restart queue. */ for( wrp = cp->active.flink; wrp != (REQB *)&cp->active; wrp = cp->active.flink ) { Remove_entry( wrp->flink ); mscp_conqrestart( wrp ); } /* Issue an SCS disconnect. If the disconnect succeeds, and the * path had failed, the disconnect completes synchronously, so it * is possible to redispatch immediately to restart the connection. * Otherwise, the disconnect occurs asynchronously, in which case * we exit to await disconnect completion. */ cmsb = clp->cmsb; Move_connid( cp->connid, cmsb.connid ); cmsb.Reason = ADR_SUCCESS; if(( status = scs_disconnect( &cmsb )) == RET_SUCCESS ) { if( cp->flags.path_fail ) { cp->flags.path_fail = 0; cp->flags.restart = 1; new_event = EV_ERRECOV; } /* The disconnect failed. Shouldn't happen. Panic. */ } else { panic( "mscp_concleanup: disconnect failed\n" ); } return( new_event );}/**//* * * Name: mscp_condisccmplt - process completed disconnect. * * Abstract: * * Inputs: * * Outputs: * * * Return NONE * Values: */u_longmscp_condisccmplt( event, rp ) u_long event; register REQB *rp;{ register CONNB *cp = rp->connb; /* Mark the connection block as being restarted and redispatch to * attempt reconnection. */ cp->flags.restart = 1; return( EV_ERRECOV );}/**//* * * Name: mscp_condealmsg - Deallocate message buffers during restart. * * Abstract: * * Inputs: * * Outputs: * * * Return NONE * Values: */ u_longmscp_condealmsg( event, rp ) u_long event; register REQB *rp;{ register CONNB *cp = rp->connb; CSB csb; register CSB *csp = ( CSB * )&csb; u_long scs_status; /* Return the buffer to SCS ignoring any error that may occur. */ Move_connid( cp->connid, csp->connid ); csp->buf = ( u_char * )rp->msgptr; rp->msgptr = NULL; scs_status = scs_dealloc_msg( csp ); return( EV_NULL );}/**//* * * Name: mscp_consubr - Issue scs_connect and analyze return status * * Abstract: This routine attempts to make an SCS connection and * analyzes the return status. If the connect attempt * starts successfully, the connection state is updated. * * Inputs: rp Request block * connb Connection block pointer * * Outputs: cp Connection block * state Connection state *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -