175 lines
2.8 KiB
C
175 lines
2.8 KiB
C
#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...");*/
|
|
return 0;
|
|
}
|
|
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);
|
|
}
|