Blame


1 a0d146ed 2005-07-12 devnull /*
2 a0d146ed 2005-07-12 devnull * Write the dirty icache entries to disk. Random seeks are
3 a0d146ed 2005-07-12 devnull * so expensive that it makes sense to wait until we have
4 a0d146ed 2005-07-12 devnull * a lot and then just make a sequential pass over the disk.
5 a0d146ed 2005-07-12 devnull */
6 a0d146ed 2005-07-12 devnull #include "stdinc.h"
7 a0d146ed 2005-07-12 devnull #include "dat.h"
8 a0d146ed 2005-07-12 devnull #include "fns.h"
9 a0d146ed 2005-07-12 devnull
10 a0d146ed 2005-07-12 devnull static void icachewriteproc(void*);
11 a0d146ed 2005-07-12 devnull static void icachewritecoord(void*);
12 a0d146ed 2005-07-12 devnull static IEntry *iesort(IEntry*);
13 a0d146ed 2005-07-12 devnull
14 a0d146ed 2005-07-12 devnull int icachesleeptime = 1000; /* milliseconds */
15 a0d146ed 2005-07-12 devnull
16 a0d146ed 2005-07-12 devnull enum
17 a0d146ed 2005-07-12 devnull {
18 a0d146ed 2005-07-12 devnull Bufsize = 8*1024*1024
19 a0d146ed 2005-07-12 devnull };
20 a0d146ed 2005-07-12 devnull
21 a0d146ed 2005-07-12 devnull typedef struct IWrite IWrite;
22 a0d146ed 2005-07-12 devnull struct IWrite
23 a0d146ed 2005-07-12 devnull {
24 a0d146ed 2005-07-12 devnull Round round;
25 a0d146ed 2005-07-12 devnull AState as;
26 a0d146ed 2005-07-12 devnull };
27 a0d146ed 2005-07-12 devnull
28 a0d146ed 2005-07-12 devnull static IWrite iwrite;
29 a0d146ed 2005-07-12 devnull
30 a0d146ed 2005-07-12 devnull void
31 a0d146ed 2005-07-12 devnull initicachewrite(void)
32 a0d146ed 2005-07-12 devnull {
33 a0d146ed 2005-07-12 devnull int i;
34 a0d146ed 2005-07-12 devnull Index *ix;
35 a0d146ed 2005-07-12 devnull
36 a0d146ed 2005-07-12 devnull initround(&iwrite.round, "icache", 120*60*1000);
37 a0d146ed 2005-07-12 devnull ix = mainindex;
38 a0d146ed 2005-07-12 devnull for(i=0; i<ix->nsects; i++){
39 a0d146ed 2005-07-12 devnull ix->sects[i]->writechan = chancreate(sizeof(ulong), 1);
40 a0d146ed 2005-07-12 devnull ix->sects[i]->writedonechan = chancreate(sizeof(ulong), 1);
41 a0d146ed 2005-07-12 devnull vtproc(icachewriteproc, ix->sects[i]);
42 a0d146ed 2005-07-12 devnull }
43 a0d146ed 2005-07-12 devnull vtproc(icachewritecoord, nil);
44 a0d146ed 2005-07-12 devnull vtproc(delaykickroundproc, &iwrite.round);
45 a0d146ed 2005-07-12 devnull }
46 a0d146ed 2005-07-12 devnull
47 a0d146ed 2005-07-12 devnull static IEntry*
48 a0d146ed 2005-07-12 devnull nextchunk(Index *ix, ISect *is, IEntry **pie, u64int *paddr, uint *pnbuf)
49 a0d146ed 2005-07-12 devnull {
50 a0d146ed 2005-07-12 devnull u64int addr, naddr;
51 a0d146ed 2005-07-12 devnull uint nbuf;
52 a0d146ed 2005-07-12 devnull int bsize;
53 a0d146ed 2005-07-12 devnull IEntry *iefirst, *ie, **l;
54 a0d146ed 2005-07-12 devnull
55 a0d146ed 2005-07-12 devnull bsize = 1<<is->blocklog;
56 a0d146ed 2005-07-12 devnull iefirst = *pie;
57 a0d146ed 2005-07-12 devnull addr = is->blockbase + ((u64int)(hashbits(iefirst->score, 32) / ix->div - is->start) << is->blocklog);
58 a0d146ed 2005-07-12 devnull nbuf = 0;
59 a0d146ed 2005-07-12 devnull for(l=&iefirst->nextdirty; (ie=*l)!=nil; l=&(*l)->nextdirty){
60 a0d146ed 2005-07-12 devnull naddr = is->blockbase + ((u64int)(hashbits(ie->score, 32) / ix->div - is->start) << is->blocklog);
61 a0d146ed 2005-07-12 devnull if(naddr - addr >= Bufsize)
62 a0d146ed 2005-07-12 devnull break;
63 a0d146ed 2005-07-12 devnull nbuf = naddr-addr;
64 a0d146ed 2005-07-12 devnull }
65 a0d146ed 2005-07-12 devnull nbuf += bsize;
66 a0d146ed 2005-07-12 devnull
67 a0d146ed 2005-07-12 devnull *l = nil;
68 a0d146ed 2005-07-12 devnull *pie = ie;
69 a0d146ed 2005-07-12 devnull *paddr = addr;
70 a0d146ed 2005-07-12 devnull *pnbuf = nbuf;
71 a0d146ed 2005-07-12 devnull return iefirst;
72 a0d146ed 2005-07-12 devnull }
73 a0d146ed 2005-07-12 devnull
74 a0d146ed 2005-07-12 devnull static int
75 a0d146ed 2005-07-12 devnull icachewritesect(Index *ix, ISect *is, u8int *buf)
76 a0d146ed 2005-07-12 devnull {
77 a0d146ed 2005-07-12 devnull int err, h, bsize;
78 a0d146ed 2005-07-12 devnull u32int lo, hi;
79 a0d146ed 2005-07-12 devnull u64int addr, naddr;
80 a0d146ed 2005-07-12 devnull uint nbuf, off;
81 a0d146ed 2005-07-12 devnull DBlock *b;
82 a0d146ed 2005-07-12 devnull IBucket ib;
83 a0d146ed 2005-07-12 devnull IEntry *ie, *iedirty, **l, *chunk;
84 a0d146ed 2005-07-12 devnull
85 a0d146ed 2005-07-12 devnull lo = is->start * ix->div;
86 a0d146ed 2005-07-12 devnull if(TWID32/ix->div < is->stop)
87 a0d146ed 2005-07-12 devnull hi = TWID32;
88 a0d146ed 2005-07-12 devnull else
89 a0d146ed 2005-07-12 devnull hi = is->stop * ix->div - 1;
90 a0d146ed 2005-07-12 devnull
91 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritesect enter %ud %ud %llud", lo, hi, iwrite.as.aa);
92 a0d146ed 2005-07-12 devnull
93 a0d146ed 2005-07-12 devnull iedirty = icachedirty(lo, hi, iwrite.as.aa);
94 a0d146ed 2005-07-12 devnull iedirty = iesort(iedirty);
95 a0d146ed 2005-07-12 devnull bsize = 1<<is->blocklog;
96 a0d146ed 2005-07-12 devnull err = 0;
97 a0d146ed 2005-07-12 devnull
98 a0d146ed 2005-07-12 devnull while(iedirty){
99 a0d146ed 2005-07-12 devnull sleep(icachesleeptime);
100 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritesect nextchunk");
101 a0d146ed 2005-07-12 devnull chunk = nextchunk(ix, is, &iedirty, &addr, &nbuf);
102 a0d146ed 2005-07-12 devnull
103 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritesect readpart 0x%llux+0x%ux", addr, nbuf);
104 a0d146ed 2005-07-12 devnull if(readpart(is->part, addr, buf, nbuf) < 0){
105 a0d146ed 2005-07-12 devnull // XXX
106 a0d146ed 2005-07-12 devnull fprint(2, "icachewriteproc readpart: %r\n");
107 a0d146ed 2005-07-12 devnull err = -1;
108 a0d146ed 2005-07-12 devnull continue;
109 a0d146ed 2005-07-12 devnull }
110 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritesect updatebuf");
111 a0d146ed 2005-07-12 devnull addstat(StatIsectReadBytes, nbuf);
112 a0d146ed 2005-07-12 devnull addstat(StatIsectRead, 1);
113 a0d146ed 2005-07-12 devnull
114 a0d146ed 2005-07-12 devnull for(l=&chunk; (ie=*l)!=nil; l=&ie->nextdirty){
115 a0d146ed 2005-07-12 devnull again:
116 a0d146ed 2005-07-12 devnull naddr = is->blockbase + ((u64int)(hashbits(ie->score, 32) / ix->div - is->start) << is->blocklog);
117 a0d146ed 2005-07-12 devnull off = naddr - addr;
118 a0d146ed 2005-07-12 devnull if(off+bsize > nbuf){
119 a0d146ed 2005-07-12 devnull fprint(2, "whoops! addr=0x%llux nbuf=%ud addr+nbuf=0x%llux naddr=0x%llux\n",
120 a0d146ed 2005-07-12 devnull addr, nbuf, addr+nbuf, naddr);
121 a0d146ed 2005-07-12 devnull assert(off+bsize <= nbuf);
122 a0d146ed 2005-07-12 devnull }
123 a0d146ed 2005-07-12 devnull unpackibucket(&ib, buf+off, is->bucketmagic);
124 a0d146ed 2005-07-12 devnull if(okibucket(&ib, is) < 0){
125 a0d146ed 2005-07-12 devnull fprint(2, "bad bucket XXX\n");
126 a0d146ed 2005-07-12 devnull goto skipit;
127 a0d146ed 2005-07-12 devnull }
128 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritesect add %V at 0x%llux", ie->score, naddr);
129 a0d146ed 2005-07-12 devnull h = bucklook(ie->score, ie->ia.type, ib.data, ib.n);
130 a0d146ed 2005-07-12 devnull if(h & 1){
131 a0d146ed 2005-07-12 devnull h ^= 1;
132 a0d146ed 2005-07-12 devnull packientry(ie, &ib.data[h]);
133 a0d146ed 2005-07-12 devnull }else if(ib.n < is->buckmax){
134 a0d146ed 2005-07-12 devnull memmove(&ib.data[h+IEntrySize], &ib.data[h], ib.n*IEntrySize - h);
135 a0d146ed 2005-07-12 devnull ib.n++;
136 a0d146ed 2005-07-12 devnull packientry(ie, &ib.data[h]);
137 a0d146ed 2005-07-12 devnull }else{
138 a0d146ed 2005-07-12 devnull fprint(2, "bucket overflow XXX\n");
139 a0d146ed 2005-07-12 devnull skipit:
140 a0d146ed 2005-07-12 devnull err = -1;
141 a0d146ed 2005-07-12 devnull *l = ie->nextdirty;
142 a0d146ed 2005-07-12 devnull ie = *l;
143 a0d146ed 2005-07-12 devnull if(ie)
144 a0d146ed 2005-07-12 devnull goto again;
145 a0d146ed 2005-07-12 devnull else
146 a0d146ed 2005-07-12 devnull break;
147 a0d146ed 2005-07-12 devnull }
148 a0d146ed 2005-07-12 devnull packibucket(&ib, buf+off, is->bucketmagic);
149 a0d146ed 2005-07-12 devnull if((b = _getdblock(is->part, naddr, ORDWR, 0)) != nil){
150 a0d146ed 2005-07-12 devnull memmove(b->data, buf+off, bsize);
151 a0d146ed 2005-07-12 devnull putdblock(b);
152 a0d146ed 2005-07-12 devnull }
153 a0d146ed 2005-07-12 devnull }
154 a0d146ed 2005-07-12 devnull
155 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritesect writepart", addr, nbuf);
156 a0d146ed 2005-07-12 devnull if(writepart(is->part, addr, buf, nbuf) < 0){
157 a0d146ed 2005-07-12 devnull // XXX
158 a0d146ed 2005-07-12 devnull fprint(2, "icachewriteproc writepart: %r\n");
159 a0d146ed 2005-07-12 devnull err = -1;
160 a0d146ed 2005-07-12 devnull continue;
161 a0d146ed 2005-07-12 devnull }
162 a0d146ed 2005-07-12 devnull addstat(StatIsectWriteBytes, nbuf);
163 a0d146ed 2005-07-12 devnull addstat(StatIsectWrite, 1);
164 a0d146ed 2005-07-12 devnull icacheclean(chunk);
165 a0d146ed 2005-07-12 devnull }
166 a0d146ed 2005-07-12 devnull
167 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritesect done");
168 a0d146ed 2005-07-12 devnull return err;
169 a0d146ed 2005-07-12 devnull }
170 a0d146ed 2005-07-12 devnull
171 a0d146ed 2005-07-12 devnull static void
172 a0d146ed 2005-07-12 devnull icachewriteproc(void *v)
173 a0d146ed 2005-07-12 devnull {
174 a0d146ed 2005-07-12 devnull uint bsize;
175 a0d146ed 2005-07-12 devnull ISect *is;
176 a0d146ed 2005-07-12 devnull Index *ix;
177 a0d146ed 2005-07-12 devnull u8int *buf;
178 a0d146ed 2005-07-12 devnull
179 a0d146ed 2005-07-12 devnull ix = mainindex;
180 a0d146ed 2005-07-12 devnull is = v;
181 a0d146ed 2005-07-12 devnull threadsetname("icachewriteproc:%s", is->part->name);
182 a0d146ed 2005-07-12 devnull
183 a0d146ed 2005-07-12 devnull bsize = 1<<is->blocklog;
184 a0d146ed 2005-07-12 devnull buf = emalloc(Bufsize+bsize);
185 a0d146ed 2005-07-12 devnull buf = (u8int*)(((ulong)buf+bsize-1)&~(ulong)(bsize-1));
186 a0d146ed 2005-07-12 devnull
187 a0d146ed 2005-07-12 devnull for(;;){
188 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewriteproc recv");
189 a0d146ed 2005-07-12 devnull recv(is->writechan, 0);
190 a0d146ed 2005-07-12 devnull trace(TraceWork, "start");
191 a0d146ed 2005-07-12 devnull icachewritesect(ix, is, buf);
192 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewriteproc send");
193 a0d146ed 2005-07-12 devnull trace(TraceWork, "finish");
194 a0d146ed 2005-07-12 devnull send(is->writedonechan, 0);
195 a0d146ed 2005-07-12 devnull }
196 a0d146ed 2005-07-12 devnull }
197 a0d146ed 2005-07-12 devnull
198 a0d146ed 2005-07-12 devnull static void
199 a0d146ed 2005-07-12 devnull icachewritecoord(void *v)
200 a0d146ed 2005-07-12 devnull {
201 a0d146ed 2005-07-12 devnull int i;
202 a0d146ed 2005-07-12 devnull Index *ix;
203 a0d146ed 2005-07-12 devnull AState as;
204 a0d146ed 2005-07-12 devnull
205 a0d146ed 2005-07-12 devnull USED(v);
206 a0d146ed 2005-07-12 devnull
207 a0d146ed 2005-07-12 devnull threadsetname("icachewritecoord");
208 a0d146ed 2005-07-12 devnull
209 a0d146ed 2005-07-12 devnull ix = mainindex;
210 a0d146ed 2005-07-12 devnull iwrite.as = diskstate();
211 a0d146ed 2005-07-12 devnull
212 a0d146ed 2005-07-12 devnull for(;;){
213 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritecoord sleep");
214 a0d146ed 2005-07-12 devnull waitforkick(&iwrite.round);
215 a0d146ed 2005-07-12 devnull trace(TraceWork, "start");
216 a0d146ed 2005-07-12 devnull as = diskstate();
217 a0d146ed 2005-07-12 devnull if(as.arena==iwrite.as.arena && as.aa==iwrite.as.aa){
218 a0d146ed 2005-07-12 devnull /* will not be able to do anything more than last flush - kick disk */
219 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritecoord flush dcache");
220 a0d146ed 2005-07-12 devnull kickdcache();
221 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritecoord flushed dcache");
222 a0d146ed 2005-07-12 devnull }
223 a0d146ed 2005-07-12 devnull iwrite.as = as;
224 a0d146ed 2005-07-12 devnull
225 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritecoord start flush");
226 a0d146ed 2005-07-12 devnull if(iwrite.as.arena){
227 a0d146ed 2005-07-12 devnull for(i=0; i<ix->nsects; i++)
228 a0d146ed 2005-07-12 devnull send(ix->sects[i]->writechan, 0);
229 a0d146ed 2005-07-12 devnull if(ix->bloom)
230 a0d146ed 2005-07-12 devnull send(ix->bloom->writechan, 0);
231 a0d146ed 2005-07-12 devnull
232 a0d146ed 2005-07-12 devnull for(i=0; i<ix->nsects; i++)
233 a0d146ed 2005-07-12 devnull recv(ix->sects[i]->writedonechan, 0);
234 a0d146ed 2005-07-12 devnull if(ix->bloom)
235 a0d146ed 2005-07-12 devnull recv(ix->bloom->writedonechan, 0);
236 a0d146ed 2005-07-12 devnull
237 a0d146ed 2005-07-12 devnull trace(TraceProc, "icachewritecoord donewrite");
238 a0d146ed 2005-07-12 devnull setatailstate(&iwrite.as);
239 a0d146ed 2005-07-12 devnull }
240 a0d146ed 2005-07-12 devnull icacheclean(nil); /* wake up anyone waiting */
241 a0d146ed 2005-07-12 devnull trace(TraceWork, "finish");
242 a0d146ed 2005-07-12 devnull addstat(StatIcacheFlush, 1);
243 a0d146ed 2005-07-12 devnull }
244 a0d146ed 2005-07-12 devnull }
245 a0d146ed 2005-07-12 devnull
246 a0d146ed 2005-07-12 devnull void
247 a0d146ed 2005-07-12 devnull flushicache(void)
248 a0d146ed 2005-07-12 devnull {
249 a0d146ed 2005-07-12 devnull trace(TraceProc, "flushicache enter");
250 a0d146ed 2005-07-12 devnull kickround(&iwrite.round, 1);
251 a0d146ed 2005-07-12 devnull trace(TraceProc, "flushicache exit");
252 a0d146ed 2005-07-12 devnull }
253 a0d146ed 2005-07-12 devnull
254 a0d146ed 2005-07-12 devnull void
255 a0d146ed 2005-07-12 devnull kickicache(void)
256 a0d146ed 2005-07-12 devnull {
257 a0d146ed 2005-07-12 devnull kickround(&iwrite.round, 0);
258 a0d146ed 2005-07-12 devnull }
259 a0d146ed 2005-07-12 devnull
260 a0d146ed 2005-07-12 devnull void
261 a0d146ed 2005-07-12 devnull delaykickicache(void)
262 a0d146ed 2005-07-12 devnull {
263 a0d146ed 2005-07-12 devnull delaykickround(&iwrite.round);
264 a0d146ed 2005-07-12 devnull }
265 a0d146ed 2005-07-12 devnull
266 a0d146ed 2005-07-12 devnull static IEntry*
267 a0d146ed 2005-07-12 devnull iesort(IEntry *ie)
268 a0d146ed 2005-07-12 devnull {
269 a0d146ed 2005-07-12 devnull int cmp;
270 a0d146ed 2005-07-12 devnull IEntry **l;
271 a0d146ed 2005-07-12 devnull IEntry *ie1, *ie2, *sorted;
272 a0d146ed 2005-07-12 devnull
273 a0d146ed 2005-07-12 devnull if(ie == nil || ie->nextdirty == nil)
274 a0d146ed 2005-07-12 devnull return ie;
275 a0d146ed 2005-07-12 devnull
276 a0d146ed 2005-07-12 devnull /* split the lists */
277 a0d146ed 2005-07-12 devnull ie1 = ie;
278 a0d146ed 2005-07-12 devnull ie2 = ie;
279 a0d146ed 2005-07-12 devnull if(ie2)
280 a0d146ed 2005-07-12 devnull ie2 = ie2->nextdirty;
281 a0d146ed 2005-07-12 devnull if(ie2)
282 a0d146ed 2005-07-12 devnull ie2 = ie2->nextdirty;
283 a0d146ed 2005-07-12 devnull while(ie1 && ie2){
284 a0d146ed 2005-07-12 devnull ie1 = ie1->nextdirty;
285 a0d146ed 2005-07-12 devnull ie2 = ie2->nextdirty;
286 a0d146ed 2005-07-12 devnull if(ie2)
287 a0d146ed 2005-07-12 devnull ie2 = ie2->nextdirty;
288 a0d146ed 2005-07-12 devnull }
289 a0d146ed 2005-07-12 devnull if(ie1){
290 a0d146ed 2005-07-12 devnull ie2 = ie1->nextdirty;
291 a0d146ed 2005-07-12 devnull ie1->nextdirty = nil;
292 a0d146ed 2005-07-12 devnull }
293 a0d146ed 2005-07-12 devnull
294 a0d146ed 2005-07-12 devnull /* sort the lists */
295 a0d146ed 2005-07-12 devnull ie1 = iesort(ie);
296 a0d146ed 2005-07-12 devnull ie2 = iesort(ie2);
297 a0d146ed 2005-07-12 devnull
298 a0d146ed 2005-07-12 devnull /* merge the lists */
299 a0d146ed 2005-07-12 devnull sorted = nil;
300 a0d146ed 2005-07-12 devnull l = &sorted;
301 a0d146ed 2005-07-12 devnull cmp = 0;
302 a0d146ed 2005-07-12 devnull while(ie1 || ie2){
303 a0d146ed 2005-07-12 devnull if(ie1 && ie2)
304 a0d146ed 2005-07-12 devnull cmp = scorecmp(ie1->score, ie2->score);
305 a0d146ed 2005-07-12 devnull if(ie1==nil || (ie2 && cmp > 0)){
306 a0d146ed 2005-07-12 devnull *l = ie2;
307 a0d146ed 2005-07-12 devnull l = &ie2->nextdirty;
308 a0d146ed 2005-07-12 devnull ie2 = ie2->nextdirty;
309 a0d146ed 2005-07-12 devnull }else{
310 a0d146ed 2005-07-12 devnull *l = ie1;
311 a0d146ed 2005-07-12 devnull l = &ie1->nextdirty;
312 a0d146ed 2005-07-12 devnull ie1 = ie1->nextdirty;
313 a0d146ed 2005-07-12 devnull }
314 a0d146ed 2005-07-12 devnull }
315 a0d146ed 2005-07-12 devnull *l = nil;
316 a0d146ed 2005-07-12 devnull return sorted;
317 a0d146ed 2005-07-12 devnull }
318 a0d146ed 2005-07-12 devnull