1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* Buffered I/O functions. By cacheing the most recently used blocks,
* we can cut WAAY down on disk traffic...
*/
static int bio_fd = -1;
static int bio_counter = 0;
static int bio_blocksize = 0;
struct bio_buf {
int blkno;
int last_access;
int dirty;
char * data;
};
#define NBUFS 32
struct bio_buf buflist[NBUFS];
/* initialize the buffer cache. Blow away anything that may
* have been previously cached...
*/
void
binit(int fd, int blocksize)
{
int i;
bio_fd = fd;
bio_blocksize = blocksize;
for(i = 0; i < NBUFS; i++) {
buflist[i].blkno = 0;
if(buflist[i].data) {
free(buflist[i].data);
}
buflist[i].data = 0;
buflist[i].last_access = 0;
buflist[i].dirty = 0;
}
}
/* Flush out any dirty blocks */
void
bflush(void)
{
int i;
for(i = 0; i < NBUFS; i++) {
if(buflist[i].dirty) {
#ifdef BIO_DEBUG
printf("bflush: writing block %d\n", buflist[i].blkno);
#endif
lseek(bio_fd, buflist[i].blkno * bio_blocksize, 0);
write(bio_fd, buflist[i].data, bio_blocksize);
buflist[i].dirty = 0;
}
}
}
/* Read a block. */
void
bread(int blkno, void * blkbuf)
{
int i;
int lowcount;
int lowcount_buf;
/* First, see if the block is already in memory... */
for(i = 0; i < NBUFS; i++) {
if(buflist[i].blkno == blkno) {
/* Got it! Bump the access count and return. */
buflist[i].last_access = ++bio_counter;
#ifdef BIO_DEBUG
printf("bread: buffer hit on block %d\n", blkno);
#endif
memcpy(blkbuf, buflist[i].data, bio_blocksize);
return;
}
}
/* Not in memory; need to find a buffer and read it in. */
lowcount = buflist[0].last_access;
lowcount_buf = 0;
for(i = 1; i < NBUFS; i++) {
if(buflist[i].last_access < lowcount) {
lowcount = buflist[i].last_access;
lowcount_buf = i;
}
}
/* If the buffer is dirty, we need to write it out... */
if(buflist[lowcount_buf].dirty) {
#ifdef BIO_DEBUG
printf("bread: recycling dirty buffer %d for block %d\n",
lowcount_buf, buflist[lowcount_buf].blkno);
#endif
lseek(bio_fd, buflist[lowcount_buf].blkno * bio_blocksize, 0);
write(bio_fd, buflist[lowcount_buf].data, bio_blocksize);
buflist[lowcount_buf].dirty = 0;
}
#ifdef BIO_DEBUG
printf("bread: Using buffer %d for block %d\n", lowcount_buf, blkno);
#endif
buflist[lowcount_buf].blkno = blkno;
if(!buflist[lowcount_buf].data) {
buflist[lowcount_buf].data = (char *)malloc(bio_blocksize);
}
lseek(bio_fd, blkno * bio_blocksize, 0);
if(read(bio_fd,buflist[lowcount_buf].data,bio_blocksize)!=bio_blocksize) {
perror("bread: I/O error");
}
buflist[lowcount_buf].last_access = ++bio_counter;
memcpy(blkbuf, buflist[lowcount_buf].data, bio_blocksize);
}
/* Write a block */
void
bwrite(int blkno, void * blkbuf)
{
int i;
int lowcount;
int lowcount_buf;
/* First, see if the block is already in memory... */
for(i = 0; i < NBUFS; i++) {
if(buflist[i].blkno == blkno) {
/* Got it! Bump the access count and return. */
#ifdef BIO_DEBUG
printf("bwrite: buffer hit on block %d\n", blkno);
#endif
buflist[i].last_access = ++bio_counter;
memcpy(buflist[i].data, blkbuf, bio_blocksize);
buflist[i].dirty = 1;
return;
}
}
/* Not in memory; need to find a buffer and stuff it. */
lowcount = buflist[0].last_access;
lowcount_buf = 0;
for(i = 1; i < NBUFS; i++) {
if(buflist[i].last_access < lowcount) {
lowcount = buflist[i].last_access;
lowcount_buf = i;
}
}
/* If the buffer is dirty, we need to write it out... */
if(buflist[lowcount_buf].dirty) {
#ifdef BIO_DEBUG
printf("bwrite: recycling dirty buffer %d for block %d\n",
lowcount_buf, buflist[lowcount_buf].blkno);
#endif
lseek(bio_fd, buflist[lowcount_buf].blkno * bio_blocksize, 0);
write(bio_fd, buflist[lowcount_buf].data, bio_blocksize);
buflist[lowcount_buf].dirty = 0;
}
#ifdef BIO_DEBUG
printf("bwrite: Using buffer %d for block %d\n", lowcount_buf, blkno);
#endif
buflist[lowcount_buf].blkno = blkno;
if(!buflist[lowcount_buf].data) {
buflist[lowcount_buf].data = (char *)malloc(bio_blocksize);
}
buflist[lowcount_buf].last_access = ++bio_counter;
memcpy(buflist[lowcount_buf].data, blkbuf, bio_blocksize);
buflist[lowcount_buf].dirty = 1;
}
|