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 * 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 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 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 * 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 94 logfsentryclunk(Entry *e) 95 { 96 e->inuse--; 97 if(e->inuse <= 0) 98 logfsentryfree(e); 99 } 100 101 char * 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 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 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 * 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 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 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 * 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 305 logfsservertrace(LogfsServer *server, int level) 306 { 307 server->trace = level; 308 } 309