📄 cippd_pmaint.c
字号:
* 2. Retrieve the remote port station address of the target PB. * 3. Verify the validity of the port station address. * 4. Attempt to retrieve the PB from the vector of "open PBs". * 5. Search the formative PB queue for the target PB provided the attempt * made in Step 4 failed. * 6. Unlock the PCCB provided it was locked within this function. * 7. Return the PB. * * Invalid remote port station addresses trigger event logging of the * offending packet by the appropriate port driver. Such logging occurs * only when: * * 1. The remote port station address exceeds the hardware maximum port * number for the specified local port. * 2. The remote port station address is provided to this function in the * form of a buffer( type == BUF ). * * In other words, event logging is bypassed whenever the remote port * station address exceeds the current software( CI PPD ) but not the * hardware maximum port number of the specified local port; or, the remote * port station address is explicitly provided to this function( * type == NO_BUF ). */ if( !Test_pccb_lock( pccb )) { Lock_pccb( pccb ) unlock = 1; } port = (( type == BUF ) ? ( *pccb->Get_port )( pccb, Scs_to_ppd( scsbp )) : ( u_long )*( u_char * )scsbp ); if( port <= ( CIPPD_MAXPATHS - 1 )) { if(( pb = pccb->Open_pb[ port ] ) == NULL ) { for( pb = pccb->Form_pb.flink; pb != &pccb->Form_pb && Scaaddr_low( Pb->pinfo.rport_addr ) != port; pb = pb->flink ) {} if( pb == &pccb->Form_pb ) { pb = NULL; } } } else { pb = NULL; if( port > pccb->lpinfo.Max_port && type == BUF ) { ( void )( *pccb->Log_badportnum )( pccb, Scs_to_ppd( scsbp )); } } if( unlock ) { Unlock_pccb( pccb ) } return( Pb );}/* Name: cippd_open_pb - Transition Formative Path Block to Open State * * Abstract: This function oversees transitioning of formative paths into * the PS_OPEN path state. It is only invoked when SCS receives a * request for connection establishment on a path that is not * already open. It must NEVER be invoked for "open" paths. * * NOTE: The SCS message buffer passed to this routine must NEVER * be consumed by it. * * Inputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * pb - Path Block pointer( OPTIONAL ) * scsbp - Address of SCS header in message buffer * * Outputs: * * IPL_SCS - Interrupt processor level * * Return Values: * * RET_SUCCESS - Path is successfully transitioned * RET_FAILURE - Path is unsuccessfully transitioned * * SMP: The PCCB is locked to further prevent PB deletion and as * required by both the CI PPD finite state machine and by PD * routines which close virtual circuits in case such action * becomes necessary. PCCBs addresses are always valid because * these data structures are never deleted once their * corresponding ports have been initialized. * * The PB is locked to synchronize access, postpone potential * deletion, and as required by the CI PPD finite state machine. * * The PB must EXTERNALLY be prevented from deletion to guarantee * the validity of its address. */u_longcippd_open_pb( pccb, pb, scsbp ) register PCCB *pccb; register PB *pb; register SCSH *scsbp;{ register u_long status = RET_FAILURE, setcirc = 0; register GVPPPDH *cippdbp = Scs_to_ppd( scsbp ); /* The steps involved in transitioning PBs representing formative paths * into the open state are: * * 1. Lock the PCCB. * 2. Lock the PB. * 3. Invoke the CI PPD finite state machine to transition the path. * 4. Unlock the PB. * 5. Unlock the PCCB. * * No attempt is made to transition the formative path in the absence of a * PB. This situation occurs when both the path and the attempt to disable * it fail and the remote system continues to believe the path is "open". * A STOP CI PPD datagram can NOT be transmitted to notify the remote SYSAP * of local path failure because no PB exists in order to target datagram * transmission. Neither can the finite state machine be invoked to * disable the path because of PB unavailability. The only action which * can and is taken is for this function to make an additional attempt to * disable the path. * * It is possible for SCS sequenced messages to be received over "failed" * paths because at time of reception it is possible for neither the path * to have been disabled nor the remote CI PPD to have been notified of * local path failure. It is also possible for both actions to have taken * place or some combinations in between to have occurred. Failed paths * require special handling and are processed as follows: * * 1. A STOP CI PPD datagram is transmitted to the remote CI PPD. * 2. The return status is changed from RET_SUCCESS to RET_FAILURE * 3. The path is disabled. * * Step 1 is carried out by the CI PPD finite state machine while Steps 2-3 * are executed by this function following finite state machine invocation. * Step 2 is required because the finite state machine always returns * success when processing failed paths and ultimately this routine must * return a failure status to indicate its inability to open the path. * Step 3 must also be done by this function instead of by the finite state * machine. This is because any PD specific resources associated with the * PB and reserved for disabling the corresponding path were exhausted * during the prior path failure processing. Explicitly disabling the path * within this function guarantees that at least the attempt is made. */ Lock_pccb( pccb ) if( pb ) { Lock_pb( pb ) if( pb->pinfo.state == PS_PATH_FAILURE ) { setcirc = 1; } status = cippd_dispatch( pccb, pb, CNFE_SCSMSG_REC, cippdbp ); if( pb->pinfo.state == PS_PATH_FAILURE ) { status = RET_FAILURE; } Unlock_pb( pb ) } else { setcirc = 1; } if( setcirc ) { ( void )( *pccb->Set_circuit )( pccb, NULL, ( *pccb->Get_port )( pccb, cippdbp ), SET_VC_CLOSE ); } Unlock_pccb( pccb ) return( status );}/* Name: cippd_remove_pb - Remove Path Block from System-wide Databases * * Abstract: This routine removes and deallocates the PB representing a * specific failed path from all system-wide databases. It may be * invoked only for established paths and only by SCS. PBs * representing aborted formative paths are deallocated by * cippd_clean_fpb() and never through SCS intervention. * * The SB associated with the path is deallocated following its * removal from the system-wide configuration database provided * there are no longer any remaining paths to it. * * Scheduling of PD specific port re-initialization occurs if * crash initiated clean up of the local port has completed. * * NOTE: The appropriate port drivers are always responsible for * the removal and deallocation of all free datagram and * message buffers associated with failed local ports. The * CI PPD must never attempt to dispose of such buffers. * * Inputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * ppd.cippd - CI PPD specific PCCB fields * fsmstatus.fkip - 0 * pb - Path Block pointer * pinfo.state - PS_PATH_FAILURE * pinfo.nconns - 0 * * Outputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * forkb - PCCB fork block * lpinfo.ppd.cippd - CI PPD specific local port information * npaths - Number of paths associated with the port * ppd.cippd - CI PPD specific PCCB fields * fsmstatus.fkip - Fork operation in progress * sb - System Block pointer * sinfo.npaths - Number of paths to system * * SMP: The SCA database is locked( EXTERNALLY ) for PB removal from * the system-wide configuration database, for SB removal from * this database if it becomes necessary, and to guarantee the * validity of the PB address on entry to this routine. * * The PCCB is locked to allow exclusive access to PCCB contents. * PCCB addresses are always valid because these data structures * are never deleted once their corresponding ports have been * initialized. * * The PB is locked to synchronize access, for removal from all * system-wide databases, for deallocation, and as required by PD * routines which optionally deallocate emergency command packets * associated with the PB. PB locks are released immediately * prior to PB deallocation as required by scs_dealloc_pb(). * PB address validity is guaranteed both by single threading of * path clean up and by incrementing the PB semaphore prior * to scheduling of asynchronous PB clean up. The former should * be sufficient to guarantee validity, but the latter is done * anyway as additional protection and to detect errors in error * recovery logic. * * The PB semaphore is decremented following PB locking. It was * originally incremented prior to scheduling of asynchronous path * clean up to act as a further guarantee of PB validity and to * detect errors in error recovery logic when clean up eventually * commenced. */voidcippd_remove_pb( pccb, pb ) register PCCB *pccb; register PB *pb;{ register GVPH *cibp; register SB *sb = pb->sb; register u_long ( *dealloc )(); /* Removing the PB from the system-wide databases includes: * * 1. Locking the PCCB. * 2. Locking the PB. * 3. Decrementing the PB semaphore. * 4. Optionally removing and deallocating all PD emergency command * packets still associated with the PB. * 5. Removing the PB from all internal queues. * 6. Unlocking the PB. * 7. Deallocating the PB. * 8. Decrementing the count of paths associated with the appropriate SB, * and removing the SB from all queues and deallocating it when there * are no longer any paths to the system. * 9. Decrementing the number of paths originating at the port and * scheduling port initialization through forking only when there are * no longer any paths originating at the port and port clean up is * currently in progress. * 10. Unlock the PCCB. * * The PB semaphore is decremented( Step 3 ) because it was incremented by * the CI PPD finite state machine prior to asynchronous scheduling of PB * clean up to act as a further guarantee of PB validity when clean up( by * cippd_clean_pb() ) eventually commenced and to detect errors in error * recovery logic. * * The PCCB fork block is used to schedule port initialization( Step 8 ). * It should always be available because it is used only for port clean up * and initialization, these activities are single threaded, and * initialization always follows clean up. Guaranteed availability of the * PCCB fork block is one of the benefits of single threading of port clean * up and initialization. * * Once PB removal and deallocation completes, the CI PPD is free to * attempt establishment of a new path incarnation. Such attempts do not * occur until after the path is re-discovered through polling. New path * incarnations are fully subject to crashing on encountering of * sufficiently serious errors. */ Lock_pccb( pccb ) Lock_pb( pb ) Decr_pb_sem( pb ) if( Test_pb_sem( pb )) { ( void )panic( PPDPANIC_BPATH ); } if(( dealloc = pccb->Dealloc_buf )) { ( void )( *dealloc )( pb ); } Remove_entry( pb->flink ) pccb->Open_pb[ Scaaddr_low( pb->pinfo.rport_addr )] = NULL; Unlock_pb( pb ) ( void )scs_dealloc_pb( pccb, pb ); if(( --sb->sinfo.npaths ) == 0 ) { Remove_entry( sb->flink ) ( void )scs_dealloc_sb( sb ); } if( --pccb->lpinfo.Npaths == 0 && pccb->Fsmstatus.cleanup && pccb->lpinfo.Nform_paths == 0 ) { Pccb_fork( pccb, pccb->Init_port, PPDPANIC_PCCBFB ) } Unlock_pccb( pccb )}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -