Blame


1 78a779a3 2008-07-20 rsc #include <u.h>
2 78a779a3 2008-07-20 rsc #include <libc.h>
3 78a779a3 2008-07-20 rsc #include <auth.h>
4 78a779a3 2008-07-20 rsc #include <fcall.h>
5 78a779a3 2008-07-20 rsc #include "dat.h"
6 78a779a3 2008-07-20 rsc #include "fns.h"
7 78a779a3 2008-07-20 rsc
8 78a779a3 2008-07-20 rsc /*
9 78a779a3 2008-07-20 rsc * We used to use 100 i/o buffers of size 2kb (Sectorsize).
10 78a779a3 2008-07-20 rsc * Unfortunately, reading 2kb at a time often hopping around
11 78a779a3 2008-07-20 rsc * the disk doesn't let us get near the disk bandwidth.
12 78a779a3 2008-07-20 rsc *
13 78a779a3 2008-07-20 rsc * Based on a trace of iobuf address accesses taken while
14 78a779a3 2008-07-20 rsc * tarring up a Plan 9 distribution CD, we now use 16 128kb
15 78a779a3 2008-07-20 rsc * buffers. This works for ISO9660 because data is required
16 78a779a3 2008-07-20 rsc * to be laid out contiguously; effectively we're doing agressive
17 fa325e9b 2020-01-10 cross * readahead. Because the buffers are so big and the typical
18 78a779a3 2008-07-20 rsc * disk accesses so concentrated, it's okay that we have so few
19 78a779a3 2008-07-20 rsc * of them.
20 78a779a3 2008-07-20 rsc *
21 78a779a3 2008-07-20 rsc * If this is used to access multiple discs at once, it's not clear
22 78a779a3 2008-07-20 rsc * how gracefully the scheme degrades, but I'm not convinced
23 78a779a3 2008-07-20 rsc * it's worth worrying about. -rsc
24 78a779a3 2008-07-20 rsc */
25 78a779a3 2008-07-20 rsc
26 78a779a3 2008-07-20 rsc /* trying a larger value to get greater throughput - geoff */
27 78a779a3 2008-07-20 rsc #define BUFPERCLUST 256 /* sectors/cluster; was 64, 64*Sectorsize = 128kb */
28 78a779a3 2008-07-20 rsc #define NCLUST 16
29 78a779a3 2008-07-20 rsc
30 78a779a3 2008-07-20 rsc int nclust = NCLUST;
31 78a779a3 2008-07-20 rsc
32 78a779a3 2008-07-20 rsc static Ioclust* iohead;
33 78a779a3 2008-07-20 rsc static Ioclust* iotail;
34 78a779a3 2008-07-20 rsc
35 78a779a3 2008-07-20 rsc static Ioclust* getclust(Xdata*, long);
36 78a779a3 2008-07-20 rsc static void putclust(Ioclust*);
37 78a779a3 2008-07-20 rsc static void xread(Ioclust*);
38 78a779a3 2008-07-20 rsc
39 78a779a3 2008-07-20 rsc void
40 78a779a3 2008-07-20 rsc iobuf_init(void)
41 78a779a3 2008-07-20 rsc {
42 78a779a3 2008-07-20 rsc int i, j, n;
43 78a779a3 2008-07-20 rsc Ioclust *c;
44 78a779a3 2008-07-20 rsc Iobuf *b;
45 78a779a3 2008-07-20 rsc uchar *mem;
46 78a779a3 2008-07-20 rsc
47 78a779a3 2008-07-20 rsc n = nclust*sizeof(Ioclust) +
48 78a779a3 2008-07-20 rsc nclust*BUFPERCLUST*(sizeof(Iobuf)+Sectorsize);
49 310ae033 2017-01-06 rsc mem = malloc(n);
50 310ae033 2017-01-06 rsc if(mem == (void*)0)
51 78a779a3 2008-07-20 rsc panic(0, "iobuf_init");
52 78a779a3 2008-07-20 rsc memset(mem, 0, n);
53 78a779a3 2008-07-20 rsc
54 78a779a3 2008-07-20 rsc for(i=0; i<nclust; i++){
55 78a779a3 2008-07-20 rsc c = (Ioclust*)mem;
56 78a779a3 2008-07-20 rsc mem += sizeof(Ioclust);
57 78a779a3 2008-07-20 rsc c->addr = -1;
58 78a779a3 2008-07-20 rsc c->prev = iotail;
59 78a779a3 2008-07-20 rsc if(iotail)
60 78a779a3 2008-07-20 rsc iotail->next = c;
61 78a779a3 2008-07-20 rsc iotail = c;
62 78a779a3 2008-07-20 rsc if(iohead == nil)
63 78a779a3 2008-07-20 rsc iohead = c;
64 78a779a3 2008-07-20 rsc
65 78a779a3 2008-07-20 rsc c->buf = (Iobuf*)mem;
66 78a779a3 2008-07-20 rsc mem += BUFPERCLUST*sizeof(Iobuf);
67 78a779a3 2008-07-20 rsc c->iobuf = mem;
68 78a779a3 2008-07-20 rsc mem += BUFPERCLUST*Sectorsize;
69 78a779a3 2008-07-20 rsc for(j=0; j<BUFPERCLUST; j++){
70 78a779a3 2008-07-20 rsc b = &c->buf[j];
71 78a779a3 2008-07-20 rsc b->clust = c;
72 78a779a3 2008-07-20 rsc b->addr = -1;
73 78a779a3 2008-07-20 rsc b->iobuf = c->iobuf+j*Sectorsize;
74 78a779a3 2008-07-20 rsc }
75 78a779a3 2008-07-20 rsc }
76 78a779a3 2008-07-20 rsc }
77 78a779a3 2008-07-20 rsc
78 78a779a3 2008-07-20 rsc void
79 78a779a3 2008-07-20 rsc purgebuf(Xdata *dev)
80 78a779a3 2008-07-20 rsc {
81 78a779a3 2008-07-20 rsc Ioclust *p;
82 78a779a3 2008-07-20 rsc
83 78a779a3 2008-07-20 rsc for(p=iohead; p!=nil; p=p->next)
84 78a779a3 2008-07-20 rsc if(p->dev == dev){
85 78a779a3 2008-07-20 rsc p->addr = -1;
86 78a779a3 2008-07-20 rsc p->busy = 0;
87 78a779a3 2008-07-20 rsc }
88 78a779a3 2008-07-20 rsc }
89 78a779a3 2008-07-20 rsc
90 78a779a3 2008-07-20 rsc static Ioclust*
91 78a779a3 2008-07-20 rsc getclust(Xdata *dev, long addr)
92 78a779a3 2008-07-20 rsc {
93 78a779a3 2008-07-20 rsc Ioclust *c, *f;
94 78a779a3 2008-07-20 rsc
95 78a779a3 2008-07-20 rsc f = nil;
96 78a779a3 2008-07-20 rsc for(c=iohead; c; c=c->next){
97 78a779a3 2008-07-20 rsc if(!c->busy)
98 78a779a3 2008-07-20 rsc f = c;
99 78a779a3 2008-07-20 rsc if(c->addr == addr && c->dev == dev){
100 78a779a3 2008-07-20 rsc c->busy++;
101 78a779a3 2008-07-20 rsc return c;
102 78a779a3 2008-07-20 rsc }
103 78a779a3 2008-07-20 rsc }
104 78a779a3 2008-07-20 rsc
105 78a779a3 2008-07-20 rsc if(f == nil)
106 78a779a3 2008-07-20 rsc panic(0, "out of buffers");
107 78a779a3 2008-07-20 rsc
108 78a779a3 2008-07-20 rsc f->addr = addr;
109 78a779a3 2008-07-20 rsc f->dev = dev;
110 78a779a3 2008-07-20 rsc f->busy++;
111 78a779a3 2008-07-20 rsc if(waserror()){
112 78a779a3 2008-07-20 rsc f->addr = -1; /* stop caching */
113 78a779a3 2008-07-20 rsc putclust(f);
114 78a779a3 2008-07-20 rsc nexterror();
115 78a779a3 2008-07-20 rsc }
116 78a779a3 2008-07-20 rsc xread(f);
117 78a779a3 2008-07-20 rsc poperror();
118 78a779a3 2008-07-20 rsc return f;
119 78a779a3 2008-07-20 rsc }
120 78a779a3 2008-07-20 rsc
121 78a779a3 2008-07-20 rsc static void
122 78a779a3 2008-07-20 rsc putclust(Ioclust *c)
123 78a779a3 2008-07-20 rsc {
124 78a779a3 2008-07-20 rsc if(c->busy <= 0)
125 78a779a3 2008-07-20 rsc panic(0, "putbuf");
126 78a779a3 2008-07-20 rsc c->busy--;
127 78a779a3 2008-07-20 rsc
128 78a779a3 2008-07-20 rsc /* Link onto head for LRU */
129 78a779a3 2008-07-20 rsc if(c == iohead)
130 78a779a3 2008-07-20 rsc return;
131 78a779a3 2008-07-20 rsc c->prev->next = c->next;
132 78a779a3 2008-07-20 rsc
133 78a779a3 2008-07-20 rsc if(c->next)
134 78a779a3 2008-07-20 rsc c->next->prev = c->prev;
135 78a779a3 2008-07-20 rsc else
136 78a779a3 2008-07-20 rsc iotail = c->prev;
137 78a779a3 2008-07-20 rsc
138 78a779a3 2008-07-20 rsc c->prev = nil;
139 78a779a3 2008-07-20 rsc c->next = iohead;
140 78a779a3 2008-07-20 rsc iohead->prev = c;
141 78a779a3 2008-07-20 rsc iohead = c;
142 78a779a3 2008-07-20 rsc }
143 78a779a3 2008-07-20 rsc
144 78a779a3 2008-07-20 rsc Iobuf*
145 78a779a3 2008-07-20 rsc getbuf(Xdata *dev, ulong addr)
146 78a779a3 2008-07-20 rsc {
147 78a779a3 2008-07-20 rsc int off;
148 78a779a3 2008-07-20 rsc Ioclust *c;
149 78a779a3 2008-07-20 rsc
150 78a779a3 2008-07-20 rsc off = addr%BUFPERCLUST;
151 78a779a3 2008-07-20 rsc c = getclust(dev, addr - off);
152 78a779a3 2008-07-20 rsc if(c->nbuf < off){
153 78a779a3 2008-07-20 rsc c->busy--;
154 78a779a3 2008-07-20 rsc error("I/O read error");
155 78a779a3 2008-07-20 rsc }
156 78a779a3 2008-07-20 rsc return &c->buf[off];
157 78a779a3 2008-07-20 rsc }
158 78a779a3 2008-07-20 rsc
159 78a779a3 2008-07-20 rsc void
160 78a779a3 2008-07-20 rsc putbuf(Iobuf *b)
161 78a779a3 2008-07-20 rsc {
162 78a779a3 2008-07-20 rsc putclust(b->clust);
163 78a779a3 2008-07-20 rsc }
164 78a779a3 2008-07-20 rsc
165 78a779a3 2008-07-20 rsc static void
166 78a779a3 2008-07-20 rsc xread(Ioclust *c)
167 78a779a3 2008-07-20 rsc {
168 78a779a3 2008-07-20 rsc int n;
169 78a779a3 2008-07-20 rsc Xdata *dev;
170 78a779a3 2008-07-20 rsc
171 78a779a3 2008-07-20 rsc dev = c->dev;
172 78a779a3 2008-07-20 rsc seek(dev->dev, (vlong)c->addr * Sectorsize, 0);
173 78a779a3 2008-07-20 rsc n = readn(dev->dev, c->iobuf, BUFPERCLUST*Sectorsize);
174 78a779a3 2008-07-20 rsc if(n < Sectorsize)
175 78a779a3 2008-07-20 rsc error("I/O read error");
176 78a779a3 2008-07-20 rsc c->nbuf = n/Sectorsize;
177 78a779a3 2008-07-20 rsc }