9 * We used to use 100 i/o buffers of size 2kb (Sectorsize).
10 * Unfortunately, reading 2kb at a time often hopping around
11 * the disk doesn't let us get near the disk bandwidth.
13 * Based on a trace of iobuf address accesses taken while
14 * tarring up a Plan 9 distribution CD, we now use 16 128kb
15 * buffers. This works for ISO9660 because data is required
16 * to be laid out contiguously; effectively we're doing agressive
17 * readahead. Because the buffers are so big and the typical
18 * disk accesses so concentrated, it's okay that we have so few
21 * If this is used to access multiple discs at once, it's not clear
22 * how gracefully the scheme degrades, but I'm not convinced
23 * it's worth worrying about. -rsc
26 #define BUFPERCLUST 64 /* sectors/cluster; 64*Sectorsize = 128kb */
31 static Ioclust* iohead;
32 static Ioclust* iotail;
34 static Ioclust* getclust(Xdata*, long, ulong);
35 static void putclust(Ioclust*);
36 static void xread(Ioclust*);
46 n = nclust*sizeof(Ioclust) +
47 nclust*BUFPERCLUST*(sizeof(Iobuf)+Sectorsize);
50 panic(0, "iobuf_init");
53 for(i=0; i<nclust; i++){
55 mem += sizeof(Ioclust);
58 * on a iso filesystem, data is usually layed out sequentially
59 * but directory information is at the end of the disk. to avoid
60 * evicting directory information when reading large sequential
61 * files, we keep them tagged in the cache. for now, we use
62 * an 8th of the clusters for meta data.
64 c->tag = i <= (nclust/8);
75 mem += BUFPERCLUST*sizeof(Iobuf);
77 mem += BUFPERCLUST*Sectorsize;
78 for(j=0; j<BUFPERCLUST; j++){
82 b->iobuf = c->iobuf+j*Sectorsize;
92 for(p=iohead; p!=nil; p=p->next)
100 getclust(Xdata *dev, long addr, ulong tag)
105 for(c=iohead; c; c=c->next){
106 if(!c->busy && c->tag == tag)
108 if(c->addr == addr && c->dev == dev){
115 panic(0, "out of buffers");
121 f->addr = -1; /* stop caching */
137 /* Link onto head for LRU */
140 c->prev->next = c->next;
143 c->next->prev = c->prev;
154 getbuf(Xdata *dev, ulong addr, ulong tag)
159 off = addr%BUFPERCLUST;
160 c = getclust(dev, addr - off, tag);
163 error("I/O read error");
181 seek(dev->dev, (vlong)c->addr * Sectorsize, 0);
182 n = readn(dev->dev, c->iobuf, BUFPERCLUST*Sectorsize);
184 error("I/O read error");
185 c->nbuf = n/Sectorsize;