1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <fcall.h> 5 #include <thread.h> 6 #include <9p.h> 7 #include "flashfs.h" 8 9 static int nextfnum; 10 static Intmap* map; 11 static Dir dirproto; 12 13 static char user[] = "flash"; 14 15 Entry *root; 16 ulong used; 17 ulong limit; 18 ulong maxwrite; 19 20 enum 21 { 22 debug = 0, 23 }; 24 25 static int 26 fnum(void) 27 { 28 return ++nextfnum; 29 } 30 31 static void 32 maxfnum(int n) 33 { 34 if(n > nextfnum) 35 nextfnum = n; 36 } 37 38 static int 39 hash(char *s) 40 { 41 int c, d, h; 42 43 h = 0; 44 while((c = *s++) != '\0') { 45 d = c; 46 c ^= c << 6; 47 h += (c << 11) ^ (c >> 1); 48 h ^= (d << 14) + (d << 7) + (d << 4) + d; 49 } 50 51 if(h < 0) 52 return ~h; 53 return h; 54 } 55 56 static void 57 dirinit(Entry *e) 58 { 59 Entry **t; 60 61 e->size = 0; 62 t = emalloc9p(HSIZE * sizeof(Entry*)); 63 memset(t, 0, HSIZE * sizeof(Entry*)); 64 e->htab = t; 65 e->files = nil; 66 e->readers = nil; 67 } 68 69 static void 70 fileinit(Entry *e) 71 { 72 e->size = 0; 73 e->gen[0].head = nil; 74 e->gen[0].tail = nil; 75 e->gen[1].head = nil; 76 e->gen[1].tail = nil; 77 } 78 79 static void 80 elfree(Extent *x) 81 { 82 Extent *t; 83 84 while(x != nil) { 85 t = x->next; 86 used -= x->size; 87 free(x); 88 x = t; 89 } 90 } 91 92 static void 93 extfree(Entry *e) 94 { 95 elfree(e->gen[0].head); 96 elfree(e->gen[1].head); 97 } 98 99 static void 100 efree(Entry *e) 101 { 102 if(debug) 103 fprint(2, "free %s\n", e->name); 104 105 if(e->mode & DMDIR) 106 free(e->htab); 107 else 108 extfree(e); 109 110 free(e->name); 111 free(e); 112 } 113 114 void 115 einit(void) 116 { 117 Entry *e; 118 119 e = emalloc9p(sizeof(Entry)); 120 e->ref = 1; 121 e->parent = nil; 122 dirinit(e); 123 e->name = estrdup9p(""); 124 e->fnum = 0; 125 e->mode = DMDIR | 0775; 126 e->mnum = 0; 127 e->mtime = 0; 128 root = e; 129 map = allocmap(nil); 130 } 131 132 static void 133 dumptree(Entry *e, int n) 134 { 135 Entry *l; 136 137 if(debug) 138 fprint(2, "%d %s %d\n", n, e->name, e->ref); 139 140 if(e->mode & DMDIR) { 141 n++; 142 for(l = e->files; l != nil; l = l->fnext) 143 dumptree(l, n); 144 } 145 } 146 147 void 148 edump(void) 149 { 150 if(debug) 151 dumptree(root, 0); 152 } 153 154 Entry * 155 elookup(ulong key) 156 { 157 if(key == 0) 158 return root; 159 maxfnum(key); 160 return lookupkey(map, key); 161 } 162 163 Extent * 164 esum(Entry *e, int sect, ulong addr, int *more) 165 { 166 Exts *x; 167 Extent *t, *u; 168 169 x = &e->gen[eparity]; 170 t = x->tail; 171 if(t == nil || t->sect != sect || t->addr != addr) 172 return nil; 173 u = t->prev; 174 if(u != nil) { 175 u->next = nil; 176 *more = 1; 177 } 178 else { 179 x->head = nil; 180 *more = 0; 181 } 182 x->tail = u; 183 x = &e->gen[eparity^1]; 184 u = x->head; 185 t->next = u; 186 x->head = t; 187 if(u == nil) 188 x->tail = t; 189 else 190 u->prev = t; 191 return t; 192 } 193 194 void 195 edestroy(Entry *e) 196 { 197 e->ref--; 198 if(e->ref == 0) 199 efree(e); 200 } 201 202 Entry * 203 ecreate(Entry *d, char *name, ulong n, ulong mode, ulong mtime, char **err) 204 { 205 int h; 206 Entry *e, *f; 207 208 h = hash(name) & HMASK; 209 for(e = d->htab[h]; e != nil; e = e->hnext) { 210 if(strcmp(e->name, name) == 0) { 211 *err = Eexists; 212 return nil; 213 } 214 } 215 216 e = emalloc9p(sizeof(Entry)); 217 e->ref = 1; 218 e->parent = d; 219 d->ref++; 220 f = d->htab[h]; 221 e->hnext = f; 222 e->hprev = nil; 223 if(f != nil) 224 f->hprev = e; 225 d->htab[h] = e; 226 f = d->files; 227 e->fnext = f; 228 e->fprev = nil; 229 if(f != nil) 230 f->fprev = e; 231 d->files = e; 232 233 d->ref--; 234 e->ref++; 235 e->name = estrdup9p(name); 236 if(n == 0) 237 n = fnum(); 238 else 239 maxfnum(n); 240 insertkey(map, n, e); 241 e->fnum = n; 242 e->mode = mode & d->mode; 243 e->mnum = 0; 244 e->mtime = mtime; 245 246 if(e->mode & DMDIR) 247 dirinit(e); 248 else 249 fileinit(e); 250 251 d->mtime = mtime; 252 return e; 253 } 254 255 void 256 etrunc(Entry *e, ulong n, ulong mtime) 257 { 258 extfree(e); 259 deletekey(map, e->fnum); 260 if(n == 0) 261 n = fnum(); 262 else 263 maxfnum(n); 264 e->fnum = n; 265 e->mnum = 0; 266 e->mtime = mtime; 267 insertkey(map, n, e); 268 fileinit(e); 269 e->parent->mtime = mtime; 270 } 271 272 char * 273 eremove(Entry *e) 274 { 275 Dirr *r; 276 Entry *d, *n, *p; 277 278 d = e->parent; 279 if(d == nil) 280 return Eperm; 281 282 if((e->mode & DMDIR) != 0 && e->files != nil) 283 return Edirnotempty; 284 285 p = e->hprev; 286 n = e->hnext; 287 if(n != nil) 288 n->hprev = p; 289 if(p != nil) 290 p->hnext = n; 291 else 292 d->htab[hash(e->name) & HMASK] = n; 293 294 for(r = d->readers; r != nil; r = r->next) { 295 if(r->cur == e) 296 r->cur = e->fnext; 297 } 298 299 p = e->fprev; 300 n = e->fnext; 301 if(n != nil) 302 n->fprev = p; 303 if(p != nil) 304 p->fnext = n; 305 else 306 d->files = n; 307 308 e->parent = nil; 309 d->ref--; 310 deletekey(map, e->fnum); 311 edestroy(e); 312 return nil; 313 } 314 315 Entry * 316 ewalk(Entry *d, char *name, char **err) 317 { 318 Entry *e; 319 320 if((d->mode & DMDIR) == 0) { 321 *err = Enotdir; 322 return nil; 323 } 324 325 if(strcmp(name, "..") == 0) { 326 e = d->parent; 327 if(e == nil) 328 return d; 329 edestroy(d); 330 e->ref++; 331 return e; 332 } 333 334 for(e = d->htab[hash(name) & HMASK]; e != nil; e = e->hnext) { 335 if(strcmp(e->name, name) == 0) { 336 d->ref--; 337 e->ref++; 338 return e; 339 } 340 } 341 342 *err = Enonexist; 343 return nil; 344 } 345 346 static void 347 eread0(Extent *e, Extent *x, uchar *a, ulong n, ulong off) 348 { 349 uchar *a0, *a1; 350 ulong n0, n1, o0, o1, d, z; 351 352 for(;;) { 353 while(e != nil) { 354 if(off < e->off + e->size && off + n > e->off) { 355 if(off >= e->off) { 356 d = off - e->off; 357 z = e->size - d; 358 if(n <= z) { 359 readdata(e->sect, a, n, e->addr + d); 360 return; 361 } 362 readdata(e->sect, a, z, e->addr + d); 363 a += z; 364 n -= z; 365 off += z; 366 } 367 else { 368 a0 = a; 369 n0 = e->off - off; 370 o0 = off; 371 a += n0; 372 n -= n0; 373 off += n0; 374 z = e->size; 375 if(n <= z) { 376 readdata(e->sect, a, n, e->addr); 377 a = a0; 378 n = n0; 379 off = o0; 380 } 381 else { 382 readdata(e->sect, a, z, e->addr); 383 a1 = a + z; 384 n1 = n - z; 385 o1 = off + z; 386 if(n0 < n1) { 387 eread0(e->next, x, a0, n0, o0); 388 a = a1; 389 n = n1; 390 off = o1; 391 } 392 else { 393 eread0(e->next, x, a1, n1, o1); 394 a = a0; 395 n = n0; 396 off = o0; 397 } 398 } 399 } 400 } 401 e = e->next; 402 } 403 404 if(x == nil) 405 break; 406 407 e = x; 408 x = nil; 409 } 410 411 memset(a, 0, n); 412 } 413 414 ulong 415 eread(Entry *e, int parity, void *a, ulong n, ulong off) 416 { 417 if(n + off >= e->size) 418 n = e->size - off; 419 if(n <= 0) 420 return 0; 421 eread0(e->gen[parity].head, e->gen[parity^1].head, a, n, off); 422 return n; 423 } 424 425 void 426 ewrite(Entry *e, Extent *x, int parity, ulong mtime) 427 { 428 ulong z; 429 Extent *t; 430 431 t = e->gen[parity].head; 432 x->next = t; 433 x->prev = nil; 434 e->gen[parity].head = x; 435 if(t == nil) 436 e->gen[parity].tail = x; 437 else 438 t->prev = x; 439 if(mtime != 0) 440 e->mtime = mtime; 441 used += x->size; 442 z = x->off + x->size; 443 if(z > e->size) 444 e->size = z; 445 } 446 447 ulong 448 echmod(Entry *e, ulong mode, ulong mnum) 449 { 450 if(mnum != 0) 451 e->mnum = mnum; 452 else 453 e->mnum++; 454 e->mode &= ~0777; 455 e->mode |= mode; 456 return e->mnum; 457 } 458 459 Qid 460 eqid(Entry *e) 461 { 462 Qid qid; 463 464 if(e->mode & DMDIR) 465 qid.type = QTDIR; 466 else 467 qid.type = 0; 468 qid.path = e->fnum; 469 return qid; 470 } 471 472 void 473 estat(Entry *e, Dir *d, int alloc) 474 { 475 d->type = 'z'; 476 d->dev = 0; 477 if(alloc) { 478 d->uid = estrdup9p(user); 479 d->gid = estrdup9p(user); 480 d->muid = estrdup9p(user); 481 d->name = estrdup9p(e->name); 482 } 483 else { 484 d->uid = user; 485 d->gid = user; 486 d->muid = user; 487 d->name = e->name; 488 } 489 d->mode = e->mode; 490 d->length = e->size; 491 d->atime = e->mtime; 492 d->mtime = e->mtime; 493 d->qid = eqid(e); 494 } 495 496 Dirr * 497 ediropen(Entry *e) 498 { 499 Dirr *d, *t; 500 501 d = emalloc9p(sizeof(Dirr)); 502 d->dir = e; 503 d->cur = e->files; 504 t = e->readers; 505 d->next = t; 506 d->prev = nil; 507 if(t != nil) 508 t->prev = d; 509 e->readers = d; 510 e->ref++; 511 return d; 512 } 513 514 int 515 edirread(Dirr *r, char *a, long n) 516 { 517 Dir d; 518 Entry *e; 519 int m, x; 520 521 m = 0; 522 for(e = r->cur; e != nil; e = e->fnext) { 523 estat(e, &d, 0); 524 x = convD2M(&d, (uchar *)a, n); 525 if(x <= BIT16SZ) 526 break; 527 a += x; 528 n -= x; 529 m += x; 530 } 531 532 r->cur = e; 533 return m; 534 } 535 536 void 537 edirclose(Dirr *d) 538 { 539 Entry *e; 540 Dirr *p, *n; 541 542 e = d->dir; 543 p = d->prev; 544 n = d->next; 545 if(n != nil) 546 n->prev = p; 547 if(p != nil) 548 p->next = n; 549 else 550 e->readers = n; 551 552 edestroy(e); 553 free(d); 554 } 555 556 static Renum R; 557 558 static void 559 xrenum(Extent *x) 560 { 561 while(x != nil) { 562 if(x->sect == R.old) 563 x->sect = R.new; 564 x = x->next; 565 } 566 } 567 568 static void 569 renum(Entry *e) 570 { 571 if(e->mode & DMDIR) { 572 for(e = e->files; e != nil; e = e->fnext) 573 renum(e); 574 } 575 else { 576 xrenum(e->gen[0].head); 577 xrenum(e->gen[1].head); 578 } 579 } 580 581 void 582 erenum(Renum *r) 583 { 584 R = *r; 585 renum(root); 586 } 587