void cnodata(Mntcache *m) { Extent *e; /* * Invalidate all extent data * Image lru will waste the pages */ while(e = m->list){ m->list = e->next; extentfree(e); } }
void cnodata(Mntcache *m) { Extent *e, *n; /* * Invalidate all extent data * Image lru will waste the pages */ for(e = m->list; e; e = n) { n = e->next; extentfree(e); } m->list = 0; }
void cwrite(Chan* c, uchar *buf, int len, vlong off) { int o, eo; Mntcache *m; ulong eblock, ee; Extent *p, *f, *e, *tail; ulong offset; if(off > maxcache || len == 0) return; m = c->mcp; if(m == 0) return; qlock(m); if(cdev(m, c) == 0) { qunlock(m); return; } offset = off; m->qid.vers++; c->qid.vers++; p = 0; for(f = m->list; f; f = f->next) { if(f->start >= offset) break; p = f; } if(p != 0) { ee = p->start+p->len; eo = offset - p->start; /* pack in predecessor if there is space */ if(offset <= ee && eo < BY2PG) { o = len; if(o > BY2PG - eo) o = BY2PG - eo; if(cpgmove(p, buf, eo, o)) { if(eo+o > p->len) p->len = eo+o; buf += o; len -= o; offset += o; } } } /* free the overlap -- it's a rare case */ eblock = offset+len; while(f && f->start < eblock) { e = f->next; extentfree(f); f = e; } /* link the block (if any) into the middle */ e = cchain(buf, offset, len, &tail); if(e != 0) { tail->next = f; f = e; } if(p == 0) m->list = f; else p->next = f; qunlock(m); }
Extent* cchain(uchar *buf, ulong offset, int len, Extent **tail) { int l; Page *p; KMap *k; Extent *e, *start, **t; start = 0; *tail = 0; t = &start; while(len) { e = extentalloc(); if(e == 0) break; p = auxpage(); if(p == 0) { extentfree(e); break; } l = len; if(l > BY2PG) l = BY2PG; e->cache = p; e->start = offset; e->len = l; qlock(&cache); e->bid = cache.pgno; cache.pgno += BY2PG; /* wrap the counter; low bits are unused by pghash but checked by lookpage */ if((cache.pgno & ~(BY2PG-1)) == 0){ if(cache.pgno == BY2PG-1){ print("cache wrapped\n"); cache.pgno = 0; }else cache.pgno++; } qunlock(&cache); p->daddr = e->bid; k = kmap(p); if(waserror()) { /* buf may be virtual */ kunmap(k); nexterror(); } memmove((void*)VA(k), buf, l); poperror(); kunmap(k); cachepage(p, &fscache); putpage(p); buf += l; offset += l; len -= l; *t = e; *tail = e; t = &e->next; } return start; }
int cread(Chan *c, uchar *buf, int len, vlong off) { KMap *k; Page *p; Mntcache *m; Extent *e, **t; int o, l, total; ulong offset; if(off+len > maxcache) return 0; m = c->mcp; if(m == 0) return 0; qlock(m); if(cdev(m, c) == 0) { qunlock(m); return 0; } offset = off; t = &m->list; for(e = *t; e; e = e->next) { if(offset >= e->start && offset < e->start+e->len) break; t = &e->next; } if(e == 0) { qunlock(m); return 0; } total = 0; while(len) { p = cpage(e); if(p == 0) { *t = e->next; extentfree(e); qunlock(m); return total; } o = offset - e->start; l = len; if(l > e->len-o) l = e->len-o; k = kmap(p); if(waserror()) { kunmap(k); putpage(p); qunlock(m); nexterror(); } memmove(buf, (uchar*)VA(k) + o, l); poperror(); kunmap(k); putpage(p); buf += l; len -= l; offset += l; total += l; t = &e->next; e = e->next; if(e == 0 || e->start != offset) break; } qunlock(m); return total; }
void copen(Chan *c) { int h; Extent *e, *next; Mntcache *m, *f, **l; /* directories aren't cacheable and append-only files confuse us */ if(c->qid.type&(QTDIR|QTAPPEND)) return; h = c->qid.path%NHASH; qlock(&cache); for(m = cache.hash[h]; m; m = m->hash) { if(m->qid.path == c->qid.path) if(m->qid.type == c->qid.type) if(m->dev == c->dev && m->type == c->type) { c->mcp = m; ctail(m); qunlock(&cache); /* File was updated, invalidate cache */ if(m->qid.vers != c->qid.vers) { m->qid.vers = c->qid.vers; qlock(m); cnodata(m); qunlock(m); } return; } } /* LRU the cache headers */ m = cache.head; l = &cache.hash[m->qid.path%NHASH]; for(f = *l; f; f = f->hash) { if(f == m) { *l = m->hash; break; } l = &f->hash; } m->qid = c->qid; m->dev = c->dev; m->type = c->type; l = &cache.hash[h]; m->hash = *l; *l = m; ctail(m); qlock(m); c->mcp = m; e = m->list; m->list = 0; qunlock(&cache); while(e) { next = e->next; extentfree(e); e = next; } qunlock(m); }