FreeBSD/sys/boot/common/bcache.c
/* 
 * Requests larger than 1/2 cache size will be bypassed and go
 * directly to the disk.  XXX tune this.
 */
Requests larger than 1/2 cache size will be bypassed and go
directly to the disk.  XXX tune this.
Requests larger than 1 / 2 cache size will be bypassed and go directly to the disk . XXX tune this .
int
bcache_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
    size_t size, char *buf, size_t *rsize)
{
    struct bcache_devdata	*dd = (struct bcache_devdata *)devdata;
    struct bcache		*bc = dd->dv_cache;
    u_int bcache_nblks = 0;
    int nblk, cblk, ret;
    size_t csize, isize, total;
    bcache_ops++;
    if (bc != NULL)
	bcache_nblks = bc->bcache_nblks;
    if (bc == NULL ||
	(offset == 0 && ((size * 2 / bcache_blksize) > bcache_nblks))) {
	DEBUG("bypass %d from %d", size / bcache_blksize, blk);
	bcache_bypasses++;
	return (dd->dv_strategy(dd->dv_devdata, rw, blk, offset, size, buf,
	    rsize));
    }
    while (offset >= bcache_blksize) {
	blk++;
	offset -= bcache_blksize;
    }
    switch (rw) {
    case F_READ:
	nblk = size / bcache_blksize;
	if (offset || (size != 0 && nblk == 0))
	    nblk++;	
	ret = 0;
	total = 0;
	while(size) {
	    cblk = bcache_nblks - BHASH(bc, blk); 
	    cblk = MIN(cblk, nblk);
	    if (size <= bcache_blksize)
		csize = size;
	    else {
		csize = cblk * bcache_blksize;
		if (offset)
		    csize -= (bcache_blksize - offset);
	    }
	    ret = read_strategy(devdata, rw, blk, offset,
		csize, buf+total, &isize);
	    if (ret != 0 || isize == 0) {
		if (total != 0)
		    ret = 0;
		break;
	    }
	    blk += (offset+isize) / bcache_blksize;
	    offset = 0;
	    total += isize;
	    size -= isize;
	    nblk = size / bcache_blksize;
	}
	if (rsize)
	    *rsize = total;
	return (ret);
    case F_WRITE:
	return write_strategy(devdata, rw, blk, offset, size, buf, rsize);
    }
    return -1;
}
int bcache_strategy ( void * devdata , int rw , daddr_t blk , size_t offset , size_t size , char * buf , size_t * rsize ) { struct bcache_devdata * dd = ( struct bcache_devdata * ) devdata ; struct bcache * bc = dd -> dv_cache ; u_int bcache_nblks = 0 ; int nblk , cblk , ret ; size_t csize , isize , total ; bcache_ops ++ ; if ( bc != NULL ) bcache_nblks = bc -> bcache_nblks ; if ( bc == NULL || ( offset == 0 && ( ( size * 2 / bcache_blksize ) > bcache_nblks ) ) ) { DEBUG ( " " , size / bcache_blksize , blk ) ; bcache_bypasses ++ ; return ( dd -> dv_strategy ( dd -> dv_devdata , rw , blk , offset , size , buf , rsize ) ) ; } while ( offset >= bcache_blksize ) { blk ++ ; offset -= bcache_blksize ; } switch ( rw ) { case F_READ : nblk = size / bcache_blksize ; if ( offset || ( size != 0 && nblk == 0 ) ) nblk ++ ; ret = 0 ; total = 0 ; while ( size ) { cblk = bcache_nblks - BHASH ( bc , blk ) ; cblk = MIN ( cblk , nblk ) ; if ( size <= bcache_blksize ) csize = size ; else { csize = cblk * bcache_blksize ; if ( offset ) csize -= ( bcache_blksize - offset ) ; } ret = read_strategy ( devdata , rw , blk , offset , csize , buf + total , & isize ) ; if ( ret != 0 || isize == 0 ) { if ( total != 0 ) ret = 0 ; break ; } blk += ( offset + isize ) / bcache_blksize ; offset = 0 ; total += isize ; size -= isize ; nblk = size / bcache_blksize ; } if ( rsize ) * rsize = total ; return ( ret ) ; case F_WRITE : return write_strategy ( devdata , rw , blk , offset , size , buf , rsize ) ; } return -1 ; }
Requests larger than 1/2 cache size will be bypassed and go
 directly to the disk.
Requests larger than 1 / 2 cache size will be bypassed and go directly to the disk .
/* bypass large requests, or when the cache is inactive */ /* normalize offset */ /* read at least one block */ /* # of blocks left */ /*
	     * we may have error from read ahead, if we have read some data
	     * return partial read.
	     */