📄 mscp_bbr.c
字号:
/* * * Name: mscp_bbr_step7b - Stress test bad block, continued * * Abstract: Step 7 of the bad block replacement algorithm * issues reads and writes with correction and error * recovery disabled to test the block in question. * This function writes the saved data, then reads it * back up to 4 times. An error during writing or * reading means that the stress test has failed and * the block will have to be replaced. * * Inputs: IPL_SCS * event Event code * rp Request block pointer * * Implicit * Inputs: * * Outputs: * * * Return * Values: EV_NULL */u_longmscp_bbr_step7b( event, rp ) u_long event; register REQB *rp;{ register BBRB *bbrp = rp->connb->bbrb; register MSCP *mp = rp->msgptr; register u_long new_event = EV_NULL; u_long code = mp->mscp_status & MSCP_ST_MASK; u_long subcode = mp->mscp_status >> MSCP_ST_SBBIT; Dprintf("mscp_bbr_step7b: entered, Event = %x\n", event); /* If the event indicates initial entry for this substep, initialize * the loop counter and write the saved data into the block in question. */ if( event == EV_BBRSUCCESS ) { bbrp->loop_ct1 = 4; rp->p1 = bbrp->lbn; rp->p2 = MSCP_MD_SECOR | MSCP_MD_SEREC; new_event = mscp_bbr_write( rp, bbrp->buf1 ); /* Not initial entry, so an end message must have arrived. If the * the message was a write, and the write succeeded, start up the * first read. If the write failed, set an error flag and set the * return status to cause redispatch to step 8. */ } else if( mp->mscp_endcode == ( MSCP_OP_WRITE | MSCP_OP_END )) { if( code == MSCP_ST_SUCC ) { new_event = mscp_bbr_read( rp, bbrp->buf3 ); } else { bbrp->flags.bit.error = 1; new_event = EV_BBRERROR; } /* The end message was a read. If the end message status is success * and the bad block reported flag is set or the status is a data * error other than forced error, the read failed. Set an error flag * and the return status. */ } else if( (( code == MSCP_ST_SUCC ) && ( mp->mscp_flags & MSCP_EF_BBLKR )) || (( code == MSCP_ST_DATA ) && ( subcode != MSCP_SC_FRCER )) ) { bbrp->flags.bit.error = 1; new_event = EV_BBRERROR; /* If the read succeeded and there are more reads to do, issue the * next one. */ } else if( --bbrp->loop_ct1 ) { new_event = mscp_bbr_read( rp, bbrp->buf3 ); /* All of the stress reads succeeded. Continue to the next substep. */ } else { new_event = EV_BBRSUCCESS; } return( new_event );}/**//* * * Name: mscp_bbr_step7c - Stress test bad block, continued * * Abstract: Step 7 of the bad block replacement algorithm * issues reads and writes with correction and error * recovery disabled to test the block in question. * This function writes the inverse (one's complement) of * the saved data, then reads it back up to 4 times. An * error during writing or reading means that the stress * test has failed and the block will have to be replaced. * * Inputs: IPL_SCS * event Event code * rp Request block pointer * * Implicit * Inputs: * * Outputs: * * * Return * Values: EV_NULL */u_longmscp_bbr_step7c( event, rp ) u_long event; register REQB *rp;{ register BBRB *bbrp = rp->connb->bbrb; register MSCP *mp = rp->msgptr; register u_long new_event = EV_NULL; u_long code = mp->mscp_status & MSCP_ST_MASK; u_long subcode = mp->mscp_status >> MSCP_ST_SBBIT; Dprintf("mscp_bbr_step7c: entered, Event = %x\n", event); /* If the event indicates initial entry for this substep, initialize * the loop counter and write the inverse of the saved data into the * block in question. The data is written with error correction and * error recovery suppressed, and with the forced error modifier set * to protect the integrity of the block. */ if( event == EV_BBRSUCCESS ) { bbrp->loop_ct1 = 4; rp->p1 = bbrp->lbn; rp->p2 = MSCP_MD_SECOR | MSCP_MD_SEREC | MSCP_MD_ERROR; new_event = mscp_bbr_write( rp, bbrp->buf2 ); /* Not initial entry, so an end message must have arrived. If the * the message was a write, and the write succeeded, start up the * first read. If the write failed, set an error flag and set the * return status to EV_BBRERROR causing redispatch to step 8. */ } else if( mp->mscp_endcode == ( MSCP_OP_WRITE | MSCP_OP_END )) { if( code == MSCP_ST_SUCC ) { new_event = mscp_bbr_read( rp, bbrp->buf3 ); } else { bbrp->flags.bit.error = 1; new_event = EV_BBRERROR; } /* The end message was a read. If the end message status is success * and the bad block reported flag is set or the status is a data * error other than forced error, the read failed. Set an error flag * and set the return status to EV_BBRERROR. */ } else if( (( code == MSCP_ST_SUCC ) && ( mp->mscp_flags & MSCP_EF_BBLKR )) || (( code == MSCP_ST_DATA ) && ( subcode != MSCP_SC_FRCER )) ) { bbrp->flags.bit.error = 1; new_event = EV_BBRERROR; /* If the read succeeded and there are more reads to do, issue the * next one. */ } else if( --bbrp->loop_ct1 ) { new_event = mscp_bbr_read( rp, bbrp->buf3 ); /* All of the stress reads succeeded. If any more repetitions of the * stress test remain, loop back to the substep corresponding to step * 7b of the algorithm. Otherwise, set the return status to continue * on to step 8. */ } else if( --bbrp->loop_ct2 ) { new_event = EV_BBRSUCCESS; } else { new_event = EV_BBRERROR; } return( new_event );}/**//* * * Name: mscp_bbr_step8 - Write back saved data * * Abstract: Step 8 of the bad block replacement algorithm * writes the saved data back to the bad block, then * reads it back and compares it to the saved data. * If the step 7 stress testing and the step 8 write, * read and compare operations all succeed, the block * in question is not bad and doesn't need to be * replaced. * * Inputs: IPL_SCS * event Event code * rp Request block pointer * * Implicit * Inputs: * * Outputs: * * * Return * Values: EV_NULL */u_longmscp_bbr_step8( event, rp ) u_long event; register REQB *rp;{ register BBRB *bbrp = rp->connb->bbrb; register MSCP *mp = rp->msgptr; register u_long new_event = EV_NULL; u_long code = mp->mscp_status & MSCP_ST_MASK; u_long subcode = mp->mscp_status >> MSCP_ST_SBBIT; Cprintf("mscp_bbr_step8: entered, Event = %x\n", event); /* On initial entry into this substep, initialize the loop counter * and write the saved data into the block in question. If the FE flag * is set, write the data with the forced error modifier. */ if( (event == EV_BBRSUCCESS) || (event == EV_BBRERROR) ) { rp->p1 = bbrp->lbn; rp->p2 = 0; if( bbrp->flags.bit.fe ) rp->p2 |= MSCP_MD_ERROR; new_event = mscp_bbr_write( rp, bbrp->buf1 ); /* Not the initial entry, so an end message arrived. If the message was * a write, and it succeeded, read back the data into another work * buffer. If the write failed or the error flag is set from step 7, * set the status to EV_BBRERROR. */ } else if( mp->mscp_endcode == ( MSCP_OP_WRITE | MSCP_OP_END )) { if(( code != MSCP_ST_SUCC ) || ( bbrp->flags.bit.error )) new_event = EV_BBRERROR; else new_event = mscp_bbr_read( rp, bbrp->buf3 ); /* The end message was a read. If the end message status is success * or the status is a forced error and the data was written with the * forced error modifier, the read succeeded. Compare the saved data * to the data read back. If the read and the compare both succeeded, * set the return status to EV_BBRSUCCESS. Otherwise set it to * EV_BBRERROR. */ } else if(( code == MSCP_ST_SUCC ) || (( code == MSCP_ST_DATA ) && ( subcode == MSCP_SC_FRCER ) && ( bbrp->flags.bit.fe )) && ( bcmp( bbrp->buf1, bbrp->buf3, 512 ) == 0 )) { new_event = EV_BBRSUCCESS; bbrp->flags.bit.trans = 1; /* The read failed: set the error flag. */ } else new_event = EV_BBRERROR; return( new_event );}/**//* * * Name: mscp_bbr_step9 - Search RCT for available RBN * * Abstract: This function invokes the RCT search routine to * find an available replacement block. In addition, * a recursion counter is checked to ensure that this * step is not reentered an excessive number of times * from step 12 when replacing a bad replacement block. * * Inputs: IPL_SCS * event Event code * rp Request block pointer * * Implicit * Inputs: * * Outputs: * * * Return * Values: EV_NULL */u_longmscp_bbr_step9( event, rp ) u_long event; register REQB *rp;{ register BBRB *bbrp = rp->connb->bbrb; register u_long new_event; Cprintf("mscp_bbr_step9: entered\n"); /* If the recursion count has not yet gone to zero, search the * RCT for an available replacement block. Otherwise, log the * error and redispatch with error status. */ if( bbrp->recursion_ct-- ) new_event = mscp_rct_search( EV_NULL, rp ); else { bbrp->flags.bit.recurs = 1; new_event = EV_BBRERROR; } return( new_event );}/**//* * * Name: mscp_bbr_step10 - Phase 2 update to RCT sector 0 * * Abstract: This function updates RCT sector 0 to reflect the * phase 2 state. The sector, read in step 6, is * modified and written to the RCT. * * Inputs: IPL_SCS * event Event code * rp Request block pointer * * Implicit * Inputs: * * Outputs: * * * Return * Values: EV_NULL */u_longmscp_bbr_step10( event, rp ) u_long event; register REQB *rp;{ register BBRB *bbrp = rp->connb->bbrb; register UNITB *up = rp->unitb; register RCT_SECTOR_0 *sp = ( RCT_SECTOR_0 * )bbrp->buf0; Cprintf("mscp_bbr_step10: entered\n"); /* Update RCT sector 0. Set the phase 2 flag, clear the phase 1 and * bad replacement block flags, and store the replacement block number. * If the logical block has been replaced previously, set the bad * replacement block flag and store the previous (bad) RBN. */ sp->flags |= RCT_S0_P2; sp->flags &= ~( RCT_S0_P1 | RCT_S0_BR ); sp->rbn = bbrp->rbn; if( bbrp->flags.bit.match ) { sp->flags |= RCT_S0_BR; sp->badrbn = bbrp->match_rbn; } /* Set up the buffer address and RCT sector 0 logical block * number and start the multicopy write. */ bbrp->multi_buf = bbrp->buf0; rp->p1 = up->unt_size; return( mscp_multi_write( rp ));}/**//* * * Name: mscp_bbr_step11 - * * Abstract: This function issues a read for the target RCT descriptor * block if the block has not already been read (i.e. we got * here from online processing) * * Inputs: IPL_SCS * event Event code * rp Request block pointer * * Implicit * Inputs: * * Outputs: * * * Return * Values: EV_NULL */u_longmscp_bbr_step11( event, rp ) u_long event; register REQB *rp;{ register BBRB *bbrp = rp->connb->bbrb; register UNITB *up = rp->unitb; register RCT_DESC *sp; u_long new_block; u_long new_event = EV_BBRSUCCESS; Cprintf("mscp_bbr_step11: entered, Event = %x\n", event); /* If in Phase 2 recovery must read in RCT block for destination RBN */ if( (event == EV_INITIAL) && bbrp->flags.bit.p2recov) { new_block = ( bbrp->rbn / 128 ) + up->unt_size + 2; bbrp->cur_block = new_block; bbrp->multi_buf = bbrp->buf2; rp->p1 = new_block; new_event = mscp_multi_read( rp ); } /* If it was necessary to read in a RCT block, processing * will be continued in step11a when the multi-read completes. * Otherwise, pass control to step11b. */ return( new_event );}/**//* * * Name: mscp_bbr_step11a - * * Abstract: This function updates the RCT descriptor block to record * the replacement. If a previous replacement of this block had * occurred and the descriptor is in a different RCT block, issue * a read for that block. * * Inputs: IPL_SCS * event Event code * rp Request block pointer * * Implicit * Inputs: * * Outputs: * * * Return * Values: EV_NULL */u_longmscp_bbr_step11a( event, rp ) u_long event; register REQB *rp;{ register BBRB *bbrp = rp->connb->bbrb; register UNITB *up = rp->unitb; register RCT_DESC *sp; u_long new_block, old_block; u_long new_event = EV_BBRSUBSTEP; Cprintf("mscp_bbr_step11a: entered\n"); Cprintf("lbn = %x, rbn = %x, block = %x\n", bbrp->lbn, bbrp->rbn, bbrp->cur_block); /* Calculate the offset of the new replacement descriptor, then * fill it in with the bad block lbn and primary/non-primary code. * Set a flag to indicate that the RCT has been modified. */ bbrp->flags.bit.rplatt = 1; sp = (( RCT_DESC * )bbrp->buf2 ) + ( bbrp->rbn % 128 ); sp->lbn = bbrp->lbn; if( bbrp->flags.bit.nonprim ) sp->code = RCT_DS_NONPRIM; else sp->code = RCT_DS_PRIMARY; /* If there has been a previous replacement of the bad block and the * current and previous replacement block descriptors fall into * different RCT blocks, read the RCT block that contains the * previous replacement block descriptor. If the descriptors fall * into the same RCT block, save a copy of the old descriptor in the * BBRB, and fill in the old descriptor with the "unusable" code and a * zero LBN. */ if( bbrp->flags.bit.match ) { old_block = ( bbrp->match_rbn / 128 ) + up->unt_size + 2; if( old_block != bbrp->cur_block ) { bbrp->multi_buf = bbrp->buf3; rp->p1 = old_block; new_event = mscp_multi_read( rp ); } else { sp = (( RCT_DESC * )bbrp->buf2 ) + ( bbrp->match_rbn % 128 ); bbrp->prev_desc.code = sp->code; bbrp->prev_desc.lbn = sp->lbn; sp->code = RCT_DS_UNUSABL; sp->lbn = 0; } } /* If it was necessary to read in a second RCT block, processing * will be continued in step11b when the multi-read completes. * Otherwise, pass control to step11c. */ return( new_event );}/**//* * * Name: mscp_bbr_step11b - * * Abstract: This function writes the second updated RCT descriptor * block to disk. * * Inputs: IPL_SCS * event Event code * rp Request block pointer * * Implicit * Inputs: * * Outputs: * * * Return * Values: EV_NULL */u_longmscp_bbr_step11b( event, rp ) u_long event; register REQB *rp;{ register BBRB *bbrp = rp->connb->bbrb; register UNITB *up = rp->unitb; register RCT_DESC *sp; u_long new_event; Cprintf("mscp_bbr_step11b: entered\n"); /* Calculate the offset of the previous replacement descriptor, save a * copy of the descriptor in the BBRB, and fill it in with the "unusable" * descriptor code and a zero lbn. Then multi-write the block back into * the RCT. */ sp = ( RCT_DESC * )bbrp->buf3 + ( bbrp->match_rbn % 128 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -