1 #include "logfsos.h"
2 #include "logfs.h"
3 #include "fcall.h"
4 #include "local.h"
5
6 static char *unimp = "unimplemented";
7 char *logfsbadfid = "invalid fid";
8
9 char *
logfsstrdup(char * p)10 logfsstrdup(char *p)
11 {
12 int l;
13 char *q;
14 if(p == nil)
15 return nil;
16 l = strlen(p);
17 q = logfsrealloc(nil, l + 1);
18 if(q == nil)
19 return nil;
20 return strcpy(q, p);
21 }
22
23 static
mkdirentry(LogfsServer * server,Entry * e,int inuse,ulong path,Entry * parent,char * name,char * uid,char * gid,ulong mtime,char * muid,ulong perm)24 mkdirentry(LogfsServer *server, Entry *e, int inuse, ulong path, Entry *parent, char *name, char *uid, char *gid,
25 ulong mtime, char *muid, ulong perm)
26 {
27 //print("mkdirentry 0x%.8lux\n", e);
28 e->inuse = inuse;
29 e->qid.path = path;
30 e->qid.vers = 0;
31 e->qid.type = QTDIR;
32 e->parent = parent;
33 e->name = name;
34 e->uid = logfsisustadd(server->is, uid);
35 e->gid = logfsisustadd(server->is, gid);
36 e->mtime = mtime;
37 e->muid = logfsisustadd(server->is, muid);
38 e->perm = perm | DMDIR;
39 e->next = nil;
40 return e->uid != nil && e->muid != nil && e->name != nil;
41 }
42
43 void
logfsentryfree(Entry * e)44 logfsentryfree(Entry *e)
45 {
46 logfsfreemem(e->name);
47 if((e->qid.type & QTDIR) == 0)
48 logfsextentlistfree(&e->u.file.extent);
49 logfsfreemem(e);
50 }
51
52 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)53 logfsentrynew(LogfsServer *server, int inuse, u32int path, Entry *parent, char *name, char *uid, char *gid,
54 u32int mtime, char *muid, u32int perm, ulong cvers, ulong length, Entry **ep)
55 {
56 Entry *e;
57 char *errmsg;
58 e = logfsrealloc(nil, sizeof(*e));
59 if(e == nil)
60 return Enomem;
61 e->inuse = inuse;
62 e->qid.path = path;
63 e->qid.vers = 0;
64 e->qid.type = perm >> 24;
65 e->parent = parent;
66 e->name = logfsstrdup(name);
67 e->uid = logfsisustadd(server->is, uid);
68 e->gid = logfsisustadd(server->is, gid);
69 e->muid = logfsisustadd(server->is, muid);
70 if(e->uid == nil || e->gid == nil || e->muid == nil || e->name == nil) {
71 logfsentryfree(e);
72 return Enomem;
73 }
74 e->mtime = mtime;
75 if(perm & DMDIR)
76 e->perm = perm & (~0777 | (parent->perm & 0777));
77 else {
78 e->perm = perm & (~0666 | (parent->perm & 0666));
79 e->u.file.cvers = cvers;
80 e->u.file.length = length;
81 errmsg = logfsextentlistnew(&e->u.file.extent);
82 if(errmsg) {
83 logfsentryfree(e);
84 return errmsg;
85 }
86 }
87 //print("e 0x%.8lux perm 0%.uo\n", e, e->perm);
88 *ep = e;
89 return nil;
90
91 }
92
93 void
logfsentryclunk(Entry * e)94 logfsentryclunk(Entry *e)
95 {
96 e->inuse--;
97 if(e->inuse <= 0)
98 logfsentryfree(e);
99 }
100
101 char *
logfsservernew(LogfsBoot * lb,LogfsLowLevel * ll,LogfsIdentityStore * is,ulong openflags,int trace,LogfsServer ** srvp)102 logfsservernew(LogfsBoot *lb, LogfsLowLevel *ll, LogfsIdentityStore *is, ulong openflags, int trace, LogfsServer **srvp)
103 {
104 LogfsServer *srv;
105 char *errmsg;
106 Path *p;
107
108 if(trace > 1)
109 print("logfsservernew()\n");
110 if(ll->l2pagesperblock > 5)
111 return "more than 32 pages per block";
112 if((1 << (ll->pathbits - L2LogSweeps - L2BlockCopies)) < ll->blocks)
113 return "too many blocks";
114 srv = logfsrealloc(nil, sizeof(*srv));
115 if(srv == nil) {
116 memerror:
117 errmsg = Enomem;
118 err:
119 logfsserverfree(&srv);
120 return errmsg;
121 }
122 errmsg = logfsfidmapnew(&srv->fidmap);
123 if(errmsg)
124 goto memerror;
125 errmsg = logfspathmapnew(&srv->pathmap);
126 if(errmsg)
127 goto memerror;
128 srv->is = is;
129 srv->ll = ll;
130 srv->trace = trace;
131 srv->lb = lb;
132 srv->openflags = openflags;
133 if(!mkdirentry(srv, &srv->root, 1, 0, &srv->root, "", "inferno", "sys", logfsnow(), "inferno", 0777))
134 goto memerror;
135 errmsg = logfspathmapnewentry(srv->pathmap, 0, &srv->root, &p);
136 /* p is guaranteed to be non null */
137 if(errmsg)
138 goto memerror;
139 errmsg = logfslogsegmentnew(srv, 0, &srv->activelog);
140 if(errmsg)
141 goto memerror;
142 srv->ndatablocks = 0;
143 srv->datablock = logfsrealloc(nil, sizeof(DataBlock) * ll->blocks);
144 if(srv->datablock == nil)
145 goto memerror;
146 errmsg = logfsscan(srv);
147 if(errmsg)
148 goto err;
149 errmsg = logfsreplay(srv, srv->sweptlog, 0);
150 if(errmsg)
151 goto err;
152 errmsg = logfsreplay(srv, srv->activelog, srv->sweptlog != nil);
153 if(errmsg)
154 goto err;
155 logfsreplayfinddata(srv);
156 *srvp = srv;
157 return nil;
158 }
159
160 static void
freeentrylist(Entry * e)161 freeentrylist(Entry *e)
162 {
163 Entry *next;
164 while(e) {
165 next = e->next;
166 if(e->qid.type & QTDIR)
167 freeentrylist(e->u.dir.list);
168 logfsentryfree(e);
169 e = next;
170 }
171 }
172
173 void
logfsserverfree(LogfsServer ** serverp)174 logfsserverfree(LogfsServer **serverp)
175 {
176 LogfsServer *server = *serverp;
177 if(server) {
178 logfsfidmapfree(&server->fidmap);
179 logfslogsegmentfree(&server->activelog);
180 logfslogsegmentfree(&server->sweptlog);
181 logfspathmapfree(&server->pathmap);
182 logfsfreemem(server->datablock);
183 logfsfreemem(server);
184 freeentrylist(server->root.u.dir.list);
185 *serverp = nil;
186 }
187 }
188
189 char *
logfsserverattach(LogfsServer * server,u32int fid,char * uname,Qid * qid)190 logfsserverattach(LogfsServer *server, u32int fid, char *uname, Qid *qid)
191 {
192 char *errmsg;
193 Fid *f;
194 if(server->trace > 1)
195 print("logfsserverattach(%ud, %s)\n", fid, uname);
196 errmsg = logfsfidmapnewentry(server->fidmap, fid, &f);
197 if(errmsg)
198 return errmsg;
199 f->uname = logfsisustadd(server->is, uname);
200 if(f->uname == nil) {
201 logfsfidmapclunk(server->fidmap, fid);
202 return Enomem;
203 }
204 f->entry = &server->root;
205 f->entry->inuse++;
206 *qid = f->entry->qid;
207 return nil;
208 }
209
210 static void
id2name(LogfsIdentityStore * is,char * id,char ** namep,int * badp,int * lenp)211 id2name(LogfsIdentityStore *is, char *id, char **namep, int *badp, int *lenp)
212 {
213 char *name;
214 if(id == logfsisgroupnonename)
215 name = id;
216 else {
217 name = logfsisfindnamefromid(is, id);
218 if(name == nil) {
219 *badp = 2;
220 name = id;
221 }
222 }
223 *lenp = strlen(name);
224 *namep = name;
225 }
226
227 u32int
logfsflattenentry(LogfsIdentityStore * is,uchar * buf,u32int limit,Entry * e)228 logfsflattenentry(LogfsIdentityStore *is, uchar *buf, u32int limit, Entry *e)
229 {
230 int unamelen, gnamelen, munamelen, namelen;
231 uint len;
232 uchar *p;
233 int unamebad = 0, gnamebad = 0, munamebad = 0;
234 char *uname, *gname, *muname;
235
236 id2name(is, e->uid, &uname, &unamebad, &unamelen);
237 id2name(is, e->gid, &gname, &gnamebad, &gnamelen);
238 id2name(is, e->muid, &muname, &munamebad, &munamelen);
239 namelen = strlen(e->name);
240 len = 49 + unamelen + unamebad + gnamelen + gnamebad + munamelen + munamebad + namelen;
241 if(buf == nil)
242 return len;
243 if(len > limit)
244 return 0;
245 p = buf;
246 /* size */ PBIT16(p, len - BIT16SZ); p += BIT16SZ;
247 /* type */ p += BIT16SZ;
248 /* dev */ p += BIT32SZ;
249 /* qid.type */ *p++ = e->qid.type;
250 /* qid.vers */ PBIT32(p, e->qid.vers); p += BIT32SZ;
251 /* qid.path */ PBIT64(p, e->qid.path); p+= 8;
252 /* mode */ PBIT32(p, e->perm); p+= BIT32SZ;
253 /* atime */ PBIT32(p, e->mtime); p+= BIT32SZ;
254 /* mtime */ PBIT32(p, e->mtime); p+= BIT32SZ;
255 /* length */ if(e->qid.type & QTDIR) {
256 PBIT64(p, 0);
257 p += 8;
258 }
259 else {
260 PBIT32(p, e->u.file.length); p += BIT32SZ;
261 PBIT32(p, 0); p += BIT32SZ;
262 }
263 /* name */ PBIT16(p, namelen); p += BIT16SZ; memmove(p, e->name, namelen); p+= namelen;
264 /* uid */ PBIT16(p, unamelen + unamebad); p += BIT16SZ;
265 if(unamebad)
266 *p++ = '(';
267 memmove(p, uname, unamelen + unamebad); p+= unamelen;
268 if(unamebad)
269 *p++ = ')';
270 /* gid */ PBIT16(p, gnamelen + gnamebad); p += BIT16SZ;
271 if(gnamebad)
272 *p++ = '(';
273 memmove(p, gname, gnamelen); p+= gnamelen;
274 if(gnamebad)
275 *p++ = ')';
276 /* muid */ PBIT16(p, munamelen + munamebad); p += BIT16SZ;
277 if(munamebad)
278 *p++ = '(';
279 memmove(p, muname, munamelen); p+= munamelen;
280 if(munamebad)
281 *p = ')';
282 //print("len %ud p - buf %ld\n", len, p - buf);
283 return len;
284 }
285
286 char *
logfsserverstat(LogfsServer * server,u32int fid,uchar * buf,u32int bufsize,ushort * nstat)287 logfsserverstat(LogfsServer *server, u32int fid, uchar *buf, u32int bufsize, ushort *nstat)
288 {
289 Fid *f;
290 if(server->trace > 1)
291 print("logfsserverstat(%ud)\n", fid);
292 f = logfsfidmapfindentry(server->fidmap, fid);
293 if(f == nil)
294 return logfsbadfid;
295 if(f->entry->deadandgone)
296 return Eio;
297 *nstat = logfsflattenentry(server->is, buf, bufsize, f->entry);
298 if(*nstat == 0)
299 return Eshortstat;
300 return nil;
301 }
302
303
304 void
logfsservertrace(LogfsServer * server,int level)305 logfsservertrace(LogfsServer *server, int level)
306 {
307 server->trace = level;
308 }
309