⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcachecbio.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
📖 第 1 页 / 共 5 页
字号:
	{ logMsg(fmt,a1,a2,a3,a4,a5,a6); }#include "assert.h"/********************************************************************************* dcacheDevCreate - Create a disk cache** This routine creates a disk cache unit. * The disk cache unit accesses the disk through the subordinate CBIO* device driver, provided with the <subDev> argument.** A valid block device handle may be provided instead of a CBIO* handle, in which case it will be automatically converted into* a CBIO device by using the wrapper functionality from cbioLib.** Memory which will be used for caching disk data may be provided by the* caller with <ramAddr>, or it will be allocated by dcacheDevCreate() from* the common system memory pool, if <memAddr> is passed as NULL. <memSize> is* the amount of memory to use for disk caching, if 0 is passed, then a* certain default value will be calculated, based on available memory.* <description> is a string describing the device, used later by* dcacheShow(), and is useful when there are many cached disk devices.** A maximum of 16 disk cache devices are supported at this time.* * RETURNS: disk cache device handle, or NULL if there is not enough* memory to satisfy the request, or the <blkDev> handle is invalid.** INTERNAL* There is not an appropriate Destroy function at this time.*/CBIO_DEV_ID dcacheDevCreate    (    CBIO_DEV_ID  subDev,  /* block device handle */    char  *   ramAddr,    /* where it is in memory (NULL = malloc)  */    int       memSize,	  /* amount of memory to use                */    char *    description /* device description string */    )    {    CBIO_DEV *	pDev = NULL ;    CBIO_DEV *	pSubDev = NULL ;    int i ;    pSubDev = cbioDevVerify( subDev, FALSE ) ;    if(pSubDev == NULL)	{	return NULL; 	/* failed */	}    /* Fill in defaults for args with 0 value */    if( memSize == 0)	memSize = min( memFindMax()/16, 188*1024 ) ;    cbioLibInit();	/* just in case */    if( cbioClassId->createRtn != NULL )	pDev = (CBIO_DEV_ID) cbioClassId->createRtn( ramAddr, memSize );    if( pDev == NULL )	return( NULL ); /* failed */    pDev->pDc			= NULL ;    /* cbioFuncs is staticly allocated in each driver. */    pDev->pFuncs = &cbioFuncs;    /* mutex is not created yet */    taskLock();    /* allocate extension control structure */    for(i = (int) 0; i < (int) NELEMENTS(dcacheCtrl); i++)	{	if( dcacheCtrl[i].cbio_dev == NULL )	    {	    pDev->pDc = & dcacheCtrl[i] ;	    break;	    }	}    if( pDev->pDc == NULL )	{	taskUnlock();		/* FIXME - if too many devs, mem leak */	errno = ENODEV;	return NULL;	}    bzero( (caddr_t) pDev->pDc, sizeof(struct dcache_ctrl));    /* backward connect the cbio device */    pDev->pDc->cbio_dev = pDev ;    taskUnlock();    /* connect the underlying block driver */    pDev->pDc->dc_subDev	= pSubDev ;    if( description != NULL )	pDev->pDc->dc_desc 	= strdup(description) ;    else	pDev->pDc->dc_desc 	= "" ;    dacacheDevInit( pDev );    /* Create the Updater task if not already created */    if( dcacheUpdTaskId == 0 )	{	dcacheUpdTaskId = taskSpawn(		"tDcacheUpd",		dcacheUpdTaskPriority,		dcacheUpdTaskOptions,		dcacheUpdTaskStack,		(FUNCPTR) dcacheUpd,		0,0,0,0,0,0,0,0,0,0) ;	}    /* return device handle */    return( pDev );    }/******************************************************************************** * dcacheErrorHandler - handle I/O errors and device changes** INTERNAL** Error handling here are performed with the assumption that* any possible recovery was already performed by the driver, i.e. retries,* corrections, maybe even reassignments.* This means there is not much we can do at this level.* Still, most errors are probably due to device change, which* is not limited to strictly removable devices, as hard drives* that appear Fixed are in fact hot swappable in some environments.** Other issues such as mapping a sectors as BAD in the FAT, or Bad* Block Reassignment (SCSI) will be left to the Utilities to handle,* e.g. Surface Scan is the way to do such mappings.** RETURNS: the return value will mean if the disk cache should* continue operation, or abort the current operation and return* an ERROR to the file system.**/LOCAL STATUS dcacheErrorHandler    (    CBIO_DEV_ID dev,    DCACHE_DESC * pDesc,     enum cbio_rw rw    )    {    STATUS stat = ERROR ; /* OK means cache may continue, ERROR - abort */    static char errorMsgTemplate[] =	"disk cache error: device %x block %d errno %x, %s\n" ;    /* record this errno */    dev->params.cbio_lastErrno = errno ;    /* record the block # where error occurred */    if( pDesc != NULL )	dev->params.cbio_lastErrBlk = pDesc->block ;    else	dev->params.cbio_lastErrBlk = NONE ;    DEBUG_MSG( "disk cache error: errno=%x, block=%x, removable=%s, "    	    "readyChanged=%s\n",	    dev->params.cbio_lastErrno,	    dev->params.cbio_lastErrBlk,	    (int) (dev->pDc->dc_subDev->params.cbio_removable)?"Yes":"No",	    (int) (dev->pDc->dc_subDev->cbio_readyChanged)?"Yes":"No", 0, 0	    );    /* now shall we see if the error was due to device removal */    /* first, let us assume the driver has set the flag */    if( TRUE == dev->pDc->dc_subDev->cbio_readyChanged )	{	stat = ERROR ;	dev->cbio_readyChanged = TRUE ;	}    /* next, we will double-check if the device is ready */    else 	{	stat = dev->pDc->dc_subDev->pFuncs->cbio_ioctl(			dev->pDc->dc_subDev, CBIO_STATUS_CHK, 0);	if( stat == ERROR )	    dev->cbio_readyChanged = TRUE ;	}    /* so if the reason was device removal, stop right here */    if( TRUE == dev->cbio_readyChanged )	{	/* override errno for removed disk */	errno = S_ioLib_DISK_NOT_PRESENT ;	/* dont issue warning for read errors on removal, only for writes */	if( rw == CBIO_WRITE )	    {	    /* write error, issue warning to the console */	    INFO_MSG(errorMsgTemplate,		    (int) dev,		    dev->params.cbio_lastErrBlk,		    dev->params.cbio_lastErrno,		    (int) "disk removed while writing data, probable data loss",		    0,0		    );	    }	return(ERROR);	}    /* at this point, it is a certain block which is causing this error */    /* override errno if not set by driver */    if( errno == 0 )	errno = S_ioLib_DEVICE_ERROR ;    if( rw == CBIO_READ )	{	INFO_MSG(errorMsgTemplate,		(int) dev,		dev->params.cbio_lastErrBlk,		dev->params.cbio_lastErrno,		(int) "disk read failed",		0,0		);	return(ERROR);	}    else	{	/*	 * this policy will be questioned for some time to come	 */	INFO_MSG(errorMsgTemplate,		(int) dev,		dev->params.cbio_lastErrBlk,		dev->params.cbio_lastErrno,		(int) "disk write failed, data loss may have occurred",		0,0		);	return(ERROR);	}    /*NOTREACH*/    }/******************************************************************************** * dcacheBlockCksum - calculate a checksum signature for a cache block** calculate a 32-bit signature for a block, using a permuted-shift checksum*/LOCAL u_long dcacheBlockCksum( CBIO_DEV_ID dev, DCACHE_DESC *pDesc )    {    FAST u_long cksum = 0 ;    FAST int i ;    FAST u_short *p ;    p = (ushort *) pDesc->data ;    i = dev->params.cbio_bytesPerBlk >> 1 ;    for( ; i > 0 ; i -- )	cksum += *p++ << (i & 0x3) ;    return( cksum );    }/******************************************************************************** * dcacheHashRemove - remove a block desc from hash table**/LOCAL void dcacheHashRemove ( CBIO_DEV_ID dev, DCACHE_DESC *pDesc )    {    FAST DCACHE_DESC *pTmp = NULL ;    FAST DCACHE_DESC **pHashSlot ;    FAST struct dcache_ctrl * pDc = dev->pDc ;    if( pDesc->state != CB_STATE_EMPTY && pDc->dc_hashSize != 0 )	{	/* empty blocks are not expected to be in hash, or no hash table */	pHashSlot = &(pDc->dc_hashBase [			pDesc->block % pDc->dc_hashSize ]);	pTmp = *pHashSlot ;	if( pTmp == pDesc )	    {	    *pHashSlot = pTmp->hashNext ;	    }	else 	    {	    while( pTmp != NULL )		{		if( pTmp->hashNext == pDesc )		    {		    pTmp->hashNext = pDesc->hashNext;		    break;		    }		pTmp = pTmp->hashNext ;		}	    }	}    /* assert that we did not fail to find in hash unless has is void */    assert( (pTmp != NULL) == (pDc->dc_hashSize > 0) );    pDesc->busy = 0;    pDesc->block = NONE ;    pDesc->state = CB_STATE_EMPTY ;    pDesc->hashNext = NULL ;    }/******************************************************************************** * dcacheChangeDetect - detect a possible disk change** This will return ERROR and set cbio_readyChanged to TRUE* if a change in the boot block's checksum is detected.*/LOCAL STATUS dcacheChangeDetect ( CBIO_DEV_ID dev, BOOL invalidate )    {    DCACHE_DESC *pDesc ;    block_t bootBlockNum = DCACHE_BOOT_BLOCK_NUM ;    FAST u_long cksum ;    DEBUG_MSG("change detect, idle was %d ms\n",	1000 * (tickGet() - dev->pDc->dc_actTick)/sysClkRateGet(),	0,0,0,0,0);    dev->pDc->dc_actTick = tickGet() ;        pDesc = dcacheBlockGet(dev, bootBlockNum, NULL, /*readData=*/ TRUE);    if( pDesc == NULL )	return ERROR ;    if( pDesc->state != CB_STATE_CLEAN )	{	return OK;	}    else if ((pDesc->state == CB_STATE_CLEAN) && invalidate )	{	/* invalidate the boot block to read it from disk */	dcacheHashRemove(dev, pDesc);	}    cksum = dcacheBlockCksum( dev, pDesc );    if ( dev->pDc->dc_diskSignature != cksum )	{	DEBUG_MSG("disk changed, signature old %x, new %x\n",		dev->pDc->dc_diskSignature, cksum, 0,0,0,0 );	dev->cbio_readyChanged = TRUE ;	dev->pDc->dc_diskSignature = cksum ;	errno = S_ioLib_DISK_NOT_PRESENT ;	return ERROR ;	}    return OK ;    }/******************************************************************************** * dcacheListAddSort - add descriptor to a sorted list**/LOCAL void dcacheListAddSort( DL_LIST * pList, DCACHE_DESC * pDesc )    {    FAST DCACHE_DESC * pTmp = NULL ;    if( DLL_EMPTY( pList ))	{	dllAdd( pList, &pDesc->lruList );	return;	}    /* start at the tail */    for( pTmp = (DCACHE_DESC *) DLL_LAST(pList) ; pTmp != NULL ;		pTmp = (DCACHE_DESC *) DLL_PREVIOUS( pTmp ) )	{	if( pTmp->block < pDesc->block )	    {	    /* insert before pTmp */	    dllInsert( pList,  &pTmp->lruList,  &pDesc->lruList );	    return;	    }	}    /* else it should be first */    dllInsert( pList, NULL,  &pDesc->lruList );    return;    }/******************************************************************************** * dcacheFlushBatch - flush a batch of sorted blocks to disk **/LOCAL STATUS dcacheFlushBatch    (    CBIO_DEV_ID dev,    DL_LIST * pList,    BOOL doInvalidate    )    {    FAST DCACHE_DESC * pTmp, * pContig  ;    FAST struct dcache_ctrl * pDc = dev->pDc ;    STATUS ret, retstat = OK ;    u_long burstCount, ix ;    caddr_t pData ;    if ( dev->params.cbio_removable && (pDc->dc_actTick <			tickGet() - sysClkRateGet() * DCACHE_IDLE_SECS ))	{	if( dcacheChangeDetect( dev, FALSE ) == ERROR )	    return ERROR;	}    for( pTmp = (DCACHE_DESC *) DLL_FIRST(pList) ; pTmp != NULL ;		pTmp = (DCACHE_DESC *) DLL_FIRST(pList) )	{	pContig = pTmp ;	for(burstCount = 1 ; burstCount <= pDc->dc_BigBufSize; burstCount++)	    {	    pContig =  (DCACHE_DESC *) DLL_NEXT( pContig );	    if( pContig == NULL )		break ;	    if( pContig->block != (pTmp->block + burstCount) )		break ;	    } /*for burstCount */	if( burstCount == 1 )	    {	    /* non-contiguous block, write directly from cache block */	    ret = pDc->dc_subDev->pFuncs->cbio_blkRW(		    pDc->dc_subDev,		    pTmp->block, 1,		    pTmp->data, CBIO_WRITE, NULL );	    pDc->dc_lastAccBlock = pTmp->block + 1 ;	    }	else	    {	    /* contiguous burst write */	    /* in case we overcounted */	    burstCount = min(burstCount, pDc->dc_BigBufSize);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -