19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier
79ef1f84bSDavid du Colombier enum
89ef1f84bSDavid du Colombier {
99ef1f84bSDavid du Colombier NHASH = 128,
109ef1f84bSDavid du Colombier MAXCACHE = 1024*1024,
119ef1f84bSDavid du Colombier NFILE = 4096,
129ef1f84bSDavid du Colombier NEXTENT = 200, /* extent allocation size */
139ef1f84bSDavid du Colombier };
149ef1f84bSDavid du Colombier
159ef1f84bSDavid du Colombier typedef struct Extent Extent;
169ef1f84bSDavid du Colombier struct Extent
179ef1f84bSDavid du Colombier {
189ef1f84bSDavid du Colombier int bid;
199ef1f84bSDavid du Colombier ulong start;
209ef1f84bSDavid du Colombier int len;
219ef1f84bSDavid du Colombier Page *cache;
229ef1f84bSDavid du Colombier Extent *next;
239ef1f84bSDavid du Colombier };
249ef1f84bSDavid du Colombier
259ef1f84bSDavid du Colombier typedef struct Mntcache Mntcache;
269ef1f84bSDavid du Colombier struct Mntcache
279ef1f84bSDavid du Colombier {
289ef1f84bSDavid du Colombier Qid qid;
299ef1f84bSDavid du Colombier uint devno;
309ef1f84bSDavid du Colombier Dev* dev;
319ef1f84bSDavid du Colombier QLock;
329ef1f84bSDavid du Colombier Extent *list;
339ef1f84bSDavid du Colombier Mntcache *hash;
349ef1f84bSDavid du Colombier Mntcache *prev;
359ef1f84bSDavid du Colombier Mntcache *next;
369ef1f84bSDavid du Colombier };
379ef1f84bSDavid du Colombier
389ef1f84bSDavid du Colombier typedef struct Cache Cache;
399ef1f84bSDavid du Colombier struct Cache
409ef1f84bSDavid du Colombier {
419ef1f84bSDavid du Colombier QLock;
429ef1f84bSDavid du Colombier int pgno;
439ef1f84bSDavid du Colombier Mntcache *head;
449ef1f84bSDavid du Colombier Mntcache *tail;
459ef1f84bSDavid du Colombier Mntcache *hash[NHASH];
469ef1f84bSDavid du Colombier };
479ef1f84bSDavid du Colombier
489ef1f84bSDavid du Colombier typedef struct Ecache Ecache;
499ef1f84bSDavid du Colombier struct Ecache
509ef1f84bSDavid du Colombier {
519ef1f84bSDavid du Colombier Lock;
529ef1f84bSDavid du Colombier int total;
539ef1f84bSDavid du Colombier int free;
549ef1f84bSDavid du Colombier Extent* head;
559ef1f84bSDavid du Colombier };
569ef1f84bSDavid du Colombier
579ef1f84bSDavid du Colombier static Image fscache;
589ef1f84bSDavid du Colombier static Cache cache;
599ef1f84bSDavid du Colombier static Ecache ecache;
609ef1f84bSDavid du Colombier static int maxcache = MAXCACHE;
619ef1f84bSDavid du Colombier
629ef1f84bSDavid du Colombier static void
extentfree(Extent * e)639ef1f84bSDavid du Colombier extentfree(Extent* e)
649ef1f84bSDavid du Colombier {
659ef1f84bSDavid du Colombier lock(&ecache);
669ef1f84bSDavid du Colombier e->next = ecache.head;
679ef1f84bSDavid du Colombier ecache.head = e;
689ef1f84bSDavid du Colombier ecache.free++;
699ef1f84bSDavid du Colombier unlock(&ecache);
709ef1f84bSDavid du Colombier }
719ef1f84bSDavid du Colombier
729ef1f84bSDavid du Colombier static Extent*
extentalloc(void)739ef1f84bSDavid du Colombier extentalloc(void)
749ef1f84bSDavid du Colombier {
759ef1f84bSDavid du Colombier Extent *e;
769ef1f84bSDavid du Colombier int i;
779ef1f84bSDavid du Colombier
789ef1f84bSDavid du Colombier lock(&ecache);
799ef1f84bSDavid du Colombier if(ecache.head == nil){
809ef1f84bSDavid du Colombier e = malloc(NEXTENT*sizeof(Extent));
819ef1f84bSDavid du Colombier if(e == nil){
829ef1f84bSDavid du Colombier unlock(&ecache);
839ef1f84bSDavid du Colombier return nil;
849ef1f84bSDavid du Colombier }
859ef1f84bSDavid du Colombier for(i = 0; i < NEXTENT; i++){
869ef1f84bSDavid du Colombier e->next = ecache.head;
879ef1f84bSDavid du Colombier ecache.head = e;
889ef1f84bSDavid du Colombier e++;
899ef1f84bSDavid du Colombier }
909ef1f84bSDavid du Colombier ecache.free += NEXTENT;
919ef1f84bSDavid du Colombier ecache.total += NEXTENT;
929ef1f84bSDavid du Colombier }
939ef1f84bSDavid du Colombier
949ef1f84bSDavid du Colombier e = ecache.head;
959ef1f84bSDavid du Colombier ecache.head = e->next;
969ef1f84bSDavid du Colombier memset(e, 0, sizeof(Extent));
979ef1f84bSDavid du Colombier ecache.free--;
989ef1f84bSDavid du Colombier unlock(&ecache);
999ef1f84bSDavid du Colombier
1009ef1f84bSDavid du Colombier return e;
1019ef1f84bSDavid du Colombier }
1029ef1f84bSDavid du Colombier
1039ef1f84bSDavid du Colombier void
cinit(void)1049ef1f84bSDavid du Colombier cinit(void)
1059ef1f84bSDavid du Colombier {
1069ef1f84bSDavid du Colombier int i;
1079ef1f84bSDavid du Colombier Mntcache *mc;
1089ef1f84bSDavid du Colombier
1099ef1f84bSDavid du Colombier if((cache.head = malloc(sizeof(Mntcache)*NFILE)) == nil)
1109ef1f84bSDavid du Colombier panic("cinit: no memory");
1119ef1f84bSDavid du Colombier mc = cache.head;
1129ef1f84bSDavid du Colombier
1139ef1f84bSDavid du Colombier /* a good algorithm to set maxcache would be nice */
1149ef1f84bSDavid du Colombier
1159ef1f84bSDavid du Colombier for(i = 0; i < NFILE-1; i++) {
1169ef1f84bSDavid du Colombier mc->next = mc+1;
1179ef1f84bSDavid du Colombier mc->prev = mc-1;
1189ef1f84bSDavid du Colombier mc++;
1199ef1f84bSDavid du Colombier }
1209ef1f84bSDavid du Colombier
1219ef1f84bSDavid du Colombier cache.tail = mc;
1229ef1f84bSDavid du Colombier cache.tail->next = 0;
1239ef1f84bSDavid du Colombier cache.head->prev = 0;
1249ef1f84bSDavid du Colombier
1259ef1f84bSDavid du Colombier fscache.notext = 1;
1269ef1f84bSDavid du Colombier }
1279ef1f84bSDavid du Colombier
1289ef1f84bSDavid du Colombier Page*
cpage(Extent * e)1299ef1f84bSDavid du Colombier cpage(Extent *e)
1309ef1f84bSDavid du Colombier {
1319ef1f84bSDavid du Colombier /* Easy consistency check */
1329ef1f84bSDavid du Colombier if(e->cache->daddr != e->bid)
1339ef1f84bSDavid du Colombier return 0;
1349ef1f84bSDavid du Colombier
1359ef1f84bSDavid du Colombier return lookpage(&fscache, e->bid);
1369ef1f84bSDavid du Colombier }
1379ef1f84bSDavid du Colombier
1389ef1f84bSDavid du Colombier void
cnodata(Mntcache * mc)1399ef1f84bSDavid du Colombier cnodata(Mntcache *mc)
1409ef1f84bSDavid du Colombier {
1419ef1f84bSDavid du Colombier Extent *e, *n;
1429ef1f84bSDavid du Colombier
1439ef1f84bSDavid du Colombier /*
1449ef1f84bSDavid du Colombier * Invalidate all extent data
1459ef1f84bSDavid du Colombier * Image lru will waste the pages
1469ef1f84bSDavid du Colombier */
1479ef1f84bSDavid du Colombier for(e = mc->list; e; e = n) {
1489ef1f84bSDavid du Colombier n = e->next;
1499ef1f84bSDavid du Colombier extentfree(e);
1509ef1f84bSDavid du Colombier }
1519ef1f84bSDavid du Colombier mc->list = 0;
1529ef1f84bSDavid du Colombier }
1539ef1f84bSDavid du Colombier
1549ef1f84bSDavid du Colombier void
ctail(Mntcache * mc)1559ef1f84bSDavid du Colombier ctail(Mntcache *mc)
1569ef1f84bSDavid du Colombier {
1579ef1f84bSDavid du Colombier /* Unlink and send to the tail */
1589ef1f84bSDavid du Colombier if(mc->prev)
1599ef1f84bSDavid du Colombier mc->prev->next = mc->next;
1609ef1f84bSDavid du Colombier else
1619ef1f84bSDavid du Colombier cache.head = mc->next;
1629ef1f84bSDavid du Colombier if(mc->next)
1639ef1f84bSDavid du Colombier mc->next->prev = mc->prev;
1649ef1f84bSDavid du Colombier else
1659ef1f84bSDavid du Colombier cache.tail = mc->prev;
1669ef1f84bSDavid du Colombier
1679ef1f84bSDavid du Colombier if(cache.tail) {
1689ef1f84bSDavid du Colombier mc->prev = cache.tail;
1699ef1f84bSDavid du Colombier cache.tail->next = mc;
1709ef1f84bSDavid du Colombier mc->next = 0;
1719ef1f84bSDavid du Colombier cache.tail = mc;
1729ef1f84bSDavid du Colombier }
1739ef1f84bSDavid du Colombier else {
1749ef1f84bSDavid du Colombier cache.head = mc;
1759ef1f84bSDavid du Colombier cache.tail = mc;
1769ef1f84bSDavid du Colombier mc->prev = 0;
1779ef1f84bSDavid du Colombier mc->next = 0;
1789ef1f84bSDavid du Colombier }
1799ef1f84bSDavid du Colombier }
1809ef1f84bSDavid du Colombier
1819ef1f84bSDavid du Colombier void
copen(Chan * c)1829ef1f84bSDavid du Colombier copen(Chan *c)
1839ef1f84bSDavid du Colombier {
1849ef1f84bSDavid du Colombier int h;
1859ef1f84bSDavid du Colombier Extent *e, *next;
1869ef1f84bSDavid du Colombier Mntcache *mc, *f, **l;
1879ef1f84bSDavid du Colombier
1889ef1f84bSDavid du Colombier /* directories aren't cacheable and append-only files confuse us */
1899ef1f84bSDavid du Colombier if(c->qid.type&(QTDIR|QTAPPEND))
1909ef1f84bSDavid du Colombier return;
1919ef1f84bSDavid du Colombier
1929ef1f84bSDavid du Colombier h = c->qid.path%NHASH;
1939ef1f84bSDavid du Colombier qlock(&cache);
1949ef1f84bSDavid du Colombier for(mc = cache.hash[h]; mc != nil; mc = mc->hash) {
1959ef1f84bSDavid du Colombier if(mc->qid.path == c->qid.path)
1969ef1f84bSDavid du Colombier if(mc->qid.type == c->qid.type)
1979ef1f84bSDavid du Colombier if(mc->devno == c->devno && mc->dev == c->dev) {
1989ef1f84bSDavid du Colombier c->mc = mc;
1999ef1f84bSDavid du Colombier ctail(mc);
2009ef1f84bSDavid du Colombier qunlock(&cache);
2019ef1f84bSDavid du Colombier
2029ef1f84bSDavid du Colombier /* File was updated, invalidate cache */
2039ef1f84bSDavid du Colombier if(mc->qid.vers != c->qid.vers) {
2049ef1f84bSDavid du Colombier mc->qid.vers = c->qid.vers;
2059ef1f84bSDavid du Colombier qlock(mc);
2069ef1f84bSDavid du Colombier cnodata(mc);
2079ef1f84bSDavid du Colombier qunlock(mc);
2089ef1f84bSDavid du Colombier }
2099ef1f84bSDavid du Colombier return;
2109ef1f84bSDavid du Colombier }
2119ef1f84bSDavid du Colombier }
2129ef1f84bSDavid du Colombier
2139ef1f84bSDavid du Colombier /* LRU the cache headers */
2149ef1f84bSDavid du Colombier mc = cache.head;
2159ef1f84bSDavid du Colombier l = &cache.hash[mc->qid.path%NHASH];
2169ef1f84bSDavid du Colombier for(f = *l; f; f = f->hash) {
2179ef1f84bSDavid du Colombier if(f == mc) {
2189ef1f84bSDavid du Colombier *l = mc->hash;
2199ef1f84bSDavid du Colombier break;
2209ef1f84bSDavid du Colombier }
2219ef1f84bSDavid du Colombier l = &f->hash;
2229ef1f84bSDavid du Colombier }
2239ef1f84bSDavid du Colombier
2249ef1f84bSDavid du Colombier mc->qid = c->qid;
2259ef1f84bSDavid du Colombier mc->devno = c->devno;
2269ef1f84bSDavid du Colombier mc->dev = c->dev;
2279ef1f84bSDavid du Colombier
2289ef1f84bSDavid du Colombier l = &cache.hash[h];
2299ef1f84bSDavid du Colombier mc->hash = *l;
2309ef1f84bSDavid du Colombier *l = mc;
2319ef1f84bSDavid du Colombier ctail(mc);
2329ef1f84bSDavid du Colombier
2339ef1f84bSDavid du Colombier qlock(mc);
2349ef1f84bSDavid du Colombier c->mc = mc;
2359ef1f84bSDavid du Colombier e = mc->list;
2369ef1f84bSDavid du Colombier mc->list = 0;
2379ef1f84bSDavid du Colombier qunlock(&cache);
2389ef1f84bSDavid du Colombier
2399ef1f84bSDavid du Colombier while(e) {
2409ef1f84bSDavid du Colombier next = e->next;
2419ef1f84bSDavid du Colombier extentfree(e);
2429ef1f84bSDavid du Colombier e = next;
2439ef1f84bSDavid du Colombier }
2449ef1f84bSDavid du Colombier qunlock(mc);
2459ef1f84bSDavid du Colombier }
2469ef1f84bSDavid du Colombier
2479ef1f84bSDavid du Colombier static int
cdev(Mntcache * mc,Chan * c)2489ef1f84bSDavid du Colombier cdev(Mntcache *mc, Chan *c)
2499ef1f84bSDavid du Colombier {
2509ef1f84bSDavid du Colombier if(mc->qid.path != c->qid.path)
2519ef1f84bSDavid du Colombier return 0;
2529ef1f84bSDavid du Colombier if(mc->qid.type != c->qid.type)
2539ef1f84bSDavid du Colombier return 0;
2549ef1f84bSDavid du Colombier if(mc->devno != c->devno)
2559ef1f84bSDavid du Colombier return 0;
2569ef1f84bSDavid du Colombier if(mc->dev != c->dev)
2579ef1f84bSDavid du Colombier return 0;
2589ef1f84bSDavid du Colombier if(mc->qid.vers != c->qid.vers)
2599ef1f84bSDavid du Colombier return 0;
2609ef1f84bSDavid du Colombier return 1;
2619ef1f84bSDavid du Colombier }
2629ef1f84bSDavid du Colombier
2639ef1f84bSDavid du Colombier int
cread(Chan * c,uchar * buf,int len,vlong off)2649ef1f84bSDavid du Colombier cread(Chan *c, uchar *buf, int len, vlong off)
2659ef1f84bSDavid du Colombier {
2669ef1f84bSDavid du Colombier KMap *k;
2679ef1f84bSDavid du Colombier Page *p;
2689ef1f84bSDavid du Colombier Mntcache *mc;
2699ef1f84bSDavid du Colombier Extent *e, **t;
2709ef1f84bSDavid du Colombier int o, l, total;
2719ef1f84bSDavid du Colombier ulong offset;
2729ef1f84bSDavid du Colombier
2739ef1f84bSDavid du Colombier if(off+len > maxcache)
2749ef1f84bSDavid du Colombier return 0;
2759ef1f84bSDavid du Colombier
2769ef1f84bSDavid du Colombier mc = c->mc;
2779ef1f84bSDavid du Colombier if(mc == nil)
2789ef1f84bSDavid du Colombier return 0;
2799ef1f84bSDavid du Colombier
2809ef1f84bSDavid du Colombier qlock(mc);
2819ef1f84bSDavid du Colombier if(cdev(mc, c) == 0) {
2829ef1f84bSDavid du Colombier qunlock(mc);
2839ef1f84bSDavid du Colombier return 0;
2849ef1f84bSDavid du Colombier }
2859ef1f84bSDavid du Colombier
2869ef1f84bSDavid du Colombier offset = off;
2879ef1f84bSDavid du Colombier t = &mc->list;
2889ef1f84bSDavid du Colombier for(e = *t; e; e = e->next) {
2899ef1f84bSDavid du Colombier if(offset >= e->start && offset < e->start+e->len)
2909ef1f84bSDavid du Colombier break;
2919ef1f84bSDavid du Colombier t = &e->next;
2929ef1f84bSDavid du Colombier }
2939ef1f84bSDavid du Colombier
2949ef1f84bSDavid du Colombier if(e == 0) {
2959ef1f84bSDavid du Colombier qunlock(mc);
2969ef1f84bSDavid du Colombier return 0;
2979ef1f84bSDavid du Colombier }
2989ef1f84bSDavid du Colombier
2999ef1f84bSDavid du Colombier total = 0;
3009ef1f84bSDavid du Colombier while(len) {
3019ef1f84bSDavid du Colombier p = cpage(e);
3029ef1f84bSDavid du Colombier if(p == 0) {
3039ef1f84bSDavid du Colombier *t = e->next;
3049ef1f84bSDavid du Colombier extentfree(e);
3059ef1f84bSDavid du Colombier qunlock(mc);
3069ef1f84bSDavid du Colombier return total;
3079ef1f84bSDavid du Colombier }
3089ef1f84bSDavid du Colombier
3099ef1f84bSDavid du Colombier o = offset - e->start;
3109ef1f84bSDavid du Colombier l = len;
3119ef1f84bSDavid du Colombier if(l > e->len-o)
3129ef1f84bSDavid du Colombier l = e->len-o;
3139ef1f84bSDavid du Colombier
3149ef1f84bSDavid du Colombier k = kmap(p);
3159ef1f84bSDavid du Colombier if(waserror()) {
3169ef1f84bSDavid du Colombier kunmap(k);
3179ef1f84bSDavid du Colombier putpage(p);
3189ef1f84bSDavid du Colombier qunlock(mc);
3199ef1f84bSDavid du Colombier nexterror();
3209ef1f84bSDavid du Colombier }
3219ef1f84bSDavid du Colombier
3229ef1f84bSDavid du Colombier memmove(buf, (uchar*)VA(k) + o, l);
3239ef1f84bSDavid du Colombier
3249ef1f84bSDavid du Colombier poperror();
3259ef1f84bSDavid du Colombier kunmap(k);
3269ef1f84bSDavid du Colombier
3279ef1f84bSDavid du Colombier putpage(p);
3289ef1f84bSDavid du Colombier
3299ef1f84bSDavid du Colombier buf += l;
3309ef1f84bSDavid du Colombier len -= l;
3319ef1f84bSDavid du Colombier offset += l;
3329ef1f84bSDavid du Colombier total += l;
3339ef1f84bSDavid du Colombier t = &e->next;
3349ef1f84bSDavid du Colombier e = e->next;
3359ef1f84bSDavid du Colombier if(e == 0 || e->start != offset)
3369ef1f84bSDavid du Colombier break;
3379ef1f84bSDavid du Colombier }
3389ef1f84bSDavid du Colombier
3399ef1f84bSDavid du Colombier qunlock(mc);
3409ef1f84bSDavid du Colombier return total;
3419ef1f84bSDavid du Colombier }
3429ef1f84bSDavid du Colombier
3439ef1f84bSDavid du Colombier Extent*
cchain(uchar * buf,ulong offset,int len,Extent ** tail)3449ef1f84bSDavid du Colombier cchain(uchar *buf, ulong offset, int len, Extent **tail)
3459ef1f84bSDavid du Colombier {
3469ef1f84bSDavid du Colombier int l;
3479ef1f84bSDavid du Colombier Page *p;
3489ef1f84bSDavid du Colombier KMap *k;
3499ef1f84bSDavid du Colombier Extent *e, *start, **t;
3509ef1f84bSDavid du Colombier
3519ef1f84bSDavid du Colombier start = 0;
3529ef1f84bSDavid du Colombier *tail = 0;
3539ef1f84bSDavid du Colombier t = &start;
3549ef1f84bSDavid du Colombier while(len) {
3559ef1f84bSDavid du Colombier e = extentalloc();
3569ef1f84bSDavid du Colombier if(e == 0)
3579ef1f84bSDavid du Colombier break;
3589ef1f84bSDavid du Colombier
359*094d6818SDavid du Colombier p = auxpage(PGSHFT);
3609ef1f84bSDavid du Colombier if(p == 0) {
3619ef1f84bSDavid du Colombier extentfree(e);
3629ef1f84bSDavid du Colombier break;
3639ef1f84bSDavid du Colombier }
3649ef1f84bSDavid du Colombier l = len;
3659ef1f84bSDavid du Colombier if(l > PGSZ)
3669ef1f84bSDavid du Colombier l = PGSZ;
3679ef1f84bSDavid du Colombier
3689ef1f84bSDavid du Colombier e->cache = p;
3699ef1f84bSDavid du Colombier e->start = offset;
3709ef1f84bSDavid du Colombier e->len = l;
3719ef1f84bSDavid du Colombier
3729ef1f84bSDavid du Colombier qlock(&cache);
3739ef1f84bSDavid du Colombier e->bid = cache.pgno;
3749ef1f84bSDavid du Colombier cache.pgno += PGSZ;
3759ef1f84bSDavid du Colombier /* wrap the counter; low bits are unused by pghash but checked by lookpage */
3769ef1f84bSDavid du Colombier if((cache.pgno & ~(PGSZ-1)) == 0){
3779ef1f84bSDavid du Colombier if(cache.pgno == PGSZ-1){
3789ef1f84bSDavid du Colombier print("cache wrapped\n");
3799ef1f84bSDavid du Colombier cache.pgno = 0;
3809ef1f84bSDavid du Colombier }else
3819ef1f84bSDavid du Colombier cache.pgno++;
3829ef1f84bSDavid du Colombier }
3839ef1f84bSDavid du Colombier qunlock(&cache);
3849ef1f84bSDavid du Colombier
3859ef1f84bSDavid du Colombier p->daddr = e->bid;
3869ef1f84bSDavid du Colombier k = kmap(p);
3879ef1f84bSDavid du Colombier if(waserror()) { /* buf may be virtual */
3889ef1f84bSDavid du Colombier kunmap(k);
3899ef1f84bSDavid du Colombier nexterror();
3909ef1f84bSDavid du Colombier }
3919ef1f84bSDavid du Colombier memmove((void*)VA(k), buf, l);
3929ef1f84bSDavid du Colombier poperror();
3939ef1f84bSDavid du Colombier kunmap(k);
3949ef1f84bSDavid du Colombier
3959ef1f84bSDavid du Colombier cachepage(p, &fscache);
3969ef1f84bSDavid du Colombier putpage(p);
3979ef1f84bSDavid du Colombier
3989ef1f84bSDavid du Colombier buf += l;
3999ef1f84bSDavid du Colombier offset += l;
4009ef1f84bSDavid du Colombier len -= l;
4019ef1f84bSDavid du Colombier
4029ef1f84bSDavid du Colombier *t = e;
4039ef1f84bSDavid du Colombier *tail = e;
4049ef1f84bSDavid du Colombier t = &e->next;
4059ef1f84bSDavid du Colombier }
4069ef1f84bSDavid du Colombier
4079ef1f84bSDavid du Colombier return start;
4089ef1f84bSDavid du Colombier }
4099ef1f84bSDavid du Colombier
4109ef1f84bSDavid du Colombier int
cpgmove(Extent * e,uchar * buf,int boff,int len)4119ef1f84bSDavid du Colombier cpgmove(Extent *e, uchar *buf, int boff, int len)
4129ef1f84bSDavid du Colombier {
4139ef1f84bSDavid du Colombier Page *p;
4149ef1f84bSDavid du Colombier KMap *k;
4159ef1f84bSDavid du Colombier
4169ef1f84bSDavid du Colombier p = cpage(e);
4179ef1f84bSDavid du Colombier if(p == 0)
4189ef1f84bSDavid du Colombier return 0;
4199ef1f84bSDavid du Colombier
4209ef1f84bSDavid du Colombier k = kmap(p);
4219ef1f84bSDavid du Colombier if(waserror()) { /* Since buf may be virtual */
4229ef1f84bSDavid du Colombier kunmap(k);
4239ef1f84bSDavid du Colombier nexterror();
4249ef1f84bSDavid du Colombier }
4259ef1f84bSDavid du Colombier
4269ef1f84bSDavid du Colombier memmove((uchar*)VA(k)+boff, buf, len);
4279ef1f84bSDavid du Colombier
4289ef1f84bSDavid du Colombier poperror();
4299ef1f84bSDavid du Colombier kunmap(k);
4309ef1f84bSDavid du Colombier putpage(p);
4319ef1f84bSDavid du Colombier
4329ef1f84bSDavid du Colombier return 1;
4339ef1f84bSDavid du Colombier }
4349ef1f84bSDavid du Colombier
4359ef1f84bSDavid du Colombier void
cupdate(Chan * c,uchar * buf,int len,vlong off)4369ef1f84bSDavid du Colombier cupdate(Chan *c, uchar *buf, int len, vlong off)
4379ef1f84bSDavid du Colombier {
4389ef1f84bSDavid du Colombier Mntcache *mc;
4399ef1f84bSDavid du Colombier Extent *tail;
4409ef1f84bSDavid du Colombier Extent *e, *f, *p;
4419ef1f84bSDavid du Colombier int o, ee, eblock;
4429ef1f84bSDavid du Colombier ulong offset;
4439ef1f84bSDavid du Colombier
4449ef1f84bSDavid du Colombier if(off > maxcache || len == 0)
4459ef1f84bSDavid du Colombier return;
4469ef1f84bSDavid du Colombier
4479ef1f84bSDavid du Colombier mc = c->mc;
4489ef1f84bSDavid du Colombier if(mc == nil)
4499ef1f84bSDavid du Colombier return;
4509ef1f84bSDavid du Colombier qlock(mc);
4519ef1f84bSDavid du Colombier if(cdev(mc, c) == 0) {
4529ef1f84bSDavid du Colombier qunlock(mc);
4539ef1f84bSDavid du Colombier return;
4549ef1f84bSDavid du Colombier }
4559ef1f84bSDavid du Colombier
4569ef1f84bSDavid du Colombier /*
4579ef1f84bSDavid du Colombier * Find the insertion point
4589ef1f84bSDavid du Colombier */
4599ef1f84bSDavid du Colombier offset = off;
4609ef1f84bSDavid du Colombier p = 0;
4619ef1f84bSDavid du Colombier for(f = mc->list; f; f = f->next) {
4629ef1f84bSDavid du Colombier if(f->start > offset)
4639ef1f84bSDavid du Colombier break;
4649ef1f84bSDavid du Colombier p = f;
4659ef1f84bSDavid du Colombier }
4669ef1f84bSDavid du Colombier
4679ef1f84bSDavid du Colombier /* trim if there is a successor */
4689ef1f84bSDavid du Colombier eblock = offset+len;
4699ef1f84bSDavid du Colombier if(f != 0 && eblock > f->start) {
4709ef1f84bSDavid du Colombier len -= (eblock - f->start);
4719ef1f84bSDavid du Colombier if(len <= 0) {
4729ef1f84bSDavid du Colombier qunlock(mc);
4739ef1f84bSDavid du Colombier return;
4749ef1f84bSDavid du Colombier }
4759ef1f84bSDavid du Colombier }
4769ef1f84bSDavid du Colombier
4779ef1f84bSDavid du Colombier if(p == 0) { /* at the head */
4789ef1f84bSDavid du Colombier e = cchain(buf, offset, len, &tail);
4799ef1f84bSDavid du Colombier if(e != 0) {
4809ef1f84bSDavid du Colombier mc->list = e;
4819ef1f84bSDavid du Colombier tail->next = f;
4829ef1f84bSDavid du Colombier }
4839ef1f84bSDavid du Colombier qunlock(mc);
4849ef1f84bSDavid du Colombier return;
4859ef1f84bSDavid du Colombier }
4869ef1f84bSDavid du Colombier
4879ef1f84bSDavid du Colombier /* trim to the predecessor */
4889ef1f84bSDavid du Colombier ee = p->start+p->len;
4899ef1f84bSDavid du Colombier if(offset < ee) {
4909ef1f84bSDavid du Colombier o = ee - offset;
4919ef1f84bSDavid du Colombier len -= o;
4929ef1f84bSDavid du Colombier if(len <= 0) {
4939ef1f84bSDavid du Colombier qunlock(mc);
4949ef1f84bSDavid du Colombier return;
4959ef1f84bSDavid du Colombier }
4969ef1f84bSDavid du Colombier buf += o;
4979ef1f84bSDavid du Colombier offset += o;
4989ef1f84bSDavid du Colombier }
4999ef1f84bSDavid du Colombier
5009ef1f84bSDavid du Colombier /* try and pack data into the predecessor */
5019ef1f84bSDavid du Colombier if(offset == ee && p->len < PGSZ) {
5029ef1f84bSDavid du Colombier o = len;
5039ef1f84bSDavid du Colombier if(o > PGSZ - p->len)
5049ef1f84bSDavid du Colombier o = PGSZ - p->len;
5059ef1f84bSDavid du Colombier if(cpgmove(p, buf, p->len, o)) {
5069ef1f84bSDavid du Colombier p->len += o;
5079ef1f84bSDavid du Colombier buf += o;
5089ef1f84bSDavid du Colombier len -= o;
5099ef1f84bSDavid du Colombier offset += o;
5109ef1f84bSDavid du Colombier if(len <= 0) {
5119ef1f84bSDavid du Colombier if(f && p->start + p->len > f->start) print("CACHE: p->start=%uld p->len=%d f->start=%uld\n", p->start, p->len, f->start);
5129ef1f84bSDavid du Colombier qunlock(mc);
5139ef1f84bSDavid du Colombier return;
5149ef1f84bSDavid du Colombier }
5159ef1f84bSDavid du Colombier }
5169ef1f84bSDavid du Colombier }
5179ef1f84bSDavid du Colombier
5189ef1f84bSDavid du Colombier e = cchain(buf, offset, len, &tail);
5199ef1f84bSDavid du Colombier if(e != 0) {
5209ef1f84bSDavid du Colombier p->next = e;
5219ef1f84bSDavid du Colombier tail->next = f;
5229ef1f84bSDavid du Colombier }
5239ef1f84bSDavid du Colombier qunlock(mc);
5249ef1f84bSDavid du Colombier }
5259ef1f84bSDavid du Colombier
5269ef1f84bSDavid du Colombier void
cwrite(Chan * c,uchar * buf,int len,vlong off)5279ef1f84bSDavid du Colombier cwrite(Chan* c, uchar *buf, int len, vlong off)
5289ef1f84bSDavid du Colombier {
5299ef1f84bSDavid du Colombier int o, eo;
5309ef1f84bSDavid du Colombier Mntcache *mc;
5319ef1f84bSDavid du Colombier ulong eblock, ee;
5329ef1f84bSDavid du Colombier Extent *p, *f, *e, *tail;
5339ef1f84bSDavid du Colombier ulong offset;
5349ef1f84bSDavid du Colombier
5359ef1f84bSDavid du Colombier if(off > maxcache || len == 0)
5369ef1f84bSDavid du Colombier return;
5379ef1f84bSDavid du Colombier
5389ef1f84bSDavid du Colombier mc = c->mc;
5399ef1f84bSDavid du Colombier if(mc == nil)
5409ef1f84bSDavid du Colombier return;
5419ef1f84bSDavid du Colombier
5429ef1f84bSDavid du Colombier qlock(mc);
5439ef1f84bSDavid du Colombier if(cdev(mc, c) == 0) {
5449ef1f84bSDavid du Colombier qunlock(mc);
5459ef1f84bSDavid du Colombier return;
5469ef1f84bSDavid du Colombier }
5479ef1f84bSDavid du Colombier
5489ef1f84bSDavid du Colombier offset = off;
5499ef1f84bSDavid du Colombier mc->qid.vers++;
5509ef1f84bSDavid du Colombier c->qid.vers++;
5519ef1f84bSDavid du Colombier
5529ef1f84bSDavid du Colombier p = 0;
5539ef1f84bSDavid du Colombier for(f = mc->list; f; f = f->next) {
5549ef1f84bSDavid du Colombier if(f->start >= offset)
5559ef1f84bSDavid du Colombier break;
5569ef1f84bSDavid du Colombier p = f;
5579ef1f84bSDavid du Colombier }
5589ef1f84bSDavid du Colombier
5599ef1f84bSDavid du Colombier if(p != 0) {
5609ef1f84bSDavid du Colombier ee = p->start+p->len;
5619ef1f84bSDavid du Colombier eo = offset - p->start;
5629ef1f84bSDavid du Colombier /* pack in predecessor if there is space */
5639ef1f84bSDavid du Colombier if(offset <= ee && eo < PGSZ) {
5649ef1f84bSDavid du Colombier o = len;
5659ef1f84bSDavid du Colombier if(o > PGSZ - eo)
5669ef1f84bSDavid du Colombier o = PGSZ - eo;
5679ef1f84bSDavid du Colombier if(cpgmove(p, buf, eo, o)) {
5689ef1f84bSDavid du Colombier if(eo+o > p->len)
5699ef1f84bSDavid du Colombier p->len = eo+o;
5709ef1f84bSDavid du Colombier buf += o;
5719ef1f84bSDavid du Colombier len -= o;
5729ef1f84bSDavid du Colombier offset += o;
5739ef1f84bSDavid du Colombier }
5749ef1f84bSDavid du Colombier }
5759ef1f84bSDavid du Colombier }
5769ef1f84bSDavid du Colombier
5779ef1f84bSDavid du Colombier /* free the overlap -- it's a rare case */
5789ef1f84bSDavid du Colombier eblock = offset+len;
5799ef1f84bSDavid du Colombier while(f && f->start < eblock) {
5809ef1f84bSDavid du Colombier e = f->next;
5819ef1f84bSDavid du Colombier extentfree(f);
5829ef1f84bSDavid du Colombier f = e;
5839ef1f84bSDavid du Colombier }
5849ef1f84bSDavid du Colombier
5859ef1f84bSDavid du Colombier /* link the block (if any) into the middle */
5869ef1f84bSDavid du Colombier e = cchain(buf, offset, len, &tail);
5879ef1f84bSDavid du Colombier if(e != 0) {
5889ef1f84bSDavid du Colombier tail->next = f;
5899ef1f84bSDavid du Colombier f = e;
5909ef1f84bSDavid du Colombier }
5919ef1f84bSDavid du Colombier
5929ef1f84bSDavid du Colombier if(p == 0)
5939ef1f84bSDavid du Colombier mc->list = f;
5949ef1f84bSDavid du Colombier else
5959ef1f84bSDavid du Colombier p->next = f;
5969ef1f84bSDavid du Colombier qunlock(mc);
5979ef1f84bSDavid du Colombier }
598