123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- #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;
- }
|