From 4806d7571d7eacc6df58e9a481b624aef5be4217 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 14 Oct 1993 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1993-10-14 --- port/cache.c | 265 +++++++++++++++++++++++++++++++++++++++++-------- port/devmnt.c | 40 +++++--- port/lib.h | 3 +- port/portdat.h | 2 +- port/portfns.h | 5 + port/sysfile.c | 4 +- 6 files changed, 259 insertions(+), 60 deletions(-) diff --git a/port/cache.c b/port/cache.c index f2cb2b1cfe8bcda5bc6efbeb70cf0bdf4d8e7de1..a5c9cf8258cd10fa4acd92aac6c7bd1abbae6f7f 100644 --- a/port/cache.c +++ b/port/cache.c @@ -8,12 +8,20 @@ Image fscache; -typedef Extent Extent; +enum +{ + NHASH = 128, + MAXCACHE = 1024*1024, + NFILE = 4096, +}; + +typedef struct Extent Extent; struct Extent { int bid; ulong start; int len; + Page *cache; Extent *next; }; @@ -23,7 +31,7 @@ struct Mntcache Qid; int dev; int type; - Qlock; + QLock; Extent *list; Mntcache *hash; Mntcache *prev; @@ -40,16 +48,38 @@ struct Cache }; Cache cache; +void +cinit(void) +{ + int i; + Mntcache *m; + + cache.ref = 1; + cache.head = xalloc(sizeof(Mntcache)*NFILE); + m = cache.head; + + for(i = NFILE; i > 0; i++) { + m->next = m+1; + m->prev = m-1; + m++; + } + + cache.tail = m; + cache.tail->next = 0; + cache.head->prev = 0; +} + Mntcache* clook(Chan *c) { int h; + Mntcache *m; h = c->qid.path%NHASH; lock(&cache); for(m = cache.hash[h]; m; m = m->hash) { - if(m->path == c->path) { + if(m->path == c->qid.path) { qlock(m); if(m->path == c->qid.path) if(m->dev == c->dev) @@ -64,6 +94,28 @@ clook(Chan *c) return 0; } +void +cprint(Mntcache *m) +{ + Extent *e; + + print("%lux.%lux %d %d\n", m->path, m->vers, m->type, m->dev); + + while(e) + print("\t%4d %5d %4d %lux\n", + e->bid, e->start, e->len, e->cache); +} + +Page* +cpage(Extent *e) +{ + /* Easy consistency check */ + if(e->cache->daddr != e->bid) + return 0; + + return lookpage(&fscache, e->bid); +} + void cnodata(Mntcache *m) { @@ -74,7 +126,7 @@ cnodata(Mntcache *m) * Image lru will waste the pages */ for(e = m->list; e; e = n) { - n = e->list; + n = e->next; free(e); } } @@ -116,7 +168,7 @@ copen(Chan *c) m = clook(c); if(m != 0) { /* File was updated */ - if(m->vers != c->vers) + if(m->vers != c->qid.vers) cnodata(m); ctail(m); @@ -127,8 +179,8 @@ copen(Chan *c) /* LRU the cache headers */ m = cache.head; qlock(m); - lock(cache); - l = &cache.hash[m->qid.path%NHASH]; + lock(&cache); + l = &cache.hash[m->path%NHASH]; for(f = *l; f; f = f->next) { if(f == m) { *l = f->next; @@ -139,8 +191,8 @@ copen(Chan *c) l = &cache.hash[c->qid.path%NHASH]; m->hash = *l; *l = m; - unlock(cache); - m->qid = c->qid; + unlock(&cache); + m->Qid = c->qid; m->dev = c->dev; m->type = c->type; cnodata(m); @@ -152,9 +204,9 @@ copen(Chan *c) static int cdev(Mntcache *m, Chan *c) { - if(m->path != c->path) + if(m->path != c->qid.path) return 0; - if(m->vers != c->vers) + if(m->vers != c->qid.vers) return 0; if(m->dev != c->dev) return 0; @@ -164,13 +216,13 @@ cdev(Mntcache *m, Chan *c) } int -cread(Chan *c, uchar *buf, int len, long offset) +cread(Chan *c, uchar *buf, int len, ulong offset) { KMap *k; Page *p; Mntcache *m; - Extent *e, **l; - int o, l, total; + Extent *e, **t; + int o, l, total, end; m = c->mcp; if(m == 0) @@ -182,11 +234,11 @@ cread(Chan *c, uchar *buf, int len, long offset) } end = offset+len; - l = &m->list; - for(e = *l; e; e = e->next) { + t = &m->list; + for(e = *t; e; e = e->next) { if(e->start >= offset && e->start+e->len < end) break; - l = &e->next; + t = &e->next; } if(e == 0) { @@ -196,9 +248,9 @@ cread(Chan *c, uchar *buf, int len, long offset) total = 0; while(len) { - p = lookpage(&fscache, e->bid); + p = cpage(e); if(p == 0) { - *l = e->next; + *t = e->next; free(e); qunlock(m); return total; @@ -217,8 +269,7 @@ cread(Chan *c, uchar *buf, int len, long offset) if(l > e->len-o) l = e->len-o; - p = (uchar*)VA(k) + o; - memset(buf, p, l); + memmove(buf, (uchar*)VA(k) + o, l); kunmap(k); putpage(p); @@ -226,20 +277,85 @@ cread(Chan *c, uchar *buf, int len, long offset) len -= l; offset += l; total += l; - l = &e->next; + t = &e->next; e = e->next; if(e == 0 || e->start != offset) break; } - qunlock(m) + qunlock(m); return total; } +Extent* +cchain(uchar *buf, ulong offset, int len, Extent **tail) +{ + int l; + Page *p; + KMap *k; + Extent *e, *start, **t; + + start = 0; + t = &start; + while(len) { + e = malloc(sizeof(Extent)); + if(e == 0) + break; + + p = auxpage(); + if(p == 0) { + free(e); + break; + } + e->cache = p; + e->start = offset; + l = len; + if(l > BY2PG) + l = BY2PG; + + e->bid = incref(&cache); + p->daddr = e->bid; + k = kmap(p); + memmove((void*)VA(k), buf, l); + kunmap(k); + + cachepage(p, &fscache); + putpage(p); + + buf += l; + offset += l; + len -= l; + + *t = e; + *tail = e; + t = &e->next; + } + return start; +} + +int +cpgmove(Extent *e, uchar *buf, int boff, int len) +{ + Page *p; + KMap *k; + + p = cpage(e); + if(p == 0) + return 0; + k = kmap(p); + memmove((uchar*)VA(k)+boff, buf, len); + kunmap(k); + putpage(p); + + return 1; +} + void -cwrite(Chan *c, uchar *buf, int len, long offset) +cupdate(Chan *c, uchar *buf, int len, ulong offset) { - Extent *e; Mntcache *m; + Extent *tail; + Extent *e, *f, *p; + int o, ee, eblock; if(offset > MAXCACHE) return; @@ -253,22 +369,91 @@ cwrite(Chan *c, uchar *buf, int len, long offset) return; } - if(m->list == 0) { - e = malloc(sizeof(Extent)); - if(e == 0) + /* + * Find the insertion point + */ + p = 0; + for(f = m->list; f; f = f->next) { + if(f->start >= offset) + break; + p = f; + } + if(p == 0) { /* at the head */ + eblock = offset+len; + /* trim if there is a successor */ + if(f != 0 && eblock >= f->start) { + len -= (eblock - f->start); + if(len <= 0) { + qunlock(m); + return; + } + } + e = cchain(buf, offset, len, &tail); + m->list = e; + if(tail != 0) + tail->next = f; + qunlock(m); + return; + } + + /* trim to the predecessor */ + ee = p->start+p->len; + if(offset < ee) { + o = ee - offset; + len -= o; + if(len <= 0) { + qunlock(m); return; - e->start = offset; - l = len; - if(l > BY2PG) - l = BY2PG; - p = auxpage(); - if(p == 0) + } + buf += o; + offset += o; + } + + /* try and pack data into the predecessor */ + if(offset == ee && p->len < BY2PG) { + o = len; + if(o > BY2PG - p->len) + o = BY2PG - p->len; + if(len <= 0) { + qunlock(m); return; - e->bid = incref(&cache); - p->daddr = e->bid; - cachepage(p, fscache); - k = kmap(p); - - kunmap(p); + } + if(cpgmove(e, buf, p->len, o)) { + e->len += o; + buf += o; + len -= o; + offset += o; + if(len <= 0) { + qunlock(m); + return; + } + } + } + + /* append to extent list */ + if(f == 0) { + p->next = cchain(buf, offset, len, &tail); + qunlock(m); + return; + } + + /* trim data against successor */ + eblock = offset+len; + if(eblock > f->start) { + o = eblock - f->start; + if(o < 0) { + qunlock(m); + return; + } + len -= o; } + + /* Insert a middle block */ + p->next = cchain(buf, offset, len, &tail); + if(p->next == 0) + p->next = f; + else + tail->next = f; + + qunlock(m); } diff --git a/port/devmnt.c b/port/devmnt.c index 92d69976dd24fd399b4b8a91a1c88719fe3cb416..ebaaad59114bc56072c37bfecb0bbb4f7adbfb6a 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -44,7 +44,7 @@ void mntgate(Mnt*); void mntpntfree(Mnt*); void mntqrm(Mnt*, Mntrpc*); Mntrpc* mntralloc(Chan*); -long mntrdwr(int , Chan*, void*,long , ulong); +long mntrdwr(int , Mnt*, Chan*, void*,long , ulong); void mntrpcread(Mnt*, Mntrpc*); void mountio(Mnt*, Mntrpc*); void mountmux(Mnt*, Mntrpc*); @@ -83,7 +83,7 @@ mntattach(char *muxattach) struct bogus{ Chan *chan; char *spec; - char recov; + int flag; }bogus; bogus = *((struct bogus *)muxattach); @@ -133,7 +133,7 @@ mntattach(char *muxattach) m->c = c; m->c->flag |= CMSG; m->blocksize = MAXFDATA; /**/ - m->recov = bogus.recov; + m->flags = bogus.flags; switch(devchar[m->c->type]) { default: @@ -302,13 +302,6 @@ mntwalk(Chan *c, char *name) op = c->path; c->path = ptenter(&m->tree, op, name); -/* ASSERT do not remove */ -if(op->ref == 0) { - char buf[128]; - ptpath(op, buf, sizeof(buf)); - print("PATH: '%s' walking %s\n", op, name); -} - decref(op); poperror(); @@ -488,31 +481,46 @@ mntwstat(Chan *c, char *dp) long mntread(Chan *c, void *buf, long n, ulong offset) { + int nc; uchar *p, *e; - n = mntrdwr(Tread, c, buf, n, offset); + m = mntchk(c); + nc = 0; + if((m->flags&MCACHE) && !isdir(c)) { + nc = cread(c, buf, n, offset); + if(nc == n) + return n; + + buf = (uchar*)buf+nc; + offset += nc; + n -= nc; + } + + n = mntrdwr(Tread, m, c, buf, n, offset); if(c->qid.path & CHDIR) for(p = (uchar*)buf, e = &p[n]; p < e; p += DIRLEN) mntdirfix(p, c); + if(nc != 0) + cupdate(c, buf, n, offset); + return n; } long mntwrite(Chan *c, void *buf, long n, ulong offset) { - return mntrdwr(Twrite, c, buf, n, offset); + m = mntchk(c); + return mntrdwr(Twrite, m, c, buf, n, offset); } long -mntrdwr(int type, Chan *c, void *buf, long n, ulong offset) +mntrdwr(int type, Mnt *m, Chan *c, void *buf, long n, ulong offset) { - Mnt *m; Mntrpc *r; char *uba; ulong cnt, nr; - m = mntchk(c); uba = buf; cnt = 0; for(;;) { @@ -553,7 +561,7 @@ mountrpc(Mnt *m, Mntrpc *r) r->reply.type = 4; while(waserror()) { - if(m->recov == 0) + if((m->flags & MRECOV) == 0) nexterror(); mntrecover(m, r); } diff --git a/port/lib.h b/port/lib.h index 27b92d76ce88a4e2bba3511925a2ede5cbfb739d..9a625ae094e0d0e775cf84a18ec6b3a963b25b35 100644 --- a/port/lib.h +++ b/port/lib.h @@ -80,7 +80,8 @@ extern char end[]; #define MAFTER 0x0002 /* mount goes after others in union directory */ #define MCREATE 0x0004 /* permit creation in mounted directory */ #define MRECOV 0x0008 /* perform recovery if mount channel is lost */ -#define MMASK 0x000F /* all bits on */ +#define MCACHE 0x0010 /* cache some data */ +#define MMASK 0x001F /* all bits on */ #define OREAD 0 /* open for read */ #define OWRITE 1 /* write */ diff --git a/port/portdat.h b/port/portdat.h index b119c7b0da11e4e8198c9b64b3bbc54ee26db738..cc79769ac58f03acd584d9955a5600920615ddca 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -269,7 +269,7 @@ struct Mnt ulong id; /* Multiplexor id for channel check */ Mnt *list; /* Free list */ char mux; /* Set if the device does the multiplexing */ - char recov; /* Run recovery if channel is lost */ + int flags; /* recover/cache */ char recprog; /* Recovery in progress */ int blocksize; /* read/write block size */ ushort flushtag; /* Tag to send flush on */ diff --git a/port/portfns.h b/port/portfns.h index aa8828ca40ff2acef759f43443316dcdb06e61e0..9f54c151b3d9ba8d3e1758630caeb3734a56ceb5 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -10,6 +10,7 @@ long authread(Chan*, char*, int); void authreply(Session*, ulong, Fcall*); ulong authrequest(Session*, Fcall*); long authwrite(Chan*, char*, int); +Page* auxpage(void); void bitdebug(void); void bitdepth(void); void bitreverse(uchar*, int); @@ -272,3 +273,7 @@ Segment* newseg(int, ulong, ulong); Scsibuf* scsialloc(ulong); Scsibuf* scsibuf(void); Segment* seg(Proc*, ulong, int); + + +int cread(Chan*, uchar*, int, ulong); +void cupdate(Chan*, uchar*, int, ulong); diff --git a/port/sysfile.c b/port/sysfile.c index 7621b8a9e16234e2b49cc63446df12e1bfd49b1e..21e97a2c13ed8a036192aa7a5990a92dade2f3db 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -450,7 +450,7 @@ bindmount(ulong *arg, int ismount) struct{ Chan *chan; char *spec; - char recov; + int flags; }bogus; flag = arg[2]; @@ -458,7 +458,7 @@ bindmount(ulong *arg, int ismount) if(flag>MMASK || (flag&MORDER)==(MBEFORE|MAFTER)) error(Ebadarg); - bogus.recov = flag&MRECOV; + bogus.flags = flag & (MRECOV|MCACHE); if(ismount){ bc = fdtochan(fd, ORDWR, 0, 1);