2 #include "../port/lib.h"
6 #include "../port/error.h"
11 NFILE = 4093, /* should be prime */
12 MAXCACHE = 8*1024*1024,
14 MAPBITS = 8*sizeof(ulong),
15 NBITMAP = (PGROUND(MAXCACHE)/BY2PG + MAPBITS-1) / MAPBITS,
18 typedef struct Mntcache Mntcache;
30 /* page bitmap of valid pages */
31 ulong bitmap[NBITMAP];
34 typedef struct Cache Cache;
41 Mntcache *hash[NHASH];
54 m = xalloc(sizeof(Mntcache)*NFILE);
56 panic("cinit: no memory");
61 for(i = 0; i < NFILE-1; i++) {
68 cache.tail->next = nil;
69 cache.head->prev = nil;
75 cacheaddr(Mntcache *m, ulong pn)
77 uintptr da = pn * NFILE + (m - cache.alloc);
78 return (da << PGSHIFT) | (da >> (sizeof(da)*8 - PGSHIFT));
84 memset(m->bitmap, 0, sizeof(m->bitmap));
90 /* Unlink and send to the tail */
92 m->prev->next = m->next;
96 m->next->prev = m->prev;
100 if(cache.tail != nil) {
101 m->prev = cache.tail;
102 cache.tail->next = m;
114 /* called with cache locked */
116 clookup(Chan *c, int skipvers)
120 for(m = cache.hash[c->qid.path%NHASH]; m != nil; m = m->hash)
121 if(eqchantdqid(c, m->type, m->dev, m->qid, skipvers) && c->qid.type == m->qid.type)
130 Mntcache *m, *f, **l;
132 /* directories aren't cacheable and append-only files confuse us */
133 if(c->qid.type&(QTDIR|QTAPPEND)){
142 else if(m->qid.vers == c->qid.vers) {
150 l = &cache.hash[m->qid.path%NHASH];
151 for(f = *l; f != nil; f = f->hash) {
166 * someone got there first while cache lock
167 * was released and added a updated Mntcache
168 * for us. update LRU and use it.
182 l = &cache.hash[c->qid.path%NHASH];
191 /* return locked Mntcache if still valid else reset mcp */
200 if(eqchantdqid(c, m->type, m->dev, m->qid, 0) && c->qid.type == m->qid.type)
209 VABITS = 8*sizeof(uintptr) - 2*PGSHIFT,
210 VAMASK = (((uintptr)1 << VABITS)-1) << PGSHIFT,
214 cpage(Mntcache *m, ulong pn, ulong *po, ulong *pe)
219 b = 1 << (pn%MAPBITS);
220 if((m->bitmap[pn/MAPBITS] & b) == 0)
222 p = lookpage(&fscache, cacheaddr(m, pn));
224 m->bitmap[pn/MAPBITS] &= ~b;
227 *po = p->va & (BY2PG-1);
228 *pe = 1 + (p->va >> (PGSHIFT+VABITS));
234 cpageset(Page *p, ulong po, ulong pe)
237 p->va = po | (p->va & VAMASK) | ((uintptr)pe - 1) << (PGSHIFT+VABITS);
241 cread(Chan *c, uchar *buf, int len, vlong off)
247 ulong offset, pn, po, pe;
249 if(off >= MAXCACHE || len <= 0)
259 if(offset+len > MAXCACHE)
260 len = MAXCACHE - offset;
265 p = cpage(m, pn, &po, &pe);
268 if(offset < po || offset >= pe){
283 memmove(buf, (uchar*)VA(k) + offset, l);
305 /* invalidate pages in page bitmap */
307 invalidate(Mntcache *m, ulong offset, int len)
311 for(pn = offset/BY2PG; len > 0; pn++, len -= BY2PG)
312 m->bitmap[pn/MAPBITS] &= ~(1 << (pn%MAPBITS));
315 /* replace buf data from [off, off+len) in the cache or invalidate */
317 cachedata(Mntcache *m, uchar *buf, int len, vlong off)
322 ulong offset, pn, po, pe;
324 if(off >= MAXCACHE || len <= 0){
330 if(offset+len > MAXCACHE)
331 len = MAXCACHE - offset;
339 p = cpage(m, pn, &po, &pe);
341 if(offset > pe || (offset+l) < po){
342 /* cached range not extendable, set new cached range */
346 /* extend cached range */
354 invalidate(m, offset + pn*BY2PG, len);
357 p = newpage(0, nil, pn*BY2PG);
358 p->daddr = cacheaddr(m, pn);
359 cachedel(&fscache, p->daddr);
360 cachepage(p, &fscache);
361 m->bitmap[pn/MAPBITS] |= 1 << (pn%MAPBITS);
372 invalidate(m, offset + pn*BY2PG, len);
376 memmove((uchar*)VA(k) + offset, buf, l);
390 cupdate(Chan *c, uchar *buf, int len, vlong off)
397 cachedata(m, buf, len, off);
401 cwrite(Chan* c, uchar *buf, int len, vlong off)
410 cachedata(m, buf, len, off);