Changeset View
Changeset View
Standalone View
Standalone View
head/stand/common/bcache.c
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | |||||
static u_int bcache_bcount; | static u_int bcache_bcount; | ||||
static u_int bcache_rablks; | static u_int bcache_rablks; | ||||
#define BHASH(bc, blkno) ((blkno) & ((bc)->bcache_nblks - 1)) | #define BHASH(bc, blkno) ((blkno) & ((bc)->bcache_nblks - 1)) | ||||
#define BCACHE_LOOKUP(bc, blkno) \ | #define BCACHE_LOOKUP(bc, blkno) \ | ||||
((bc)->bcache_ctl[BHASH((bc), (blkno))].bc_blkno != (blkno)) | ((bc)->bcache_ctl[BHASH((bc), (blkno))].bc_blkno != (blkno)) | ||||
#define BCACHE_READAHEAD 256 | #define BCACHE_READAHEAD 256 | ||||
#define BCACHE_MINREADAHEAD 32 | #define BCACHE_MINREADAHEAD 32 | ||||
#define BCACHE_MARKER 0xdeadbeef | |||||
static void bcache_invalidate(struct bcache *bc, daddr_t blkno); | static void bcache_invalidate(struct bcache *bc, daddr_t blkno); | ||||
static void bcache_insert(struct bcache *bc, daddr_t blkno); | static void bcache_insert(struct bcache *bc, daddr_t blkno); | ||||
static void bcache_free_instance(struct bcache *bc); | static void bcache_free_instance(struct bcache *bc); | ||||
/* | /* | ||||
* Initialise the cache for (nblks) of (bsize). | * Initialise the cache for (nblks) of (bsize). | ||||
*/ | */ | ||||
Show All 20 Lines | |||||
} | } | ||||
void * | void * | ||||
bcache_allocate(void) | bcache_allocate(void) | ||||
{ | { | ||||
u_int i; | u_int i; | ||||
struct bcache *bc = malloc(sizeof (struct bcache)); | struct bcache *bc = malloc(sizeof (struct bcache)); | ||||
int disks = bcache_numdev; | int disks = bcache_numdev; | ||||
uint32_t *marker; | |||||
if (disks == 0) | if (disks == 0) | ||||
disks = 1; /* safe guard */ | disks = 1; /* safe guard */ | ||||
if (bc == NULL) { | if (bc == NULL) { | ||||
errno = ENOMEM; | errno = ENOMEM; | ||||
return (bc); | return (bc); | ||||
} | } | ||||
/* | /* | ||||
* the bcache block count must be power of 2 for hash function | * the bcache block count must be power of 2 for hash function | ||||
*/ | */ | ||||
i = fls(disks) - 1; /* highbit - 1 */ | i = fls(disks) - 1; /* highbit - 1 */ | ||||
if (disks > (1 << i)) /* next power of 2 */ | if (disks > (1 << i)) /* next power of 2 */ | ||||
i++; | i++; | ||||
bc->bcache_nblks = bcache_total_nblks >> i; | bc->bcache_nblks = bcache_total_nblks >> i; | ||||
bcache_unit_nblks = bc->bcache_nblks; | bcache_unit_nblks = bc->bcache_nblks; | ||||
bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize + | bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize); | ||||
sizeof(uint32_t)); | |||||
if (bc->bcache_data == NULL) { | if (bc->bcache_data == NULL) { | ||||
/* dont error out yet. fall back to 32 blocks and try again */ | /* dont error out yet. fall back to 32 blocks and try again */ | ||||
bc->bcache_nblks = 32; | bc->bcache_nblks = 32; | ||||
bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize + | bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize + | ||||
sizeof(uint32_t)); | sizeof(uint32_t)); | ||||
} | } | ||||
bc->bcache_ctl = malloc(bc->bcache_nblks * sizeof(struct bcachectl)); | bc->bcache_ctl = malloc(bc->bcache_nblks * sizeof(struct bcachectl)); | ||||
if ((bc->bcache_data == NULL) || (bc->bcache_ctl == NULL)) { | if ((bc->bcache_data == NULL) || (bc->bcache_ctl == NULL)) { | ||||
bcache_free_instance(bc); | bcache_free_instance(bc); | ||||
errno = ENOMEM; | errno = ENOMEM; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* Insert cache end marker. */ | |||||
marker = (uint32_t *)(bc->bcache_data + bc->bcache_nblks * bcache_blksize); | |||||
*marker = BCACHE_MARKER; | |||||
/* Flush the cache */ | /* Flush the cache */ | ||||
for (i = 0; i < bc->bcache_nblks; i++) { | for (i = 0; i < bc->bcache_nblks; i++) { | ||||
bc->bcache_ctl[i].bc_count = -1; | bc->bcache_ctl[i].bc_count = -1; | ||||
bc->bcache_ctl[i].bc_blkno = -1; | bc->bcache_ctl[i].bc_blkno = -1; | ||||
} | } | ||||
bcache_units++; | bcache_units++; | ||||
bc->ra = BCACHE_READAHEAD; /* optimistic read ahead */ | bc->ra = BCACHE_READAHEAD; /* optimistic read ahead */ | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | read_strategy(void *devdata, int rw, daddr_t blk, size_t size, | ||||
char *buf, size_t *rsize) | char *buf, size_t *rsize) | ||||
{ | { | ||||
struct bcache_devdata *dd = (struct bcache_devdata *)devdata; | struct bcache_devdata *dd = (struct bcache_devdata *)devdata; | ||||
struct bcache *bc = dd->dv_cache; | struct bcache *bc = dd->dv_cache; | ||||
size_t i, nblk, p_size, r_size, complete, ra; | size_t i, nblk, p_size, r_size, complete, ra; | ||||
int result; | int result; | ||||
daddr_t p_blk; | daddr_t p_blk; | ||||
caddr_t p_buf; | caddr_t p_buf; | ||||
uint32_t *marker; | |||||
if (bc == NULL) { | if (bc == NULL) { | ||||
errno = ENODEV; | errno = ENODEV; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
marker = (uint32_t *)(bc->bcache_data + bc->bcache_nblks * bcache_blksize); | |||||
if (rsize != NULL) | if (rsize != NULL) | ||||
*rsize = 0; | *rsize = 0; | ||||
nblk = size / bcache_blksize; | nblk = size / bcache_blksize; | ||||
if (nblk == 0 && size != 0) | if (nblk == 0 && size != 0) | ||||
nblk++; | nblk++; | ||||
result = 0; | result = 0; | ||||
complete = 1; | complete = 1; | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | if (BCACHE_LOOKUP(bc, (daddr_t)(blk + i))) | ||||
} | } | ||||
if (size > i * bcache_blksize) | if (size > i * bcache_blksize) | ||||
size = i * bcache_blksize; | size = i * bcache_blksize; | ||||
if (size != 0) { | if (size != 0) { | ||||
bcopy(bc->bcache_data + (bcache_blksize * BHASH(bc, blk)), buf, size); | bcopy(bc->bcache_data + (bcache_blksize * BHASH(bc, blk)), buf, size); | ||||
result = 0; | result = 0; | ||||
} | |||||
if (*marker != BCACHE_MARKER) { | |||||
printf("BUG: bcache corruption detected: nblks: %zu p_blk: %lu, " | |||||
"p_size: %zu, ra: %zu\n", bc->bcache_nblks, | |||||
(long unsigned)BHASH(bc, p_blk), p_size, ra); | |||||
} | } | ||||
done: | done: | ||||
if ((result == 0) && (rsize != NULL)) | if ((result == 0) && (rsize != NULL)) | ||||
*rsize = size; | *rsize = size; | ||||
return(result); | return(result); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 139 Lines • Show Last 20 Lines |