1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "logfs.h"
337da2899SCharles.Forsyth #include "local.h"
437da2899SCharles.Forsyth #include "fcall.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth void
logfsflashaddr2spo(LogfsServer * server,u32int flashaddr,long * seq,int * page,int * offset)737da2899SCharles.Forsyth logfsflashaddr2spo(LogfsServer *server, u32int flashaddr, long *seq, int *page, int *offset)
837da2899SCharles.Forsyth {
937da2899SCharles.Forsyth LogfsLowLevel *ll = server->ll;
1037da2899SCharles.Forsyth flashaddr &= ~LogAddr;
1137da2899SCharles.Forsyth *offset = flashaddr & ((1 << ll->l2pagesize) - 1);
1237da2899SCharles.Forsyth flashaddr >>= ll->l2pagesize;
1337da2899SCharles.Forsyth *page = flashaddr & ((1 << ll->l2pagesperblock) - 1);
1437da2899SCharles.Forsyth flashaddr >>= ll->l2pagesperblock;
1537da2899SCharles.Forsyth *seq = flashaddr;
1637da2899SCharles.Forsyth }
1737da2899SCharles.Forsyth
1837da2899SCharles.Forsyth u32int
logfsspo2flashaddr(LogfsServer * server,long seq,int page,int offset)1937da2899SCharles.Forsyth logfsspo2flashaddr(LogfsServer *server, long seq, int page, int offset)
2037da2899SCharles.Forsyth {
2137da2899SCharles.Forsyth //print("logfsspo2flashaddr(%ld, %d, %d)\n", seq, page, offset);
2237da2899SCharles.Forsyth return (((seq << server->ll->l2pagesperblock) + page) << server->ll->l2pagesize) + offset;
2337da2899SCharles.Forsyth }
2437da2899SCharles.Forsyth
2537da2899SCharles.Forsyth void
logfsflashaddr2o(LogfsServer * server,u32int flashaddr,int * offset)2637da2899SCharles.Forsyth logfsflashaddr2o(LogfsServer *server, u32int flashaddr, int *offset)
2737da2899SCharles.Forsyth {
2837da2899SCharles.Forsyth LogfsLowLevel *ll = server->ll;
2937da2899SCharles.Forsyth flashaddr &= ~LogAddr;
3037da2899SCharles.Forsyth *offset = flashaddr & ((1 << ll->l2pagesize) - 1);
3137da2899SCharles.Forsyth }
3237da2899SCharles.Forsyth
3337da2899SCharles.Forsyth char *
logfslogsegmentnew(LogfsServer * server,int gen,LogSegment ** segp)3437da2899SCharles.Forsyth logfslogsegmentnew(LogfsServer *server, int gen, LogSegment **segp)
3537da2899SCharles.Forsyth {
3637da2899SCharles.Forsyth LogSegment *seg;
3737da2899SCharles.Forsyth seg = logfsrealloc(nil, sizeof(LogSegment) + (server->ll->blocks - 1) * sizeof(long));
3837da2899SCharles.Forsyth if(seg == nil)
3937da2899SCharles.Forsyth return Enomem;
4037da2899SCharles.Forsyth seg->pagebuf = logfsrealloc(nil, 1 << server->ll->l2pagesize);
4137da2899SCharles.Forsyth if(seg->pagebuf == nil) {
4237da2899SCharles.Forsyth logfsfreemem(seg);
4337da2899SCharles.Forsyth return Enomem;
4437da2899SCharles.Forsyth }
4537da2899SCharles.Forsyth seg->curpage = -1;
4637da2899SCharles.Forsyth seg->curblockindex = -1;
4737da2899SCharles.Forsyth seg->gen = gen;
4837da2899SCharles.Forsyth *segp = seg;
4937da2899SCharles.Forsyth return nil;
5037da2899SCharles.Forsyth }
5137da2899SCharles.Forsyth
5237da2899SCharles.Forsyth void
logfslogsegmentfree(LogSegment ** segp)5337da2899SCharles.Forsyth logfslogsegmentfree(LogSegment **segp)
5437da2899SCharles.Forsyth {
5537da2899SCharles.Forsyth LogSegment *seg = *segp;
5637da2899SCharles.Forsyth if(seg) {
5737da2899SCharles.Forsyth logfsfreemem(seg->pagebuf);
5837da2899SCharles.Forsyth logfsfreemem(seg);
5937da2899SCharles.Forsyth *segp = nil;
6037da2899SCharles.Forsyth }
6137da2899SCharles.Forsyth }
6237da2899SCharles.Forsyth
6337da2899SCharles.Forsyth char *
logfslogsegmentflush(LogfsServer * server,int active)6437da2899SCharles.Forsyth logfslogsegmentflush(LogfsServer *server, int active)
6537da2899SCharles.Forsyth {
6637da2899SCharles.Forsyth LogSegment *seg;
6737da2899SCharles.Forsyth seg = active ? server->activelog : server->sweptlog;
6837da2899SCharles.Forsyth if(seg == nil)
6937da2899SCharles.Forsyth return nil;
7037da2899SCharles.Forsyth if(seg->curpage >= 0 && seg->nbytes) {
7137da2899SCharles.Forsyth char *errmsg;
7237da2899SCharles.Forsyth LogfsLowLevel *ll = server->ll;
7337da2899SCharles.Forsyth int pagesize = 1 << ll->l2pagesize;
7437da2899SCharles.Forsyth //print("curblockindex %ld curpage %d nbytes %d\n", seg->curblockindex, seg->curpage, seg->nbytes);
7537da2899SCharles.Forsyth if(seg->nbytes < pagesize)
7637da2899SCharles.Forsyth seg->pagebuf[seg->nbytes++] = LogfsLogTend;
7737da2899SCharles.Forsyth memset(seg->pagebuf + seg->nbytes, 0xff, pagesize - seg->nbytes);
7837da2899SCharles.Forsyth for(;;) {
7937da2899SCharles.Forsyth errmsg = (*ll->writepage)(ll, seg->pagebuf,
8037da2899SCharles.Forsyth seg->blockmap[seg->curblockindex], seg->curpage);
8137da2899SCharles.Forsyth if(errmsg == nil)
8237da2899SCharles.Forsyth break;
8337da2899SCharles.Forsyth if(strcmp(errmsg, Eio) != 0)
8437da2899SCharles.Forsyth return errmsg;
8537da2899SCharles.Forsyth errmsg = logfsserverreplacelogblock(server, seg, seg->curblockindex);
8637da2899SCharles.Forsyth if(errmsg)
8737da2899SCharles.Forsyth return errmsg;
8837da2899SCharles.Forsyth }
8937da2899SCharles.Forsyth seg->curpage++;
9037da2899SCharles.Forsyth if(seg->curpage == (1 << ll->l2pagesperblock))
9137da2899SCharles.Forsyth seg->curpage = -1;
9237da2899SCharles.Forsyth seg->nbytes = 0;
9337da2899SCharles.Forsyth }
9437da2899SCharles.Forsyth return nil;
9537da2899SCharles.Forsyth }
9637da2899SCharles.Forsyth
9737da2899SCharles.Forsyth static char *
logspace(LogfsServer * server,int active,int takearisk,int nbytes,uchar ** where,u32int * flashaddr)9837da2899SCharles.Forsyth logspace(LogfsServer *server, int active, int takearisk, int nbytes, uchar **where, u32int *flashaddr)
9937da2899SCharles.Forsyth {
10037da2899SCharles.Forsyth char *errmsg;
10137da2899SCharles.Forsyth LogfsLowLevel *ll = server->ll;
10237da2899SCharles.Forsyth int pagesize = 1 << ll->l2pagesize;
10337da2899SCharles.Forsyth LogSegment *seg;
10437da2899SCharles.Forsyth
10537da2899SCharles.Forsyth if(nbytes > pagesize)
10637da2899SCharles.Forsyth return logfselogmsgtoobig;
10737da2899SCharles.Forsyth retry:
10837da2899SCharles.Forsyth seg = active ? server->activelog : server->sweptlog;
10937da2899SCharles.Forsyth for(;;) {
11037da2899SCharles.Forsyth //print("curpage %d nbytes %d\n", seg->curpage, seg->nbytes);
11137da2899SCharles.Forsyth if(seg->curpage >= 0) {
11237da2899SCharles.Forsyth if(seg->nbytes + nbytes < pagesize)
11337da2899SCharles.Forsyth break;
11437da2899SCharles.Forsyth errmsg = logfslogsegmentflush(server, active);
11537da2899SCharles.Forsyth if(errmsg)
11637da2899SCharles.Forsyth return errmsg;
11737da2899SCharles.Forsyth }
11837da2899SCharles.Forsyth if(seg->curpage < 0) {
11937da2899SCharles.Forsyth long block;
12037da2899SCharles.Forsyth long path;
12137da2899SCharles.Forsyth block = logfsfindfreeblock(ll,
12237da2899SCharles.Forsyth active ? (takearisk ? AllocReasonLogExtend : AllocReasonDataExtend) : AllocReasonTransfer);
12337da2899SCharles.Forsyth if(block < 0) {
12437da2899SCharles.Forsyth if(active) {
12537da2899SCharles.Forsyth int didsomething;
12637da2899SCharles.Forsyth errmsg = logfsserverlogsweep(server, 0, &didsomething);
12737da2899SCharles.Forsyth if(errmsg)
12837da2899SCharles.Forsyth return errmsg;
12937da2899SCharles.Forsyth if(didsomething)
13037da2899SCharles.Forsyth goto retry;
13137da2899SCharles.Forsyth }
13237da2899SCharles.Forsyth return logfselogfull;
13337da2899SCharles.Forsyth }
13437da2899SCharles.Forsyth seg->blockmap[++seg->curblockindex] = block;
13537da2899SCharles.Forsyth path = mklogpath(seg->curblockindex, seg->gen, 0);
13637da2899SCharles.Forsyth (*ll->setblocktag)(ll, block, LogfsTlog);
13737da2899SCharles.Forsyth (*ll->setblockpath)(ll, block, path);
13837da2899SCharles.Forsyth seg->curpage = 0;
13937da2899SCharles.Forsyth #ifdef FUTURE
14037da2899SCharles.Forsyth /* TODO - do we need one of these if the underlying system supports erase counting? */
14137da2899SCharles.Forsyth seg->pagebuf[0] = LogfsLogTstart;
14237da2899SCharles.Forsyth PBIT16(seg->pagebuf + 1, 8);
14337da2899SCharles.Forsyth PBIT32(seg->pagebuf + 3, path); /* TODO duplicate information */
14437da2899SCharles.Forsyth PBIT32(seg->pagebuf + 7, 0); /* TODO don't have this - discuss with forsyth */
14537da2899SCharles.Forsyth seg->nbytes = 11;
14637da2899SCharles.Forsyth #else
14737da2899SCharles.Forsyth seg->nbytes = 0;
14837da2899SCharles.Forsyth #endif
14937da2899SCharles.Forsyth }
15037da2899SCharles.Forsyth }
15137da2899SCharles.Forsyth *where = seg->pagebuf + seg->nbytes;
15237da2899SCharles.Forsyth if(flashaddr)
15337da2899SCharles.Forsyth *flashaddr = logfsspo2flashaddr(server, seg->curblockindex, seg->curpage, seg->nbytes);
15437da2899SCharles.Forsyth seg->nbytes += nbytes;
15537da2899SCharles.Forsyth return nil;
15637da2899SCharles.Forsyth }
15737da2899SCharles.Forsyth
15837da2899SCharles.Forsyth static void
logdirty(LogfsServer * server,int active)15937da2899SCharles.Forsyth logdirty(LogfsServer *server, int active)
16037da2899SCharles.Forsyth {
16137da2899SCharles.Forsyth if(active)
16237da2899SCharles.Forsyth server->activelog->dirty = 1;
16337da2899SCharles.Forsyth else
16437da2899SCharles.Forsyth server->sweptlog->dirty = 1;
16537da2899SCharles.Forsyth }
16637da2899SCharles.Forsyth
16737da2899SCharles.Forsyth char *
logfslogbytes(LogfsServer * server,int active,uchar * msg,uint size)16837da2899SCharles.Forsyth logfslogbytes(LogfsServer *server, int active, uchar *msg, uint size)
16937da2899SCharles.Forsyth {
17037da2899SCharles.Forsyth char *errmsg;
17137da2899SCharles.Forsyth uchar *p;
17237da2899SCharles.Forsyth
17337da2899SCharles.Forsyth errmsg = logspace(server, active, 0, size, &p, nil);
17437da2899SCharles.Forsyth if(errmsg)
17537da2899SCharles.Forsyth return errmsg;
176*28942eadSforsyth memmove(p, msg, size);
17737da2899SCharles.Forsyth logdirty(server, active);
17837da2899SCharles.Forsyth return nil;
17937da2899SCharles.Forsyth }
18037da2899SCharles.Forsyth
18137da2899SCharles.Forsyth char *
logfslog(LogfsServer * server,int active,LogMessage * s)18237da2899SCharles.Forsyth logfslog(LogfsServer *server, int active, LogMessage *s)
18337da2899SCharles.Forsyth {
18437da2899SCharles.Forsyth uint size = logfssizeS2M(s);
18537da2899SCharles.Forsyth char *errmsg;
18637da2899SCharles.Forsyth uchar *p;
18737da2899SCharles.Forsyth int takearisk;
18837da2899SCharles.Forsyth
18937da2899SCharles.Forsyth if(server->trace > 1) {
19037da2899SCharles.Forsyth print("%c<< ", active ? 'A' : 'S');
19137da2899SCharles.Forsyth logfsdumpS(s);
19237da2899SCharles.Forsyth print("\n");
19337da2899SCharles.Forsyth }
19437da2899SCharles.Forsyth if(active) {
19537da2899SCharles.Forsyth switch(s->type) {
19637da2899SCharles.Forsyth case LogfsLogTremove:
19737da2899SCharles.Forsyth case LogfsLogTtrunc:
19837da2899SCharles.Forsyth takearisk = 1;
19937da2899SCharles.Forsyth break;
20037da2899SCharles.Forsyth default:
20137da2899SCharles.Forsyth takearisk = 0;
20237da2899SCharles.Forsyth }
20337da2899SCharles.Forsyth }
20437da2899SCharles.Forsyth else
20537da2899SCharles.Forsyth takearisk = 0;
20637da2899SCharles.Forsyth errmsg = logspace(server, active, takearisk, size, &p, nil);
20737da2899SCharles.Forsyth if(errmsg)
20837da2899SCharles.Forsyth return errmsg;
20937da2899SCharles.Forsyth if(logfsconvS2M(s, p, size) != size)
21037da2899SCharles.Forsyth return "bad conversion";
21137da2899SCharles.Forsyth logdirty(server, active);
21237da2899SCharles.Forsyth return nil;
21337da2899SCharles.Forsyth }
21437da2899SCharles.Forsyth
21537da2899SCharles.Forsyth int
lognicesizeforwrite(LogfsServer * server,int active,u32int count,int muidlen)21637da2899SCharles.Forsyth lognicesizeforwrite(LogfsServer *server, int active, u32int count, int muidlen)
21737da2899SCharles.Forsyth {
21837da2899SCharles.Forsyth int rawspace;
21937da2899SCharles.Forsyth LogSegment *seg;
22037da2899SCharles.Forsyth if(count > LogDataLimit)
22137da2899SCharles.Forsyth return 0;
22237da2899SCharles.Forsyth seg = active ? server->activelog : server->sweptlog;
22337da2899SCharles.Forsyth if(seg->curpage < 0)
22437da2899SCharles.Forsyth return LogDataLimit;
22537da2899SCharles.Forsyth rawspace = (1 << server->ll->l2pagesize) - seg->nbytes;
22637da2899SCharles.Forsyth if(rawspace < 5 * 4 + 2 + muidlen + 1)
22737da2899SCharles.Forsyth return LogDataLimit;
22837da2899SCharles.Forsyth return 5 * 4 + 2 + muidlen - rawspace;
22937da2899SCharles.Forsyth }
23037da2899SCharles.Forsyth
23137da2899SCharles.Forsyth char *
logfslogwrite(LogfsServer * server,int active,u32int path,u32int offset,int count,u32int mtime,u32int cvers,char * muid,uchar * data,u32int * flashaddr)23237da2899SCharles.Forsyth logfslogwrite(LogfsServer *server, int active, u32int path, u32int offset, int count, u32int mtime, u32int cvers,
23337da2899SCharles.Forsyth char *muid, uchar *data, u32int *flashaddr)
23437da2899SCharles.Forsyth {
23537da2899SCharles.Forsyth /* 'w' size[2] path[4] offset[4] count[2] mtime[4] cvers[4] muid[s] flashaddr[4] [data[n]] */
23637da2899SCharles.Forsyth LogMessage s;
23737da2899SCharles.Forsyth uint size;
23837da2899SCharles.Forsyth char *errmsg;
23937da2899SCharles.Forsyth uchar *p;
24037da2899SCharles.Forsyth u32int faddr;
24137da2899SCharles.Forsyth uint asize;
24237da2899SCharles.Forsyth
24337da2899SCharles.Forsyth s.type = LogfsLogTwrite;
24437da2899SCharles.Forsyth s.path = path;
24537da2899SCharles.Forsyth s.u.write.offset = offset;
24637da2899SCharles.Forsyth s.u.write.count = count;
24737da2899SCharles.Forsyth s.u.write.mtime = mtime;
24837da2899SCharles.Forsyth s.u.write.cvers = cvers;
24937da2899SCharles.Forsyth s.u.write.muid = muid;
25037da2899SCharles.Forsyth s.u.write.data = data;
25137da2899SCharles.Forsyth size = logfssizeS2M(&s);
25237da2899SCharles.Forsyth errmsg = logspace(server, active, 0, size, &p, &faddr);
25337da2899SCharles.Forsyth if(errmsg)
25437da2899SCharles.Forsyth return errmsg;
25537da2899SCharles.Forsyth if(data)
25637da2899SCharles.Forsyth *flashaddr = (faddr + size - count) | LogAddr;
25737da2899SCharles.Forsyth s.u.write.flashaddr = *flashaddr;
25837da2899SCharles.Forsyth if(server->trace > 1) {
25937da2899SCharles.Forsyth print("%c<< ", active ? 'A' : 'S');
26037da2899SCharles.Forsyth logfsdumpS(&s);
26137da2899SCharles.Forsyth print("\n");
26237da2899SCharles.Forsyth }
26337da2899SCharles.Forsyth if((asize = logfsconvS2M(&s, p, size)) != size) {
26437da2899SCharles.Forsyth print("expected %d actual %d\n", size, asize);
26537da2899SCharles.Forsyth return "bad conversion";
26637da2899SCharles.Forsyth }
26737da2899SCharles.Forsyth logdirty(server, active);
26837da2899SCharles.Forsyth return nil;
26937da2899SCharles.Forsyth }
27037da2899SCharles.Forsyth
271