📄 dcachecbio.c
字号:
pDesc = (DCACHE_DESC *) DLL_FIRST( & pDc->dc_LRU ); while( pDesc != NULL ) { if( pDesc->block == block ) { goto found ; } pDesc = (DCACHE_DESC *) DLL_NEXT(& pDesc->lruList ); } return NULL;found: return (pDesc ); }/********************************************************************************* dcacheBlockGet - get a disc block in a cache block** This function is code which is common for reading and writing bytewise* as well as reading blockwise.* NOTE: The cbio_mutex must already be taken when entering this function.*/LOCAL DCACHE_DESC * dcacheBlockGet( CBIO_DEV_ID dev, block_t block, cookie_t *cookie, BOOL readData ) { DCACHE_DESC *pDesc = NULL ; BOOL allocated = FALSE ; STATUS stat; /* First, verify that cookie is valid, otherwise destroy it */ if( cookie != NULL ) if( *cookie != 0) { /* these sanity tests are not needed after debugging is complete */ assert( ((caddr_t) *cookie >= dev->cbio_memBase) && ((caddr_t) *cookie < (dev->cbio_memBase+dev->cbio_memSize))); } /* entering this internal function, we should already own the mutex */ assert( dev->cbio_mutex.semOwner == (void *) taskIdSelf() ); /* try to locate block by cookie if valid */ if( cookie != NULL ) if( *cookie != 0) { pDesc = (void *) *cookie ; if( pDesc->block != block ) { dev->pDc->dc_cookieMisses ++ ; pDesc = NULL; } else { dev->pDc->dc_cookieHits ++ ; return(pDesc); /* * we omitted here making this block MRU, * cookie references should be very fast, * at a minimal risk of loosing this block * earlier then it normally would happened. */ } } /* locate block in LRU list */ if( pDesc == NULL) pDesc = dcacheBlockLocate(dev, block); /* block not found, allocate one */ if( pDesc == NULL) { dev->pDc->dc_lruMisses ++ ; allocated = TRUE ; pDesc = dcacheBlockAllocate(dev, block); /* if that failed, something is basically wrong here */ if (pDesc == NULL ) { return NULL ; } } else { dev->pDc->dc_lruHits ++ ; } /* if this is a write-only operation, -> DIRTY shortcut */ if( ! readData ) { if( pDesc->state != CB_STATE_DIRTY ) dev->pDc->dc_dirtyCount ++ ; pDesc->state = CB_STATE_DIRTY ; } if( cookie != NULL ) { *((void * *)cookie) = (void *) pDesc ; } /* fill block with data from disk if needed */ if ( readData && allocated ) { stat = dcacheBlockFill( dev, pDesc ); if( stat == ERROR) { dcacheHashRemove(dev, pDesc); /* the disk may have been removed */ return NULL ; } assert(pDesc->state == CB_STATE_CLEAN); } /* make this block MRU */ dllRemove( & dev->pDc->dc_LRU, &pDesc->lruList ); dllInsert( & dev->pDc->dc_LRU, NULL, &pDesc->lruList ); if( (pDesc->block == block) ) { return (pDesc); } else { /* this should never happen, unless tunable params are out of sanity */ INFO_MSG("dcacheCbio: dev=%#x cache internal error - starvation %d\n", (u_int) dev, pDesc->block, 0, 0, 0, 0); errno = EAGAIN; return(NULL); } }/********************************************************************************* dcacheBlkRW - Read/Write blocks** This routine transfers between a user buffer and the lower layer CBIO* It is optimized for block transfers. ** dev - the CBIO handle of the device being accessed (from creation routine)* * start_block - the starting block of the transfer operation* * num_blocks - the total number of blocks to transfer* * buffer - address of the memory buffer used for the transfer* * rw - indicates the direction of transfer up or down (READ/WRITE)* * *cookie - pointer to cookie used by upper layer such as dosFsLib(),* it should be preserved.** RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS dcacheBlkRW ( CBIO_DEV_ID dev, block_t start_block, block_t num_blocks, addr_t buffer, enum cbio_rw rw, cookie_t *cookie ) { CBIO_DEV * pDev = (void *) dev ; DCACHE_DESC *pDesc; STATUS stat = OK ; if( TRUE == dev->cbio_readyChanged ) { errno = S_ioLib_DISK_NOT_PRESENT ; return ERROR; } if( (start_block) > pDev->params.cbio_nBlocks || (start_block+num_blocks) > pDev->params.cbio_nBlocks ) { errno = EINVAL; return ERROR; } start_block += pDev->params.cbio_offset; DEBUG_MSG("dcacheBlkRW: blk %d num blocks %d\n", start_block, num_blocks, 0,0,0,0 ); if( semTake( &pDev->cbio_mutex, WAIT_FOREVER) == ERROR ) return ERROR; /* by-pass cache for large transfers */ if( num_blocks > pDev->pDc->dc_bypassCount ) { BOOL doFlush = (rw == CBIO_READ)? TRUE : FALSE ; BOOL doInval = (rw == CBIO_WRITE)? TRUE : FALSE ; /* BEGIN - Hidden write handling */ if( dev->pDc->dc_lastAccBlock < start_block ) { stat = dcacheManyFlushInval( dev, dev->pDc->dc_lastAccBlock, start_block, TRUE, FALSE, & dev->pDc->dc_writesHidden ); } if( stat == ERROR) goto read_error; /* END - Hidden write handling */ stat = dcacheManyFlushInval( dev, start_block, start_block + num_blocks -1 , doFlush, doInval, & pDev->pDc->dc_writesHidden ); if( stat == OK ) { stat = dcacheBlkBypassRW( dev, start_block, num_blocks, buffer, rw); semGive(&pDev->cbio_mutex); return( stat ) ; } } for( ; num_blocks > 0; num_blocks-- ) /* For each block req'ed */ { /* skip reading back the data if writing entire blocks */ BOOL readData = (rw == CBIO_READ)? TRUE : FALSE ; CB_STATE saveState ; /* get that block */ pDesc = dcacheBlockGet(pDev, start_block, cookie, readData); if( pDesc == NULL ) goto read_error ; /* Debug: make sure the block still has got the data */ assert( (pDesc->state == CB_STATE_CLEAN) || (pDesc->state == CB_STATE_DIRTY) ); /* move data between the cached block and caller's buffer */ switch( rw ) { case CBIO_READ: bcopy( pDesc->data, buffer, pDev->params.cbio_bytesPerBlk ); break; case CBIO_WRITE: saveState = pDesc->state ; pDesc->state = CB_STATE_UNSTABLE ; bcopy( buffer, pDesc->data, pDev->params.cbio_bytesPerBlk ); /* in case it was already CLEAN, we mark it DIRTY, * so that it will be written to disk again. */ if( saveState != CB_STATE_DIRTY ) dev->pDc->dc_dirtyCount ++ ; pDesc->state = CB_STATE_DIRTY ; break; } /* switch */ start_block ++ ; /* prepare for next */ buffer += pDev->params.cbio_bytesPerBlk ; } /* end of: For each block req'ed */ if( dev->pDc->dc_dirtyCount > dev->pDc->dc_dirtyMax ) stat = dcacheManyFlushInval( pDev, 0, NONE, TRUE, FALSE, & pDev->pDc->dc_writesForeground ); semGive(&pDev->cbio_mutex); return stat;read_error: semGive(&pDev->cbio_mutex); return ERROR; }/********************************************************************************* dcacheBytesRW - Read/Write bytes** This routine transfers between a user buffer and the lower layer hardware* It is optimized for byte transfers. ** dev - the CBIO handle of the device being accessed (from creation routine)* * start_block - the starting block of the transfer operation* * offset - offset in bytes from the beginning of the starting block* * buffer - address of the memory buffer used for the transfer* * nBytes - number of bytes to transfer* * rw - indicates the direction of transfer up or down (READ/WRITE)* * *cookie - pointer to cookie used by upper layer such as dosFsLib(),* it should be preserved.* * RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS dcacheBytesRW ( CBIO_DEV_ID dev, block_t start_block, off_t offset, addr_t buffer, size_t nBytes, enum cbio_rw rw, cookie_t *cookie ) { FAST CBIO_DEV * pDev = (void *) dev ; FAST struct dcache_ctrl * pDc = dev->pDc ; FAST DCACHE_DESC * pDesc; BOOL readData = TRUE; /* read data from disk, always */ STATUS stat = OK ; CB_STATE saveState ; if( TRUE == pDev->cbio_readyChanged ) { errno = S_ioLib_DISK_NOT_PRESENT ; return ERROR; } if( (start_block) > pDev->params.cbio_nBlocks ) { errno = EINVAL; return ERROR; } /* verify that all bytes are within one block range */ if (((offset + nBytes) > pDev->params.cbio_bytesPerBlk ) || (offset <0) || (nBytes <=0)) { errno = EINVAL; return ERROR; } start_block += pDev->params.cbio_offset; DEBUG_MSG("dcacheBytesRW: blk %d num bytes %d, offset %d\n", start_block, nBytes, offset, 0,0,0 ); if( semTake( &pDev->cbio_mutex, WAIT_FOREVER) == ERROR ) return ERROR; /* get that block */ pDesc = dcacheBlockGet(pDev, start_block, cookie, readData); if( pDesc == NULL ) goto _error ; /* Debug: make sure the block still has got the data */ assert( (pDesc->state == CB_STATE_CLEAN) || (pDesc->state == CB_STATE_DIRTY) ); /* move data between the cached block and caller's buffer */ switch( rw ) { case CBIO_READ: bcopy( pDesc->data+offset, buffer, nBytes); break; case CBIO_WRITE: saveState = pDesc->state ; pDesc->state = CB_STATE_UNSTABLE ; bcopy( buffer, pDesc->data+offset, nBytes); if( saveState != CB_STATE_DIRTY ) pDc->dc_dirtyCount ++ ; pDesc->state = CB_STATE_DIRTY; break; } /* switch */ if( pDc->dc_dirtyCount > pDc->dc_dirtyMax ) stat = dcacheManyFlushInval( pDev, 0, NONE, TRUE, FALSE, & pDev->pDc->dc_writesForeground ); semGive(&pDev->cbio_mutex); return stat;_error: semGive(&pDev->cbio_mutex); return ERROR; }/********************************************************************************* dcacheBlkCopy - Copy sectors ** This function will be mainly used to write backup copies of FAT,* hence we may assume the the source blocks are in the cache anyway,* and we assume the requests are never too big.** This routine makes copies of one or more blocks on the lower layer CBIO* It is optimized for block copies on the subordinate layer. * dev - the CBIO handle of the device being accessed (from creation routine)* * src_block - source start block of the copy* * dst_block - destination start block of the copy* * num_block - number of blocks to copy** RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS dcacheBlkCopy ( CBIO_DEV_ID dev, block_t src_block, block_t dst_block, block_t num_blocks ) { CBIO_DEV *pDev = (void *) dev ; DCACHE_DESC *pDescSrc, *pDescDst ; CB_STATE saveState ; if( TRUE == dev->cbio_readyChanged ) { errno = S_ioLib_DISK_NOT_PRESENT ; return ERROR; } if( (src_block) > pDev->params.cbio_nBlocks || (dst_block) > pDev->params.cbio_nBlocks ) { errno = EINVAL; return ERROR; } if( (src_block+num_blocks) > pDev->params.cbio_nBlocks || (dst_block+num_blocks) > pDev->params.cbio_nBlocks ) { errno = EINVAL; return ERROR; } src_block += pDev->params.cbio_offset; dst_block += pDev->params.cbio_offset; DEBUG_MSG("dcacheBlkCopy: blk %d to %d # %d blocks\n", src_block, dst_block, num_blocks, 0, 0,0 ); if( semTake( &pDev->cbio_mutex, WAIT_FOREVER) == ERROR ) return ERROR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -