1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "logfs.h"
337da2899SCharles.Forsyth #include "fcall.h"
437da2899SCharles.Forsyth #include "local.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth static char *unimp = "unimplemented";
737da2899SCharles.Forsyth char *logfsbadfid = "invalid fid";
837da2899SCharles.Forsyth
937da2899SCharles.Forsyth char *
logfsstrdup(char * p)1037da2899SCharles.Forsyth logfsstrdup(char *p)
1137da2899SCharles.Forsyth {
1237da2899SCharles.Forsyth int l;
1337da2899SCharles.Forsyth char *q;
1437da2899SCharles.Forsyth if(p == nil)
1537da2899SCharles.Forsyth return nil;
1637da2899SCharles.Forsyth l = strlen(p);
1737da2899SCharles.Forsyth q = logfsrealloc(nil, l + 1);
1837da2899SCharles.Forsyth if(q == nil)
1937da2899SCharles.Forsyth return nil;
2037da2899SCharles.Forsyth return strcpy(q, p);
2137da2899SCharles.Forsyth }
2237da2899SCharles.Forsyth
2337da2899SCharles.Forsyth static
mkdirentry(LogfsServer * server,Entry * e,int inuse,ulong path,Entry * parent,char * name,char * uid,char * gid,ulong mtime,char * muid,ulong perm)2437da2899SCharles.Forsyth mkdirentry(LogfsServer *server, Entry *e, int inuse, ulong path, Entry *parent, char *name, char *uid, char *gid,
2537da2899SCharles.Forsyth ulong mtime, char *muid, ulong perm)
2637da2899SCharles.Forsyth {
2737da2899SCharles.Forsyth //print("mkdirentry 0x%.8lux\n", e);
2837da2899SCharles.Forsyth e->inuse = inuse;
2937da2899SCharles.Forsyth e->qid.path = path;
3037da2899SCharles.Forsyth e->qid.vers = 0;
3137da2899SCharles.Forsyth e->qid.type = QTDIR;
3237da2899SCharles.Forsyth e->parent = parent;
3337da2899SCharles.Forsyth e->name = name;
3437da2899SCharles.Forsyth e->uid = logfsisustadd(server->is, uid);
3537da2899SCharles.Forsyth e->gid = logfsisustadd(server->is, gid);
3637da2899SCharles.Forsyth e->mtime = mtime;
3737da2899SCharles.Forsyth e->muid = logfsisustadd(server->is, muid);
3837da2899SCharles.Forsyth e->perm = perm | DMDIR;
3937da2899SCharles.Forsyth e->next = nil;
4037da2899SCharles.Forsyth return e->uid != nil && e->muid != nil && e->name != nil;
4137da2899SCharles.Forsyth }
4237da2899SCharles.Forsyth
4337da2899SCharles.Forsyth void
logfsentryfree(Entry * e)4437da2899SCharles.Forsyth logfsentryfree(Entry *e)
4537da2899SCharles.Forsyth {
4637da2899SCharles.Forsyth logfsfreemem(e->name);
4737da2899SCharles.Forsyth if((e->qid.type & QTDIR) == 0)
4837da2899SCharles.Forsyth logfsextentlistfree(&e->u.file.extent);
4937da2899SCharles.Forsyth logfsfreemem(e);
5037da2899SCharles.Forsyth }
5137da2899SCharles.Forsyth
5237da2899SCharles.Forsyth char *
logfsentrynew(LogfsServer * server,int inuse,u32int path,Entry * parent,char * name,char * uid,char * gid,u32int mtime,char * muid,u32int perm,ulong cvers,ulong length,Entry ** ep)5337da2899SCharles.Forsyth logfsentrynew(LogfsServer *server, int inuse, u32int path, Entry *parent, char *name, char *uid, char *gid,
5437da2899SCharles.Forsyth u32int mtime, char *muid, u32int perm, ulong cvers, ulong length, Entry **ep)
5537da2899SCharles.Forsyth {
5637da2899SCharles.Forsyth Entry *e;
5737da2899SCharles.Forsyth char *errmsg;
5837da2899SCharles.Forsyth e = logfsrealloc(nil, sizeof(*e));
5937da2899SCharles.Forsyth if(e == nil)
6037da2899SCharles.Forsyth return Enomem;
6137da2899SCharles.Forsyth e->inuse = inuse;
6237da2899SCharles.Forsyth e->qid.path = path;
6337da2899SCharles.Forsyth e->qid.vers = 0;
6437da2899SCharles.Forsyth e->qid.type = perm >> 24;
6537da2899SCharles.Forsyth e->parent = parent;
6637da2899SCharles.Forsyth e->name = logfsstrdup(name);
6737da2899SCharles.Forsyth e->uid = logfsisustadd(server->is, uid);
6837da2899SCharles.Forsyth e->gid = logfsisustadd(server->is, gid);
6937da2899SCharles.Forsyth e->muid = logfsisustadd(server->is, muid);
7037da2899SCharles.Forsyth if(e->uid == nil || e->gid == nil || e->muid == nil || e->name == nil) {
7137da2899SCharles.Forsyth logfsentryfree(e);
7237da2899SCharles.Forsyth return Enomem;
7337da2899SCharles.Forsyth }
7437da2899SCharles.Forsyth e->mtime = mtime;
7537da2899SCharles.Forsyth if(perm & DMDIR)
7637da2899SCharles.Forsyth e->perm = perm & (~0777 | (parent->perm & 0777));
7737da2899SCharles.Forsyth else {
7837da2899SCharles.Forsyth e->perm = perm & (~0666 | (parent->perm & 0666));
7937da2899SCharles.Forsyth e->u.file.cvers = cvers;
8037da2899SCharles.Forsyth e->u.file.length = length;
8137da2899SCharles.Forsyth errmsg = logfsextentlistnew(&e->u.file.extent);
8237da2899SCharles.Forsyth if(errmsg) {
8337da2899SCharles.Forsyth logfsentryfree(e);
8437da2899SCharles.Forsyth return errmsg;
8537da2899SCharles.Forsyth }
8637da2899SCharles.Forsyth }
8737da2899SCharles.Forsyth //print("e 0x%.8lux perm 0%.uo\n", e, e->perm);
8837da2899SCharles.Forsyth *ep = e;
8937da2899SCharles.Forsyth return nil;
9037da2899SCharles.Forsyth
9137da2899SCharles.Forsyth }
9237da2899SCharles.Forsyth
9337da2899SCharles.Forsyth void
logfsentryclunk(Entry * e)9437da2899SCharles.Forsyth logfsentryclunk(Entry *e)
9537da2899SCharles.Forsyth {
9637da2899SCharles.Forsyth e->inuse--;
9737da2899SCharles.Forsyth if(e->inuse <= 0)
9837da2899SCharles.Forsyth logfsentryfree(e);
9937da2899SCharles.Forsyth }
10037da2899SCharles.Forsyth
10137da2899SCharles.Forsyth char *
logfsservernew(LogfsBoot * lb,LogfsLowLevel * ll,LogfsIdentityStore * is,ulong openflags,int trace,LogfsServer ** srvp)10237da2899SCharles.Forsyth logfsservernew(LogfsBoot *lb, LogfsLowLevel *ll, LogfsIdentityStore *is, ulong openflags, int trace, LogfsServer **srvp)
10337da2899SCharles.Forsyth {
10437da2899SCharles.Forsyth LogfsServer *srv;
10537da2899SCharles.Forsyth char *errmsg;
10637da2899SCharles.Forsyth Path *p;
10737da2899SCharles.Forsyth
10837da2899SCharles.Forsyth if(trace > 1)
10937da2899SCharles.Forsyth print("logfsservernew()\n");
11037da2899SCharles.Forsyth if(ll->l2pagesperblock > 5)
11137da2899SCharles.Forsyth return "more than 32 pages per block";
11237da2899SCharles.Forsyth if((1 << (ll->pathbits - L2LogSweeps - L2BlockCopies)) < ll->blocks)
11337da2899SCharles.Forsyth return "too many blocks";
11437da2899SCharles.Forsyth srv = logfsrealloc(nil, sizeof(*srv));
11537da2899SCharles.Forsyth if(srv == nil) {
11637da2899SCharles.Forsyth memerror:
11737da2899SCharles.Forsyth errmsg = Enomem;
11837da2899SCharles.Forsyth err:
11937da2899SCharles.Forsyth logfsserverfree(&srv);
12037da2899SCharles.Forsyth return errmsg;
12137da2899SCharles.Forsyth }
12237da2899SCharles.Forsyth errmsg = logfsfidmapnew(&srv->fidmap);
12337da2899SCharles.Forsyth if(errmsg)
12437da2899SCharles.Forsyth goto memerror;
12537da2899SCharles.Forsyth errmsg = logfspathmapnew(&srv->pathmap);
12637da2899SCharles.Forsyth if(errmsg)
12737da2899SCharles.Forsyth goto memerror;
12837da2899SCharles.Forsyth srv->is = is;
12937da2899SCharles.Forsyth srv->ll = ll;
13037da2899SCharles.Forsyth srv->trace = trace;
13137da2899SCharles.Forsyth srv->lb = lb;
13237da2899SCharles.Forsyth srv->openflags = openflags;
13337da2899SCharles.Forsyth if(!mkdirentry(srv, &srv->root, 1, 0, &srv->root, "", "inferno", "sys", logfsnow(), "inferno", 0777))
13437da2899SCharles.Forsyth goto memerror;
13537da2899SCharles.Forsyth errmsg = logfspathmapnewentry(srv->pathmap, 0, &srv->root, &p);
13637da2899SCharles.Forsyth /* p is guaranteed to be non null */
13737da2899SCharles.Forsyth if(errmsg)
13837da2899SCharles.Forsyth goto memerror;
13937da2899SCharles.Forsyth errmsg = logfslogsegmentnew(srv, 0, &srv->activelog);
14037da2899SCharles.Forsyth if(errmsg)
14137da2899SCharles.Forsyth goto memerror;
14237da2899SCharles.Forsyth srv->ndatablocks = 0;
14337da2899SCharles.Forsyth srv->datablock = logfsrealloc(nil, sizeof(DataBlock) * ll->blocks);
14437da2899SCharles.Forsyth if(srv->datablock == nil)
14537da2899SCharles.Forsyth goto memerror;
14637da2899SCharles.Forsyth errmsg = logfsscan(srv);
14737da2899SCharles.Forsyth if(errmsg)
14837da2899SCharles.Forsyth goto err;
14937da2899SCharles.Forsyth errmsg = logfsreplay(srv, srv->sweptlog, 0);
15037da2899SCharles.Forsyth if(errmsg)
15137da2899SCharles.Forsyth goto err;
15237da2899SCharles.Forsyth errmsg = logfsreplay(srv, srv->activelog, srv->sweptlog != nil);
15337da2899SCharles.Forsyth if(errmsg)
15437da2899SCharles.Forsyth goto err;
15537da2899SCharles.Forsyth logfsreplayfinddata(srv);
15637da2899SCharles.Forsyth *srvp = srv;
15737da2899SCharles.Forsyth return nil;
15837da2899SCharles.Forsyth }
15937da2899SCharles.Forsyth
16037da2899SCharles.Forsyth static void
freeentrylist(Entry * e)16137da2899SCharles.Forsyth freeentrylist(Entry *e)
16237da2899SCharles.Forsyth {
16337da2899SCharles.Forsyth Entry *next;
16437da2899SCharles.Forsyth while(e) {
16537da2899SCharles.Forsyth next = e->next;
16637da2899SCharles.Forsyth if(e->qid.type & QTDIR)
16737da2899SCharles.Forsyth freeentrylist(e->u.dir.list);
16837da2899SCharles.Forsyth logfsentryfree(e);
16937da2899SCharles.Forsyth e = next;
17037da2899SCharles.Forsyth }
17137da2899SCharles.Forsyth }
17237da2899SCharles.Forsyth
17337da2899SCharles.Forsyth void
logfsserverfree(LogfsServer ** serverp)17437da2899SCharles.Forsyth logfsserverfree(LogfsServer **serverp)
17537da2899SCharles.Forsyth {
17637da2899SCharles.Forsyth LogfsServer *server = *serverp;
17737da2899SCharles.Forsyth if(server) {
17837da2899SCharles.Forsyth logfsfidmapfree(&server->fidmap);
17937da2899SCharles.Forsyth logfslogsegmentfree(&server->activelog);
18037da2899SCharles.Forsyth logfslogsegmentfree(&server->sweptlog);
18137da2899SCharles.Forsyth logfspathmapfree(&server->pathmap);
18237da2899SCharles.Forsyth logfsfreemem(server->datablock);
18337da2899SCharles.Forsyth logfsfreemem(server);
18437da2899SCharles.Forsyth freeentrylist(server->root.u.dir.list);
18537da2899SCharles.Forsyth *serverp = nil;
18637da2899SCharles.Forsyth }
18737da2899SCharles.Forsyth }
18837da2899SCharles.Forsyth
18937da2899SCharles.Forsyth char *
logfsserverattach(LogfsServer * server,u32int fid,char * uname,Qid * qid)19037da2899SCharles.Forsyth logfsserverattach(LogfsServer *server, u32int fid, char *uname, Qid *qid)
19137da2899SCharles.Forsyth {
19237da2899SCharles.Forsyth char *errmsg;
19337da2899SCharles.Forsyth Fid *f;
19437da2899SCharles.Forsyth if(server->trace > 1)
19537da2899SCharles.Forsyth print("logfsserverattach(%ud, %s)\n", fid, uname);
19637da2899SCharles.Forsyth errmsg = logfsfidmapnewentry(server->fidmap, fid, &f);
19737da2899SCharles.Forsyth if(errmsg)
19837da2899SCharles.Forsyth return errmsg;
19937da2899SCharles.Forsyth f->uname = logfsisustadd(server->is, uname);
20037da2899SCharles.Forsyth if(f->uname == nil) {
20137da2899SCharles.Forsyth logfsfidmapclunk(server->fidmap, fid);
20237da2899SCharles.Forsyth return Enomem;
20337da2899SCharles.Forsyth }
20437da2899SCharles.Forsyth f->entry = &server->root;
20537da2899SCharles.Forsyth f->entry->inuse++;
20637da2899SCharles.Forsyth *qid = f->entry->qid;
20737da2899SCharles.Forsyth return nil;
20837da2899SCharles.Forsyth }
20937da2899SCharles.Forsyth
21037da2899SCharles.Forsyth static void
id2name(LogfsIdentityStore * is,char * id,char ** namep,int * badp,int * lenp)21137da2899SCharles.Forsyth id2name(LogfsIdentityStore *is, char *id, char **namep, int *badp, int *lenp)
21237da2899SCharles.Forsyth {
21337da2899SCharles.Forsyth char *name;
21437da2899SCharles.Forsyth if(id == logfsisgroupnonename)
21537da2899SCharles.Forsyth name = id;
21637da2899SCharles.Forsyth else {
21737da2899SCharles.Forsyth name = logfsisfindnamefromid(is, id);
21837da2899SCharles.Forsyth if(name == nil) {
21937da2899SCharles.Forsyth *badp = 2;
22037da2899SCharles.Forsyth name = id;
22137da2899SCharles.Forsyth }
22237da2899SCharles.Forsyth }
22337da2899SCharles.Forsyth *lenp = strlen(name);
22437da2899SCharles.Forsyth *namep = name;
22537da2899SCharles.Forsyth }
22637da2899SCharles.Forsyth
22737da2899SCharles.Forsyth u32int
logfsflattenentry(LogfsIdentityStore * is,uchar * buf,u32int limit,Entry * e)22837da2899SCharles.Forsyth logfsflattenentry(LogfsIdentityStore *is, uchar *buf, u32int limit, Entry *e)
22937da2899SCharles.Forsyth {
23037da2899SCharles.Forsyth int unamelen, gnamelen, munamelen, namelen;
23137da2899SCharles.Forsyth uint len;
23237da2899SCharles.Forsyth uchar *p;
23337da2899SCharles.Forsyth int unamebad = 0, gnamebad = 0, munamebad = 0;
23437da2899SCharles.Forsyth char *uname, *gname, *muname;
23537da2899SCharles.Forsyth
23637da2899SCharles.Forsyth id2name(is, e->uid, &uname, &unamebad, &unamelen);
23737da2899SCharles.Forsyth id2name(is, e->gid, &gname, &gnamebad, &gnamelen);
23837da2899SCharles.Forsyth id2name(is, e->muid, &muname, &munamebad, &munamelen);
23937da2899SCharles.Forsyth namelen = strlen(e->name);
24037da2899SCharles.Forsyth len = 49 + unamelen + unamebad + gnamelen + gnamebad + munamelen + munamebad + namelen;
24137da2899SCharles.Forsyth if(buf == nil)
24237da2899SCharles.Forsyth return len;
24337da2899SCharles.Forsyth if(len > limit)
24437da2899SCharles.Forsyth return 0;
24537da2899SCharles.Forsyth p = buf;
24637da2899SCharles.Forsyth /* size */ PBIT16(p, len - BIT16SZ); p += BIT16SZ;
24737da2899SCharles.Forsyth /* type */ p += BIT16SZ;
24837da2899SCharles.Forsyth /* dev */ p += BIT32SZ;
24937da2899SCharles.Forsyth /* qid.type */ *p++ = e->qid.type;
25037da2899SCharles.Forsyth /* qid.vers */ PBIT32(p, e->qid.vers); p += BIT32SZ;
25137da2899SCharles.Forsyth /* qid.path */ PBIT64(p, e->qid.path); p+= 8;
25237da2899SCharles.Forsyth /* mode */ PBIT32(p, e->perm); p+= BIT32SZ;
25337da2899SCharles.Forsyth /* atime */ PBIT32(p, e->mtime); p+= BIT32SZ;
25437da2899SCharles.Forsyth /* mtime */ PBIT32(p, e->mtime); p+= BIT32SZ;
25537da2899SCharles.Forsyth /* length */ if(e->qid.type & QTDIR) {
25637da2899SCharles.Forsyth PBIT64(p, 0);
25737da2899SCharles.Forsyth p += 8;
25837da2899SCharles.Forsyth }
25937da2899SCharles.Forsyth else {
26037da2899SCharles.Forsyth PBIT32(p, e->u.file.length); p += BIT32SZ;
26137da2899SCharles.Forsyth PBIT32(p, 0); p += BIT32SZ;
26237da2899SCharles.Forsyth }
263*28942eadSforsyth /* name */ PBIT16(p, namelen); p += BIT16SZ; memmove(p, e->name, namelen); p+= namelen;
26437da2899SCharles.Forsyth /* uid */ PBIT16(p, unamelen + unamebad); p += BIT16SZ;
26537da2899SCharles.Forsyth if(unamebad)
26637da2899SCharles.Forsyth *p++ = '(';
267*28942eadSforsyth memmove(p, uname, unamelen + unamebad); p+= unamelen;
26837da2899SCharles.Forsyth if(unamebad)
26937da2899SCharles.Forsyth *p++ = ')';
27037da2899SCharles.Forsyth /* gid */ PBIT16(p, gnamelen + gnamebad); p += BIT16SZ;
27137da2899SCharles.Forsyth if(gnamebad)
27237da2899SCharles.Forsyth *p++ = '(';
273*28942eadSforsyth memmove(p, gname, gnamelen); p+= gnamelen;
27437da2899SCharles.Forsyth if(gnamebad)
27537da2899SCharles.Forsyth *p++ = ')';
27637da2899SCharles.Forsyth /* muid */ PBIT16(p, munamelen + munamebad); p += BIT16SZ;
27737da2899SCharles.Forsyth if(munamebad)
27837da2899SCharles.Forsyth *p++ = '(';
279*28942eadSforsyth memmove(p, muname, munamelen); p+= munamelen;
28037da2899SCharles.Forsyth if(munamebad)
28137da2899SCharles.Forsyth *p = ')';
28237da2899SCharles.Forsyth //print("len %ud p - buf %ld\n", len, p - buf);
28337da2899SCharles.Forsyth return len;
28437da2899SCharles.Forsyth }
28537da2899SCharles.Forsyth
28637da2899SCharles.Forsyth char *
logfsserverstat(LogfsServer * server,u32int fid,uchar * buf,u32int bufsize,ushort * nstat)28737da2899SCharles.Forsyth logfsserverstat(LogfsServer *server, u32int fid, uchar *buf, u32int bufsize, ushort *nstat)
28837da2899SCharles.Forsyth {
28937da2899SCharles.Forsyth Fid *f;
29037da2899SCharles.Forsyth if(server->trace > 1)
29137da2899SCharles.Forsyth print("logfsserverstat(%ud)\n", fid);
29237da2899SCharles.Forsyth f = logfsfidmapfindentry(server->fidmap, fid);
29337da2899SCharles.Forsyth if(f == nil)
29437da2899SCharles.Forsyth return logfsbadfid;
29537da2899SCharles.Forsyth if(f->entry->deadandgone)
29637da2899SCharles.Forsyth return Eio;
29737da2899SCharles.Forsyth *nstat = logfsflattenentry(server->is, buf, bufsize, f->entry);
29837da2899SCharles.Forsyth if(*nstat == 0)
299*28942eadSforsyth return Eshortstat;
30037da2899SCharles.Forsyth return nil;
30137da2899SCharles.Forsyth }
30237da2899SCharles.Forsyth
30337da2899SCharles.Forsyth
30437da2899SCharles.Forsyth void
logfsservertrace(LogfsServer * server,int level)30537da2899SCharles.Forsyth logfsservertrace(LogfsServer *server, int level)
30637da2899SCharles.Forsyth {
30737da2899SCharles.Forsyth server->trace = level;
30837da2899SCharles.Forsyth }
309