1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "logfs.h"
337da2899SCharles.Forsyth #include "local.h"
437da2899SCharles.Forsyth #include "fcall.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth struct DirReadState {
737da2899SCharles.Forsyth u32int offset;
837da2899SCharles.Forsyth u32int lastoffset;
937da2899SCharles.Forsyth u32int limit;
1037da2899SCharles.Forsyth uchar *data;
1137da2899SCharles.Forsyth };
1237da2899SCharles.Forsyth
1337da2899SCharles.Forsyth typedef struct ReaderState {
1437da2899SCharles.Forsyth uchar *buf;
1537da2899SCharles.Forsyth u32int maxoffset;
1637da2899SCharles.Forsyth LogfsServer *server;
1737da2899SCharles.Forsyth char *errmsg;
1837da2899SCharles.Forsyth } ReaderState;
1937da2899SCharles.Forsyth
2037da2899SCharles.Forsyth static DirReadState *
drsinit(LogfsIdentityStore * is,Entry * list,uchar * buf,u32int buflen,u32int * rcount)2137da2899SCharles.Forsyth drsinit(LogfsIdentityStore *is, Entry *list, uchar *buf, u32int buflen, u32int *rcount)
2237da2899SCharles.Forsyth {
2337da2899SCharles.Forsyth Entry *p, *q;
2437da2899SCharles.Forsyth DirReadState *drs;
2537da2899SCharles.Forsyth u32int k;
2637da2899SCharles.Forsyth /*
2737da2899SCharles.Forsyth * stash as many entries as will fit in the read buffer
2837da2899SCharles.Forsyth */
2937da2899SCharles.Forsyth *rcount = 0;
3037da2899SCharles.Forsyth for(p = list; p; p = p->next) {
3137da2899SCharles.Forsyth uint len = logfsflattenentry(is, buf, buflen, p);
3237da2899SCharles.Forsyth if(len == 0)
3337da2899SCharles.Forsyth break;
3437da2899SCharles.Forsyth *rcount += len;
3537da2899SCharles.Forsyth buf += len;
3637da2899SCharles.Forsyth buflen -= len;
3737da2899SCharles.Forsyth }
3837da2899SCharles.Forsyth drs = logfsrealloc(nil, sizeof(*drs));
3937da2899SCharles.Forsyth if(drs == nil)
4037da2899SCharles.Forsyth return nil;
4137da2899SCharles.Forsyth drs->offset = *rcount;
4237da2899SCharles.Forsyth drs->lastoffset = drs->offset;
4337da2899SCharles.Forsyth k = 0;
4437da2899SCharles.Forsyth for(q = p; q; q = q->next)
4537da2899SCharles.Forsyth k += logfsflattenentry(is, nil, 0, q);
4637da2899SCharles.Forsyth if(k) {
4737da2899SCharles.Forsyth u32int k2;
4837da2899SCharles.Forsyth // print("drsinit: %ud bytes extra\n", k);
4937da2899SCharles.Forsyth drs->data = logfsrealloc(nil, k);
5037da2899SCharles.Forsyth if(drs->data == nil) {
5137da2899SCharles.Forsyth logfsfreemem(drs);
5237da2899SCharles.Forsyth return nil;
5337da2899SCharles.Forsyth }
5437da2899SCharles.Forsyth k2 = 0;
5537da2899SCharles.Forsyth for(q = p; q; q = q->next)
5637da2899SCharles.Forsyth k2 += logfsflattenentry(is, drs->data + k2, k - k2, q);
5737da2899SCharles.Forsyth drs->limit = drs->offset + k;
5837da2899SCharles.Forsyth }
5937da2899SCharles.Forsyth // print("drsinit: rcount %ud\n", *rcount);
6037da2899SCharles.Forsyth return drs;
6137da2899SCharles.Forsyth }
6237da2899SCharles.Forsyth
6337da2899SCharles.Forsyth static void
drsread(DirReadState * drs,uchar * buf,u32int buflen,u32int * rcount)6437da2899SCharles.Forsyth drsread(DirReadState *drs, uchar *buf, u32int buflen, u32int *rcount)
6537da2899SCharles.Forsyth {
6637da2899SCharles.Forsyth uchar *p;
6737da2899SCharles.Forsyth *rcount = 0;
6837da2899SCharles.Forsyth p = drs->data + drs->lastoffset - drs->offset;
6937da2899SCharles.Forsyth while(drs->lastoffset < drs->limit) {
7037da2899SCharles.Forsyth /*
7137da2899SCharles.Forsyth * copy an entry, if it fits
7237da2899SCharles.Forsyth */
7337da2899SCharles.Forsyth uint len = GBIT16(p) + BIT16SZ;
7437da2899SCharles.Forsyth if(len > buflen)
7537da2899SCharles.Forsyth break;
76*28942eadSforsyth memmove(buf, p, len);
7737da2899SCharles.Forsyth drs->lastoffset += len;
7837da2899SCharles.Forsyth *rcount += len;
7937da2899SCharles.Forsyth buf += len;
8037da2899SCharles.Forsyth buflen -= len;
8137da2899SCharles.Forsyth p += len;
8237da2899SCharles.Forsyth }
8337da2899SCharles.Forsyth if(drs->lastoffset >= drs->limit) {
8437da2899SCharles.Forsyth logfsfreemem(drs->data);
8537da2899SCharles.Forsyth drs->data = nil;
8637da2899SCharles.Forsyth }
8737da2899SCharles.Forsyth }
8837da2899SCharles.Forsyth
8937da2899SCharles.Forsyth void
logfsdrsfree(DirReadState ** drsp)9037da2899SCharles.Forsyth logfsdrsfree(DirReadState **drsp)
9137da2899SCharles.Forsyth {
9237da2899SCharles.Forsyth DirReadState *drs = *drsp;
9337da2899SCharles.Forsyth if(drs) {
9437da2899SCharles.Forsyth logfsfreemem(drs->data);
9537da2899SCharles.Forsyth logfsfreemem(drs);
9637da2899SCharles.Forsyth *drsp = nil;
9737da2899SCharles.Forsyth }
9837da2899SCharles.Forsyth }
9937da2899SCharles.Forsyth
10037da2899SCharles.Forsyth static int
reader(void * magic,u32int baseoffset,u32int limitoffset,Extent * e,u32int extentoffset)10137da2899SCharles.Forsyth reader(void *magic, u32int baseoffset, u32int limitoffset, Extent *e, u32int extentoffset)
10237da2899SCharles.Forsyth {
10337da2899SCharles.Forsyth ReaderState *s = magic;
10437da2899SCharles.Forsyth LogfsServer *server;
10537da2899SCharles.Forsyth LogfsLowLevel *ll;
10637da2899SCharles.Forsyth LogfsLowLevelReadResult llrr;
10737da2899SCharles.Forsyth long seq;
10837da2899SCharles.Forsyth int page;
10937da2899SCharles.Forsyth int offset;
11037da2899SCharles.Forsyth long block;
11137da2899SCharles.Forsyth int pagesize;
11237da2899SCharles.Forsyth LogSegment *seg;
11337da2899SCharles.Forsyth int replace;
11437da2899SCharles.Forsyth
11537da2899SCharles.Forsyth if(e == nil) {
11637da2899SCharles.Forsyth //print("fill(%d, %d)\n", baseoffset, limitoffset);
11737da2899SCharles.Forsyth memset(s->buf + baseoffset, 0, limitoffset - baseoffset);
11837da2899SCharles.Forsyth if(limitoffset > s->maxoffset)
11937da2899SCharles.Forsyth s->maxoffset = limitoffset;
12037da2899SCharles.Forsyth return 1;
12137da2899SCharles.Forsyth }
12237da2899SCharles.Forsyth server = s->server;
12337da2899SCharles.Forsyth ll = server->ll;
12437da2899SCharles.Forsyth /*
12537da2899SCharles.Forsyth * extentoffset is how much to trim off the front of the extent
12637da2899SCharles.Forsyth */
12737da2899SCharles.Forsyth logfsflashaddr2spo(server, e->flashaddr + extentoffset, &seq, &page, &offset);
12837da2899SCharles.Forsyth /*
12937da2899SCharles.Forsyth * offset is the offset within the page to where e->min is stored
13037da2899SCharles.Forsyth */
13137da2899SCharles.Forsyth //print("read(%d, %d, %c%ld/%ud/%ud)\n",
13237da2899SCharles.Forsyth // baseoffset, limitoffset, (e->flashaddr & LogAddr) ? 'L' : 'D', seq, page, offset);
13337da2899SCharles.Forsyth if(e->flashaddr & LogAddr) {
13437da2899SCharles.Forsyth if(seq >= server->activelog->unsweptblockindex && seq <= server->activelog->curblockindex)
13537da2899SCharles.Forsyth seg = server->activelog;
13637da2899SCharles.Forsyth else if(server->sweptlog && seq <= server->sweptlog->curblockindex)
13737da2899SCharles.Forsyth seg = server->sweptlog;
13837da2899SCharles.Forsyth else {
13937da2899SCharles.Forsyth print("logfsserverread: illegal log sequence number %ld (active=[%ld, %ld], swept=[%ld, %ld])\n",
14037da2899SCharles.Forsyth seq, server->activelog->unsweptblockindex, server->activelog->curblockindex,
14137da2899SCharles.Forsyth server->sweptlog ? 0L : -1L, server->sweptlog ? server->sweptlog->curblockindex : -1L);
14237da2899SCharles.Forsyth s->errmsg = logfseinternal;
14337da2899SCharles.Forsyth return -1;
14437da2899SCharles.Forsyth }
14537da2899SCharles.Forsyth if(seg->curpage == page && seg->curblockindex == seq) {
14637da2899SCharles.Forsyth /*
14737da2899SCharles.Forsyth * it hasn't made it to disk yet
14837da2899SCharles.Forsyth */
149*28942eadSforsyth memmove(s->buf + baseoffset, seg->pagebuf + offset, limitoffset - baseoffset);
15037da2899SCharles.Forsyth goto done;
15137da2899SCharles.Forsyth }
15237da2899SCharles.Forsyth if(seq < seg->unsweptblockindex) {
15337da2899SCharles.Forsyth /* data already swept */
15437da2899SCharles.Forsyth print("logfsserverread: log address has been swept\n");
15537da2899SCharles.Forsyth s->errmsg = logfseinternal;
15637da2899SCharles.Forsyth return -1;
15737da2899SCharles.Forsyth }
15837da2899SCharles.Forsyth block = seg->blockmap[seq];
15937da2899SCharles.Forsyth }
16037da2899SCharles.Forsyth else {
16137da2899SCharles.Forsyth seg = nil;
16237da2899SCharles.Forsyth if(seq >= server->ndatablocks)
16337da2899SCharles.Forsyth block = -1;
16437da2899SCharles.Forsyth else
16537da2899SCharles.Forsyth block = server->datablock[seq].block;
16637da2899SCharles.Forsyth if(block < 0) {
16737da2899SCharles.Forsyth print("logfsserveread: data address does not exist\n");
16837da2899SCharles.Forsyth s->errmsg = logfseinternal;
16937da2899SCharles.Forsyth return -1;
17037da2899SCharles.Forsyth }
17137da2899SCharles.Forsyth }
17237da2899SCharles.Forsyth /*
17337da2899SCharles.Forsyth * read as many pages as necessary to get to the limitoffset
17437da2899SCharles.Forsyth */
17537da2899SCharles.Forsyth pagesize = 1 << ll->l2pagesize;
17637da2899SCharles.Forsyth replace = 0;
17737da2899SCharles.Forsyth while(baseoffset < limitoffset) {
17837da2899SCharles.Forsyth u32int thistime;
17937da2899SCharles.Forsyth thistime = pagesize - offset;
18037da2899SCharles.Forsyth if(thistime > (limitoffset - baseoffset))
18137da2899SCharles.Forsyth thistime = limitoffset - baseoffset;
18237da2899SCharles.Forsyth s->errmsg = (*ll->readpagerange)(ll, s->buf + baseoffset, block, page,
18337da2899SCharles.Forsyth offset, thistime, &llrr);
18437da2899SCharles.Forsyth if(s->errmsg)
18537da2899SCharles.Forsyth return -1;
18637da2899SCharles.Forsyth if(llrr != LogfsLowLevelReadResultOk) {
18737da2899SCharles.Forsyth replace = 1;
18837da2899SCharles.Forsyth }
18937da2899SCharles.Forsyth baseoffset += thistime;
19037da2899SCharles.Forsyth page++;
19137da2899SCharles.Forsyth offset = 0;
19237da2899SCharles.Forsyth }
19337da2899SCharles.Forsyth if(replace) {
19437da2899SCharles.Forsyth s->errmsg = logfsserverreplaceblock(server, seg, seq);
19537da2899SCharles.Forsyth if(s->errmsg)
19637da2899SCharles.Forsyth return -1;
19737da2899SCharles.Forsyth }
19837da2899SCharles.Forsyth done:
19937da2899SCharles.Forsyth if(limitoffset > s->maxoffset)
20037da2899SCharles.Forsyth s->maxoffset = limitoffset;
20137da2899SCharles.Forsyth return 1;
20237da2899SCharles.Forsyth }
20337da2899SCharles.Forsyth
20437da2899SCharles.Forsyth char *
logfsserverread(LogfsServer * server,u32int fid,u32int offset,u32int count,uchar * buf,u32int buflen,u32int * rcount)20537da2899SCharles.Forsyth logfsserverread(LogfsServer *server, u32int fid, u32int offset, u32int count, uchar *buf, u32int buflen, u32int *rcount)
20637da2899SCharles.Forsyth {
20737da2899SCharles.Forsyth Fid *f;
20837da2899SCharles.Forsyth Entry *e;
20937da2899SCharles.Forsyth ReaderState s;
21037da2899SCharles.Forsyth int rv;
21137da2899SCharles.Forsyth
21237da2899SCharles.Forsyth if(server->trace > 1)
21337da2899SCharles.Forsyth print("logfsserverread(%ud, %ud, %ud)\n", fid, offset, count);
21437da2899SCharles.Forsyth f = logfsfidmapfindentry(server->fidmap, fid);
21537da2899SCharles.Forsyth if(f == nil)
21637da2899SCharles.Forsyth return logfsebadfid;
21737da2899SCharles.Forsyth if(f->openmode < 0)
21837da2899SCharles.Forsyth return logfsefidnotopen;
21937da2899SCharles.Forsyth if((f->openmode & 3) == OWRITE)
22037da2899SCharles.Forsyth return logfseaccess;
22137da2899SCharles.Forsyth if(count > buflen)
22237da2899SCharles.Forsyth return Etoobig;
22337da2899SCharles.Forsyth e = f->entry;
22437da2899SCharles.Forsyth if(e->deadandgone)
22537da2899SCharles.Forsyth return Eio;
22637da2899SCharles.Forsyth if(e->qid.type & QTDIR) {
22737da2899SCharles.Forsyth if(offset != 0) {
22837da2899SCharles.Forsyth if(f->drs == nil || f->drs->lastoffset != offset)
22937da2899SCharles.Forsyth return Eio;
23037da2899SCharles.Forsyth drsread(f->drs, buf, count, rcount);
23137da2899SCharles.Forsyth }
23237da2899SCharles.Forsyth else {
23337da2899SCharles.Forsyth logfsdrsfree(&f->drs);
23437da2899SCharles.Forsyth f->drs = drsinit(server->is, e->u.dir.list, buf, count, rcount);
23537da2899SCharles.Forsyth if(f->drs == nil)
23637da2899SCharles.Forsyth return Enomem;
23737da2899SCharles.Forsyth }
23837da2899SCharles.Forsyth return nil;
23937da2899SCharles.Forsyth }
24037da2899SCharles.Forsyth if(offset >= e->u.file.length) {
24137da2899SCharles.Forsyth *rcount = 0;
24237da2899SCharles.Forsyth return nil;
24337da2899SCharles.Forsyth }
24437da2899SCharles.Forsyth s.buf = buf;
24537da2899SCharles.Forsyth s.server = server;
24637da2899SCharles.Forsyth s.maxoffset = 0;
24737da2899SCharles.Forsyth rv = logfsextentlistwalkrange(e->u.file.extent, reader, &s, offset, offset + count);
24837da2899SCharles.Forsyth if(rv < 0)
24937da2899SCharles.Forsyth return s.errmsg;
25037da2899SCharles.Forsyth *rcount = s.maxoffset;
25137da2899SCharles.Forsyth return nil;
25237da2899SCharles.Forsyth }
25337da2899SCharles.Forsyth
254