📄 iobuf.c
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include "dat.h"#include "fns.h"/* * We used to use 100 i/o buffers of size 2kb (Sectorsize). * Unfortunately, reading 2kb at a time often hopping around * the disk doesn't let us get near the disk bandwidth. * * Based on a trace of iobuf address accesses taken while * tarring up a Plan 9 distribution CD, we now use 16 128kb * buffers. This works for ISO9660 because data is required * to be laid out contiguously; effectively we're doing agressive * readahead. Because the buffers are so big and the typical * disk accesses so concentrated, it's okay that we have so few * of them. * * If this is used to access multiple discs at once, it's not clear * how gracefully the scheme degrades, but I'm not convinced * it's worth worrying about. -rsc */#define BUFPERCLUST 64 /* 64*Sectorsize = 128kb */#define NCLUST 16static Ioclust* iohead;static Ioclust* iotail;static Ioclust* getclust(Xdata*, long);static void putclust(Ioclust*);static void xread(Ioclust*);voidiobuf_init(void){ int i, j, n; Ioclust *c; Iobuf *b; uchar *mem; n = NCLUST*sizeof(Ioclust)+NCLUST*BUFPERCLUST*(sizeof(Iobuf)+Sectorsize); mem = sbrk(n); if(mem == (void*)-1) panic(0, "iobuf_init"); memset(mem, 0, n); for(i=0; i<NCLUST; i++){ c = (Ioclust*)mem; mem += sizeof(Ioclust); c->addr = -1; c->prev = iotail; if(iotail) iotail->next = c; iotail = c; if(iohead == nil) iohead = c; c->buf = (Iobuf*)mem; mem += BUFPERCLUST*sizeof(Iobuf); c->iobuf = mem; mem += BUFPERCLUST*Sectorsize; for(j=0; j<BUFPERCLUST; j++){ b = &c->buf[j]; b->clust = c; b->addr = -1; b->iobuf = c->iobuf+j*Sectorsize; } }}voidpurgebuf(Xdata *dev){ Ioclust *p; for(p=iohead; p!=nil; p=p->next) if(p->dev == dev){ p->addr = -1; p->busy = 0; }}static Ioclust*getclust(Xdata *dev, long addr){ Ioclust *c, *f; f = nil; for(c=iohead; c; c=c->next){ if(!c->busy) f = c; if(c->addr == addr && c->dev == dev){ c->busy++; return c; } } if(f == nil) panic(0, "out of buffers"); f->addr = addr; f->dev = dev; f->busy++; if(waserror()){ f->addr = -1; /* stop caching */ putclust(f); nexterror(); } xread(f); poperror(); return f;}static voidputclust(Ioclust *c){ if(c->busy <= 0) panic(0, "putbuf"); c->busy--; /* Link onto head for LRU */ if(c == iohead) return; c->prev->next = c->next; if(c->next) c->next->prev = c->prev; else iotail = c->prev; c->prev = nil; c->next = iohead; iohead->prev = c; iohead = c;}Iobuf*getbuf(Xdata *dev, long addr){ int off; Ioclust *c; off = addr%BUFPERCLUST; c = getclust(dev, addr - off); if(c->nbuf < off){ c->busy--; error("I/O read error"); } return &c->buf[off];}voidputbuf(Iobuf *b){ putclust(b->clust);}static voidxread(Ioclust *c){ int n; vlong addr; Xdata *dev; dev = c->dev; addr = c->addr; seek(dev->dev, addr*Sectorsize, 0); n = readn(dev->dev, c->iobuf, BUFPERCLUST*Sectorsize); if(n < Sectorsize) error("I/O read error"); c->nbuf = n/Sectorsize;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -