123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- #include "logfsos.h"
- #include "logfs.h"
- #include "local.h"
- #include "fcall.h"
- void
- logfsflashaddr2spo(LogfsServer *server, u32int flashaddr, long *seq, int *page, int *offset)
- {
- LogfsLowLevel *ll = server->ll;
- flashaddr &= ~LogAddr;
- *offset = flashaddr & ((1 << ll->l2pagesize) - 1);
- flashaddr >>= ll->l2pagesize;
- *page = flashaddr & ((1 << ll->l2pagesperblock) - 1);
- flashaddr >>= ll->l2pagesperblock;
- *seq = flashaddr;
- }
- u32int
- logfsspo2flashaddr(LogfsServer *server, long seq, int page, int offset)
- {
- //print("logfsspo2flashaddr(%ld, %d, %d)\n", seq, page, offset);
- return (((seq << server->ll->l2pagesperblock) + page) << server->ll->l2pagesize) + offset;
- }
- void
- logfsflashaddr2o(LogfsServer *server, u32int flashaddr, int *offset)
- {
- LogfsLowLevel *ll = server->ll;
- flashaddr &= ~LogAddr;
- *offset = flashaddr & ((1 << ll->l2pagesize) - 1);
- }
- char *
- logfslogsegmentnew(LogfsServer *server, int gen, LogSegment **segp)
- {
- LogSegment *seg;
- seg = logfsrealloc(nil, sizeof(LogSegment) + (server->ll->blocks - 1) * sizeof(long));
- if(seg == nil)
- return Enomem;
- seg->pagebuf = logfsrealloc(nil, 1 << server->ll->l2pagesize);
- if(seg->pagebuf == nil) {
- logfsfreemem(seg);
- return Enomem;
- }
- seg->curpage = -1;
- seg->curblockindex = -1;
- seg->gen = gen;
- *segp = seg;
- return nil;
- }
- void
- logfslogsegmentfree(LogSegment **segp)
- {
- LogSegment *seg = *segp;
- if(seg) {
- logfsfreemem(seg->pagebuf);
- logfsfreemem(seg);
- *segp = nil;
- }
- }
- char *
- logfslogsegmentflush(LogfsServer *server, int active)
- {
- LogSegment *seg;
- seg = active ? server->activelog : server->sweptlog;
- if(seg == nil)
- return nil;
- if(seg->curpage >= 0 && seg->nbytes) {
- char *errmsg;
- LogfsLowLevel *ll = server->ll;
- int pagesize = 1 << ll->l2pagesize;
- //print("curblockindex %ld curpage %d nbytes %d\n", seg->curblockindex, seg->curpage, seg->nbytes);
- if(seg->nbytes < pagesize)
- seg->pagebuf[seg->nbytes++] = LogfsLogTend;
- memset(seg->pagebuf + seg->nbytes, 0xff, pagesize - seg->nbytes);
- for(;;) {
- errmsg = (*ll->writepage)(ll, seg->pagebuf,
- seg->blockmap[seg->curblockindex], seg->curpage);
- if(errmsg == nil)
- break;
- if(strcmp(errmsg, Eio) != 0)
- return errmsg;
- errmsg = logfsserverreplacelogblock(server, seg, seg->curblockindex);
- if(errmsg)
- return errmsg;
- }
- seg->curpage++;
- if(seg->curpage == (1 << ll->l2pagesperblock))
- seg->curpage = -1;
- seg->nbytes = 0;
- }
- return nil;
- }
- static char *
- logspace(LogfsServer *server, int active, int takearisk, int nbytes, uchar **where, u32int *flashaddr)
- {
- char *errmsg;
- LogfsLowLevel *ll = server->ll;
- int pagesize = 1 << ll->l2pagesize;
- LogSegment *seg;
- if(nbytes > pagesize)
- return logfselogmsgtoobig;
- retry:
- seg = active ? server->activelog : server->sweptlog;
- for(;;) {
- //print("curpage %d nbytes %d\n", seg->curpage, seg->nbytes);
- if(seg->curpage >= 0) {
- if(seg->nbytes + nbytes < pagesize)
- break;
- errmsg = logfslogsegmentflush(server, active);
- if(errmsg)
- return errmsg;
- }
- if(seg->curpage < 0) {
- long block;
- long path;
- block = logfsfindfreeblock(ll,
- active ? (takearisk ? AllocReasonLogExtend : AllocReasonDataExtend) : AllocReasonTransfer);
- if(block < 0) {
- if(active) {
- int didsomething;
- errmsg = logfsserverlogsweep(server, 0, &didsomething);
- if(errmsg)
- return errmsg;
- if(didsomething)
- goto retry;
- }
- return logfselogfull;
- }
- seg->blockmap[++seg->curblockindex] = block;
- path = mklogpath(seg->curblockindex, seg->gen, 0);
- (*ll->setblocktag)(ll, block, LogfsTlog);
- (*ll->setblockpath)(ll, block, path);
- seg->curpage = 0;
- #ifdef FUTURE
- /* TODO - do we need one of these if the underlying system supports erase counting? */
- seg->pagebuf[0] = LogfsLogTstart;
- PBIT16(seg->pagebuf + 1, 8);
- PBIT32(seg->pagebuf + 3, path); /* TODO duplicate information */
- PBIT32(seg->pagebuf + 7, 0); /* TODO don't have this - discuss with forsyth */
- seg->nbytes = 11;
- #else
- seg->nbytes = 0;
- #endif
- }
- }
- *where = seg->pagebuf + seg->nbytes;
- if(flashaddr)
- *flashaddr = logfsspo2flashaddr(server, seg->curblockindex, seg->curpage, seg->nbytes);
- seg->nbytes += nbytes;
- return nil;
- }
- static void
- logdirty(LogfsServer *server, int active)
- {
- if(active)
- server->activelog->dirty = 1;
- else
- server->sweptlog->dirty = 1;
- }
- char *
- logfslogbytes(LogfsServer *server, int active, uchar *msg, uint size)
- {
- char *errmsg;
- uchar *p;
- errmsg = logspace(server, active, 0, size, &p, nil);
- if(errmsg)
- return errmsg;
- memmove(p, msg, size);
- logdirty(server, active);
- return nil;
- }
- char *
- logfslog(LogfsServer *server, int active, LogMessage *s)
- {
- uint size = logfssizeS2M(s);
- char *errmsg;
- uchar *p;
- int takearisk;
- if(server->trace > 1) {
- print("%c<< ", active ? 'A' : 'S');
- logfsdumpS(s);
- print("\n");
- }
- if(active) {
- switch(s->type) {
- case LogfsLogTremove:
- case LogfsLogTtrunc:
- takearisk = 1;
- break;
- default:
- takearisk = 0;
- }
- }
- else
- takearisk = 0;
- errmsg = logspace(server, active, takearisk, size, &p, nil);
- if(errmsg)
- return errmsg;
- if(logfsconvS2M(s, p, size) != size)
- return "bad conversion";
- logdirty(server, active);
- return nil;
- }
- int
- lognicesizeforwrite(LogfsServer *server, int active, u32int count, int muidlen)
- {
- int rawspace;
- LogSegment *seg;
- if(count > LogDataLimit)
- return 0;
- seg = active ? server->activelog : server->sweptlog;
- if(seg->curpage < 0)
- return LogDataLimit;
- rawspace = (1 << server->ll->l2pagesize) - seg->nbytes;
- if(rawspace < 5 * 4 + 2 + muidlen + 1)
- return LogDataLimit;
- return 5 * 4 + 2 + muidlen - rawspace;
- }
- char *
- logfslogwrite(LogfsServer *server, int active, u32int path, u32int offset, int count, u32int mtime, u32int cvers,
- char *muid, uchar *data, u32int *flashaddr)
- {
- /* 'w' size[2] path[4] offset[4] count[2] mtime[4] cvers[4] muid[s] flashaddr[4] [data[n]] */
- LogMessage s;
- uint size;
- char *errmsg;
- uchar *p;
- u32int faddr;
- uint asize;
- s.type = LogfsLogTwrite;
- s.path = path;
- s.u.write.offset = offset;
- s.u.write.count = count;
- s.u.write.mtime = mtime;
- s.u.write.cvers = cvers;
- s.u.write.muid = muid;
- s.u.write.data = data;
- size = logfssizeS2M(&s);
- errmsg = logspace(server, active, 0, size, &p, &faddr);
- if(errmsg)
- return errmsg;
- if(data)
- *flashaddr = (faddr + size - count) | LogAddr;
- s.u.write.flashaddr = *flashaddr;
- if(server->trace > 1) {
- print("%c<< ", active ? 'A' : 'S');
- logfsdumpS(&s);
- print("\n");
- }
- if((asize = logfsconvS2M(&s, p, size)) != size) {
- print("expected %d actual %d\n", size, asize);
- return "bad conversion";
- }
- logdirty(server, active);
- return nil;
- }
|