123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- #include <u.h>
- #include <libc.h>
- #include <fcall.h>
- #include <thread.h>
- #include <9p.h>
- #include "dat.h"
- #include "fns.h"
- #define NIOBUF 100
- #define HIOB (NIOBUF/3)
- static Iobuf* hiob[HIOB]; /* hash buckets */
- static Iobuf iobuf[NIOBUF]; /* buffer headers */
- static Iobuf* iohead;
- static Iobuf* iotail;
- Iobuf*
- getbuf(Xfs *dev, long addr)
- {
- Iobuf *p, *h, **l, **f;
- l = &hiob[addr%HIOB];
- for(p = *l; p; p = p->hash) {
- if(p->addr == addr && p->dev == dev) {
- p->busy++;
- return p;
- }
- }
- /* Find a non-busy buffer from the tail */
- for(p = iotail; p && (p->busy > 0); p = p->prev)
- ;
- if(!p)
- panic("all buffers busy");
- if(p->dirty){
- xwrite(p);
- p->dirty = 0;
- }
- if( xread(dev, p, addr) < 0)
- return 0;
- /* Delete from hash chain */
- f = &hiob[p->addr%HIOB];
- if( *f == p )
- *f = p->hash;
- else {
- for(h = *f; h ; h = h->hash)
- if( h->hash == p ){
- h->hash = p->hash;
- break;
- }
- }
- /* Fill and hash */
- p->hash = *l;
- *l = p;
- p->addr = addr;
- p->dev = dev;
- p->busy=1;
- return p;
- }
- void
- putbuf(Iobuf *p)
- {
- if(p->busy <= 0)
- panic("putbuf");
- p->busy--;
- /* Link onto head for lru */
- if(p == iohead)
- return;
- if( p == iotail ){
- p->prev->next = 0;
- iotail = p->prev;
- }else{
- p->prev->next = p->next;
- p->next->prev = p->prev;
- }
- p->prev = 0;
- p->next = iohead;
- iohead->prev = p;
- iohead = p;
- }
- void
- dirtybuf(Iobuf *p)
- {
- if(p->busy <=0)
- panic("dirtybuf");
- p->dirty = 1;
- }
- void
- syncbuf(void)
- {
- Iobuf *p;
- for(p=&iobuf[0] ; p<&iobuf[NIOBUF]; p++)
- if( p->dirty ){
- xwrite(p);
- p->dirty = 0;
- }
- }
- void
- purgebuf(Xfs *dev)
- {
- Iobuf *p;
- for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++)
- if(p->dev == dev)
- p->busy = 0;
- /* Blow hash chains */
- memset(hiob, 0, sizeof(hiob));
- }
- void
- iobuf_init(void)
- {
- Iobuf *p;
- iohead = iobuf;
- iotail = iobuf+NIOBUF-1;
- for(p = iobuf; p <= iotail; p++) {
- p->next = p+1;
- p->prev = p-1;
-
- p->iobuf = (char *)malloc(EXT2_MAX_BLOCK_SIZE);
- if(p->iobuf == 0)
- panic("iobuf_init");
- }
- iohead->prev = 0;
- iotail->next = 0;
- }
- int
- xread(Xfs *dev, Iobuf *p, long addr)
- {
- /*chat("xread %d,%d...", dev->dev, addr);*/
- seek(dev->dev, (vlong)addr*dev->block_size, 0);
- if( read(dev->dev, p->iobuf, dev->block_size) != dev->block_size){
- chat("xread %d, block=%d failed ...", dev->dev, addr);
- errno = Eio;
- return -1;
- }
- /*chat("xread ok...");*/
- }
- void
- xwrite(Iobuf *p)
- {
- Xfs *dev;
- long addr;
- dev = p->dev;
- addr = p->addr;
- /*chat("xwrite %d,%d...", dev->dev, addr);*/
- seek(dev->dev, (vlong)addr*dev->block_size, 0);
- if(write(dev->dev, p->iobuf, dev->block_size) != dev->block_size){
- chat("xwrite %d, block=%d failed ...", dev->dev, addr);
- errno = Eio;
- return;
- }
- /*chat("xwrite ok...");*/
- }
- void
- dumpbuf(void)
- {
- Iobuf *p;
-
- for(p = iotail; p ; p = p->prev)
- if( p->busy )
- mchat("\nHi ERROR buf(%x, %d, %d)\n", p, p->addr, p->busy);
- }
|