1 #include "all.h" 2 #include "io.h" 3 4 enum { 5 Slop = 256, /* room at the start of a message buf for proto hdrs */ 6 }; 7 8 Filsys* 9 fsstr(char *p) 10 { 11 Filsys *fs; 12 13 for(fs=filsys; fs->name; fs++) 14 if(strcmp(fs->name, p) == 0) 15 return fs; 16 return 0; 17 } 18 19 Filsys* 20 dev2fs(Device *dev) 21 { 22 Filsys *fs; 23 24 for(fs=filsys; fs->name; fs++) 25 if(fs->dev == dev) 26 return fs; 27 return 0; 28 } 29 30 /* 31 * allocate 'count' contiguous channels 32 * of type 'type' and return pointer to base 33 */ 34 Chan* 35 fs_chaninit(int type, int count, int data) 36 { 37 uchar *p; 38 Chan *cp, *icp; 39 int i; 40 41 p = malloc(count * (sizeof(Chan)+data)); 42 icp = (Chan*)p; 43 for(i = 0; i < count; i++) { 44 cp = (Chan*)p; 45 cp->next = chans; 46 chans = cp; 47 cp->type = type; 48 cp->chan = cons.chano; 49 cons.chano++; 50 strncpy(cp->whoname, "<none>", sizeof cp->whoname); 51 wlock(&cp->reflock); 52 wunlock(&cp->reflock); 53 rlock(&cp->reflock); 54 runlock(&cp->reflock); 55 56 p += sizeof(Chan); 57 if(data){ 58 cp->pdata = p; 59 p += data; 60 } 61 } 62 return icp; 63 } 64 65 void 66 fileinit(Chan *cp) 67 { 68 File *f, *prev; 69 Tlock *t; 70 int h; 71 72 loop: 73 lock(&flock); 74 for (h=0; h < nelem(flist); h++) 75 for (prev=0, f = flist[h]; f; prev=f, f=f->next) { 76 if(f->cp != cp) 77 continue; 78 if(prev) { 79 prev->next = f->next; 80 f->next = flist[h]; 81 flist[h] = f; 82 } 83 flist[h] = f->next; 84 unlock(&flock); 85 86 qlock(f); 87 if(t = f->tlock) { 88 if(t->file == f) 89 t->time = 0; /* free the lock */ 90 f->tlock = 0; 91 } 92 if(f->open & FREMOV) 93 doremove(f, 0); 94 freewp(f->wpath); 95 f->open = 0; 96 authfree(f->auth); 97 f->auth = 0; 98 f->cp = 0; 99 qunlock(f); 100 goto loop; 101 } 102 unlock(&flock); 103 } 104 105 enum { NOFID = (ulong)~0 }; 106 107 /* 108 * returns a locked file structure 109 */ 110 File* 111 filep(Chan *cp, ulong fid, int flag) 112 { 113 File *f; 114 int h; 115 116 if(fid == NOFID) 117 return 0; 118 119 h = (long)(uintptr)cp + fid; 120 if(h < 0) 121 h = ~h; 122 h %= nelem(flist); 123 124 loop: 125 lock(&flock); 126 for(f=flist[h]; f; f=f->next) 127 if(f->fid == fid && f->cp == cp){ 128 /* 129 * Already in use is an error 130 * when called from attach or clone (walk 131 * in 9P2000). The console uses FID[12] and 132 * never clunks them so catch that case. 133 */ 134 if(flag == 0 || cp == cons.chan) 135 goto out; 136 unlock(&flock); 137 return 0; 138 } 139 140 if(flag) { 141 f = newfp(); 142 if(f) { 143 f->fid = fid; 144 f->cp = cp; 145 f->wpath = 0; 146 f->tlock = 0; 147 f->doffset = 0; 148 f->dslot = 0; 149 f->auth = 0; 150 f->next = flist[h]; 151 flist[h] = f; 152 goto out; 153 } 154 } 155 unlock(&flock); 156 return 0; 157 158 out: 159 unlock(&flock); 160 qlock(f); 161 if(f->fid == fid && f->cp == cp) 162 return f; 163 qunlock(f); 164 goto loop; 165 } 166 167 /* 168 * always called with flock locked 169 */ 170 File* 171 newfp(void) 172 { 173 static int first; 174 File *f; 175 int start, i; 176 177 i = first; 178 start = i; 179 do { 180 f = &files[i]; 181 i++; 182 if(i >= conf.nfile) 183 i = 0; 184 if(f->cp) 185 continue; 186 first = i; 187 return f; 188 } while(i != start); 189 190 print("out of files\n"); 191 return 0; 192 } 193 194 void 195 freefp(File *fp) 196 { 197 Chan *cp; 198 File *f, *prev; 199 int h; 200 201 if(!fp || !(cp = fp->cp)) 202 return; 203 204 h = (long)(uintptr)cp + fp->fid; 205 if(h < 0) 206 h = ~h; 207 h %= nelem(flist); 208 209 lock(&flock); 210 for(prev=0,f=flist[h]; f; prev=f,f=f->next) 211 if(f == fp) { 212 if(prev) 213 prev->next = f->next; 214 else 215 flist[h] = f->next; 216 break; 217 } 218 fp->cp = 0; 219 unlock(&flock); 220 } 221 222 int 223 iaccess(File *f, Dentry *d, int m) 224 { 225 /* uid none gets only other permissions */ 226 if(f->uid != 0) { 227 /* 228 * owner 229 */ 230 if(f->uid == d->uid) 231 if((m<<6) & d->mode) 232 return 0; 233 /* 234 * group membership 235 */ 236 if(ingroup(f->uid, d->gid)) 237 if((m<<3) & d->mode) 238 return 0; 239 } 240 241 /* 242 * other 243 */ 244 if(m & d->mode) { 245 if((d->mode & DDIR) && (m == DEXEC)) 246 return 0; 247 if(!ingroup(f->uid, 9999)) 248 return 0; 249 } 250 251 /* 252 * various forms of superuser 253 */ 254 if(wstatallow) 255 return 0; 256 if(duallow != 0 && duallow == f->uid) 257 if((d->mode & DDIR) && (m == DREAD || m == DEXEC)) 258 return 0; 259 260 return 1; 261 } 262 263 Tlock* 264 tlocked(Iobuf *p, Dentry *d) 265 { 266 Tlock *t, *t1; 267 Off qpath; 268 Timet tim; 269 Device *dev; 270 271 tim = toytime(); 272 qpath = d->qid.path; 273 dev = p->dev; 274 275 again: 276 t1 = 0; 277 for(t=tlocks+NTLOCK-1; t>=tlocks; t--) { 278 if(t->qpath == qpath) 279 if(t->time >= tim) 280 if(t->dev == dev) 281 return nil; /* its locked */ 282 if(t1 != nil && t->time == 0) 283 t1 = t; /* remember free lock */ 284 } 285 if(t1 == 0) { 286 // reclaim old locks 287 lock(&tlocklock); 288 for(t=tlocks+NTLOCK-1; t>=tlocks; t--) 289 if(t->time < tim) { 290 t->time = 0; 291 t1 = t; 292 } 293 unlock(&tlocklock); 294 } 295 if(t1) { 296 lock(&tlocklock); 297 if(t1->time != 0) { 298 unlock(&tlocklock); 299 goto again; 300 } 301 t1->dev = dev; 302 t1->qpath = qpath; 303 t1->time = tim + TLOCK; 304 unlock(&tlocklock); 305 } 306 /* botch 307 * out of tlock nodes simulates 308 * a locked file 309 */ 310 return t1; 311 } 312 313 Wpath* 314 newwp(void) 315 { 316 static int si = 0; 317 int i; 318 Wpath *w, *sw, *ew; 319 320 i = si + 1; 321 if(i < 0 || i >= conf.nwpath) 322 i = 0; 323 si = i; 324 sw = &wpaths[i]; 325 ew = &wpaths[conf.nwpath]; 326 for(w=sw;;) { 327 w++; 328 if(w >= ew) 329 w = &wpaths[0]; 330 if(w == sw) { 331 print("out of wpaths\n"); 332 return 0; 333 } 334 if(w->refs) 335 continue; 336 lock(&wpathlock); 337 if(w->refs) { 338 unlock(&wpathlock); 339 continue; 340 } 341 w->refs = 1; 342 w->up = 0; 343 unlock(&wpathlock); 344 return w; 345 } 346 347 } 348 349 void 350 freewp(Wpath *w) 351 { 352 lock(&wpathlock); 353 for(; w; w=w->up) 354 w->refs--; 355 unlock(&wpathlock); 356 } 357 358 Off 359 qidpathgen(Device *dev) 360 { 361 Iobuf *p; 362 Superb *sb; 363 Off path; 364 365 p = getbuf(dev, superaddr(dev), Brd|Bmod); 366 if(!p || checktag(p, Tsuper, QPSUPER)) 367 panic("newqid: super block"); 368 sb = (Superb*)p->iobuf; 369 sb->qidgen++; 370 path = sb->qidgen; 371 putbuf(p); 372 return path; 373 } 374 375 /* truncating to length > 0 */ 376 static void 377 truncfree(Truncstate *ts, Device *dev, int d, Iobuf *p, int i) 378 { 379 int pastlast; 380 Off a; 381 382 pastlast = ts->pastlast; 383 a = ((Off *)p->iobuf)[i]; 384 if (d > 0 || pastlast) 385 buffree(dev, a, d, ts); 386 if (pastlast) { 387 ((Off *)p->iobuf)[i] = 0; 388 p->flags |= Bmod|Bimm; 389 } else if (d == 0 && ts->relblk == ts->lastblk) 390 ts->pastlast = 1; 391 if (d == 0) 392 ts->relblk++; 393 } 394 395 /* 396 * free the block at `addr' on dev. 397 * if it's an indirect block (d [depth] > 0), 398 * first recursively free all the blocks it names. 399 * 400 * ts->relblk is the block number within the file of this 401 * block (or the first data block eventually pointed to via 402 * this indirect block). 403 */ 404 void 405 buffree(Device *dev, Off addr, int d, Truncstate *ts) 406 { 407 Iobuf *p; 408 Off a; 409 int i, pastlast; 410 411 if(!addr) 412 return; 413 pastlast = (ts == nil? 1: ts->pastlast); 414 /* 415 * if this is an indirect block, recurse and free any 416 * suitable blocks within it (possibly via further indirect blocks). 417 */ 418 if(d > 0) { 419 d--; 420 p = getbuf(dev, addr, Brd); 421 if(p) { 422 if (ts == nil) /* common case: create */ 423 for(i=INDPERBUF-1; i>=0; i--) { 424 a = ((Off *)p->iobuf)[i]; 425 buffree(dev, a, d, nil); 426 } 427 else /* wstat truncation */ 428 for (i = 0; i < INDPERBUF; i++) 429 truncfree(ts, dev, d, p, i); 430 putbuf(p); 431 } 432 } 433 if (!pastlast) 434 return; 435 /* 436 * having zeroed the pointer to this block, add it to the free list. 437 * stop outstanding i/o 438 */ 439 p = getbuf(dev, addr, Bprobe); 440 if(p) { 441 p->flags &= ~(Bmod|Bimm); 442 putbuf(p); 443 } 444 /* 445 * dont put written worm 446 * blocks into free list 447 */ 448 if(dev->type == Devcw) { 449 i = cwfree(dev, addr); 450 if(i) 451 return; 452 } 453 p = getbuf(dev, superaddr(dev), Brd|Bmod); 454 if(!p || checktag(p, Tsuper, QPSUPER)) 455 panic("buffree: super block"); 456 addfree(dev, addr, (Superb*)p->iobuf); 457 putbuf(p); 458 } 459 460 Off 461 bufalloc(Device *dev, int tag, long qid, int uid) 462 { 463 Iobuf *bp, *p; 464 Superb *sb; 465 Off a, n; 466 467 p = getbuf(dev, superaddr(dev), Brd|Bmod); 468 if(!p || checktag(p, Tsuper, QPSUPER)) { 469 print("bufalloc: super block\n"); 470 if(p) 471 putbuf(p); 472 return 0; 473 } 474 sb = (Superb*)p->iobuf; 475 476 loop: 477 n = --sb->fbuf.nfree; 478 sb->tfree--; 479 if(n < 0 || n >= FEPERBUF) { 480 print("bufalloc: %Z: bad freelist\n", dev); 481 n = 0; 482 sb->fbuf.free[0] = 0; 483 } 484 a = sb->fbuf.free[n]; 485 if(n <= 0) { 486 if(a == 0) { 487 sb->tfree = 0; 488 sb->fbuf.nfree = 1; 489 if(dev->type == Devcw) { 490 n = uid; 491 if(n < 0 || n >= nelem(growacct)) 492 n = 0; 493 growacct[n]++; 494 if(cwgrow(dev, sb, uid)) 495 goto loop; 496 } 497 putbuf(p); 498 print("fs %Z full uid=%d\n", dev, uid); 499 return 0; 500 } 501 bp = getbuf(dev, a, Brd); 502 if(!bp || checktag(bp, Tfree, QPNONE)) { 503 if(bp) 504 putbuf(bp); 505 putbuf(p); 506 return 0; 507 } 508 sb->fbuf = *(Fbuf*)bp->iobuf; 509 putbuf(bp); 510 } 511 512 bp = getbuf(dev, a, Bmod); 513 memset(bp->iobuf, 0, RBUFSIZE); 514 settag(bp, tag, qid); 515 if(tag == Tind1 || tag == Tind2 || 516 #ifndef COMPAT32 517 tag == Tind3 || tag == Tind4 || /* add more Tind tags here ... */ 518 #endif 519 tag == Tdir) 520 bp->flags |= Bimm; 521 putbuf(bp); 522 putbuf(p); 523 return a; 524 } 525 526 /* 527 * what are legal characters in a name? 528 * only disallow control characters. 529 * a) utf avoids control characters. 530 * b) '/' may not be the separator 531 */ 532 int 533 checkname(char *n) 534 { 535 int i, c; 536 537 for(i=0; i<NAMELEN; i++) { 538 c = *n & 0xff; 539 if(c == 0) { 540 if(i == 0) 541 return 1; 542 memset(n, 0, NAMELEN-i); 543 return 0; 544 } 545 if(c <= 040) 546 return 1; 547 n++; 548 } 549 return 1; /* too long */ 550 } 551 552 void 553 addfree(Device *dev, Off addr, Superb *sb) 554 { 555 int n; 556 Iobuf *p; 557 558 n = sb->fbuf.nfree; 559 if(n < 0 || n > FEPERBUF) 560 panic("addfree: bad freelist"); 561 if(n >= FEPERBUF) { 562 p = getbuf(dev, addr, Bmod|Bimm); 563 if(p == 0) 564 panic("addfree: getbuf"); 565 *(Fbuf*)p->iobuf = sb->fbuf; 566 settag(p, Tfree, QPNONE); 567 putbuf(p); 568 n = 0; 569 } 570 sb->fbuf.free[n++] = addr; 571 sb->fbuf.nfree = n; 572 sb->tfree++; 573 if(addr >= sb->fsize) 574 sb->fsize = addr+1; 575 } 576 577 /* 578 static int 579 Yfmt(Fmt* fmt) 580 { 581 Chan *cp; 582 char s[20]; 583 584 cp = va_arg(fmt->args, Chan*); 585 sprint(s, "C%d.%.3d", cp->type, cp->chan); 586 return fmtstrcpy(fmt, s); 587 } 588 */ 589 590 static int 591 Zfmt(Fmt* fmt) 592 { 593 Device *d; 594 int c, c1; 595 char s[100]; 596 597 d = va_arg(fmt->args, Device*); 598 if(d == nil) { 599 sprint(s, "Z***"); 600 goto out; 601 } 602 c = c1 = '\0'; 603 switch(d->type) { 604 default: 605 sprint(s, "D%d", d->type); 606 break; 607 case Devwren: 608 c = 'w'; 609 /* fallthrough */ 610 case Devworm: 611 if (c == '\0') 612 c = 'r'; 613 /* fallthrough */ 614 case Devlworm: 615 if (c == '\0') 616 c = 'l'; 617 if(d->wren.ctrl == 0 && d->wren.lun == 0) 618 sprint(s, "%c%d", c, d->wren.targ); 619 else 620 sprint(s, "%c%d.%d.%d", c, d->wren.ctrl, d->wren.targ, 621 d->wren.lun); 622 break; 623 case Devmcat: 624 c = '('; 625 c1 = ')'; 626 /* fallthrough */ 627 case Devmlev: 628 if (c == '\0') { 629 c = '['; 630 c1 = ']'; 631 } 632 /* fallthrough */ 633 case Devmirr: 634 if (c == '\0') { 635 c = '{'; 636 c1 = '}'; 637 } 638 if(d->cat.first == d->cat.last) 639 sprint(s, "%c%Z%c", c, d->cat.first, c1); 640 else if(d->cat.first->link == d->cat.last) 641 sprint(s, "%c%Z%Z%c", c, d->cat.first, d->cat.last, c1); 642 else 643 sprint(s, "%c%Z-%Z%c", c, d->cat.first, d->cat.last, c1); 644 break; 645 case Devro: 646 sprint(s, "o%Z%Z", d->ro.parent->cw.c, d->ro.parent->cw.w); 647 break; 648 case Devcw: 649 sprint(s, "c%Z%Z", d->cw.c, d->cw.w); 650 break; 651 case Devjuke: 652 sprint(s, "j%Z%Z", d->j.j, d->j.m); 653 break; 654 case Devfworm: 655 sprint(s, "f%Z", d->fw.fw); 656 break; 657 case Devpart: 658 sprint(s, "p(%Z)%ld.%ld", d->part.d, d->part.base, d->part.size); 659 break; 660 case Devswab: 661 sprint(s, "x%Z", d->swab.d); 662 break; 663 case Devnone: 664 sprint(s, "n"); 665 break; 666 } 667 out: 668 return fmtstrcpy(fmt, s); 669 } 670 671 static int 672 Gfmt(Fmt* fmt) 673 { 674 int t; 675 char *s; 676 677 t = va_arg(fmt->args, int); 678 s = "<badtag>"; 679 if(t >= 0 && t < MAXTAG) 680 s = tagnames[t]; 681 return fmtstrcpy(fmt, s); 682 } 683 684 void 685 formatinit(void) 686 { 687 quotefmtinstall(); 688 // fmtinstall('Y', Yfmt); /* print channels */ 689 fmtinstall('Z', Zfmt); /* print devices */ 690 fmtinstall('G', Gfmt); /* print tags */ 691 fmtinstall('T', Tfmt); /* print times */ 692 // fmtinstall('E', eipfmt); /* print ether addresses */ 693 fmtinstall('I', eipfmt); /* print ip addresses */ 694 } 695 696 void 697 rootream(Device *dev, Off addr) 698 { 699 Iobuf *p; 700 Dentry *d; 701 702 p = getbuf(dev, addr, Bmod|Bimm); 703 memset(p->iobuf, 0, RBUFSIZE); 704 settag(p, Tdir, QPROOT); 705 d = getdir(p, 0); 706 strcpy(d->name, "/"); 707 d->uid = -1; 708 d->gid = -1; 709 d->mode = DALLOC | DDIR | 710 ((DREAD|DEXEC) << 6) | 711 ((DREAD|DEXEC) << 3) | 712 ((DREAD|DEXEC) << 0); 713 d->qid = QID9P1(QPROOT|QPDIR,0); 714 d->atime = time(nil); 715 d->mtime = d->atime; 716 d->muid = 0; 717 putbuf(p); 718 } 719 720 void 721 superream(Device *dev, Off addr) 722 { 723 Iobuf *p; 724 Superb *s; 725 Off i; 726 727 p = getbuf(dev, addr, Bmod|Bimm); 728 memset(p->iobuf, 0, RBUFSIZE); 729 settag(p, Tsuper, QPSUPER); 730 731 s = (Superb*)p->iobuf; 732 s->fstart = 2; 733 s->fsize = devsize(dev); 734 s->fbuf.nfree = 1; 735 s->qidgen = 10; 736 for(i = s->fsize-1; i >= addr+2; i--) 737 addfree(dev, i, s); 738 putbuf(p); 739 } 740 741 struct 742 { 743 Lock; 744 Msgbuf *smsgbuf; 745 Msgbuf *lmsgbuf; 746 } msgalloc; 747 748 /* 749 * pre-allocate some message buffers at boot time. 750 * if this supply is exhausted, more will be allocated as needed. 751 */ 752 void 753 mbinit(void) 754 { 755 Msgbuf *mb; 756 Rabuf *rb; 757 int i; 758 759 lock(&msgalloc); 760 unlock(&msgalloc); 761 msgalloc.lmsgbuf = 0; 762 msgalloc.smsgbuf = 0; 763 for(i=0; i<conf.nlgmsg; i++) { 764 mb = malloc(sizeof(Msgbuf)); 765 mb->magic = Mbmagic; 766 mb->xdata = malloc(LARGEBUF+Slop); 767 mb->flags = LARGE; 768 mbfree(mb); 769 cons.nlarge++; 770 } 771 for(i=0; i<conf.nsmmsg; i++) { 772 mb = malloc(sizeof(Msgbuf)); 773 mb->magic = Mbmagic; 774 mb->xdata = malloc(SMALLBUF+Slop); 775 mb->flags = 0; 776 mbfree(mb); 777 cons.nsmall++; 778 } 779 memset(mballocs, 0, sizeof(mballocs)); 780 781 lock(&rabuflock); 782 unlock(&rabuflock); 783 rabuffree = 0; 784 for(i=0; i<1000; i++) { 785 rb = malloc(sizeof(*rb)); 786 rb->link = rabuffree; 787 rabuffree = rb; 788 } 789 } 790 791 Msgbuf* 792 mballoc(int count, Chan *cp, int category) 793 { 794 Msgbuf *mb; 795 796 lock(&msgalloc); 797 if(count > SMALLBUF) { 798 if(count > LARGEBUF) 799 panic("msgbuf count"); 800 mb = msgalloc.lmsgbuf; 801 if(mb == nil) { 802 mb = malloc(sizeof(Msgbuf)); 803 mb->xdata = malloc(LARGEBUF+Slop); 804 cons.nlarge++; 805 } else 806 msgalloc.lmsgbuf = mb->next; 807 mb->flags = LARGE; 808 } else { 809 mb = msgalloc.smsgbuf; 810 if(mb == nil) { 811 mb = malloc(sizeof(Msgbuf)); 812 mb->xdata = malloc(SMALLBUF+Slop); 813 cons.nsmall++; 814 } else 815 msgalloc.smsgbuf = mb->next; 816 mb->flags = 0; 817 } 818 mballocs[category]++; 819 unlock(&msgalloc); 820 mb->magic = Mbmagic; 821 mb->count = count; 822 mb->chan = cp; 823 mb->next = 0; 824 mb->param = 0; 825 mb->category = category; 826 mb->data = mb->xdata+Slop; 827 return mb; 828 } 829 830 void 831 mbfree(Msgbuf *mb) 832 { 833 if(mb == nil) 834 return; 835 assert(mb->magic == Mbmagic); 836 if (mb->magic != Mbmagic) 837 panic("mbfree: bad magic 0x%lux", mb->magic); 838 if(mb->flags & BTRACE) 839 print("mbfree: BTRACE cat=%d flags=%ux, caller %#p\n", 840 mb->category, mb->flags, getcallerpc(&mb)); 841 842 if(mb->flags & FREE) 843 panic("mbfree already free"); 844 845 lock(&msgalloc); 846 mballocs[mb->category]--; 847 mb->flags |= FREE; 848 if(mb->flags & LARGE) { 849 mb->next = msgalloc.lmsgbuf; 850 msgalloc.lmsgbuf = mb; 851 } else { 852 mb->next = msgalloc.smsgbuf; 853 msgalloc.smsgbuf = mb; 854 } 855 mb->data = 0; 856 mb->magic = 0; 857 unlock(&msgalloc); 858 } 859 860 /* 861 * returns 1 if n is prime 862 * used for adjusting lengths 863 * of hashing things. 864 * there is no need to be clever 865 */ 866 int 867 prime(vlong n) 868 { 869 long i; 870 871 if((n%2) == 0) 872 return 0; 873 for(i=3;; i+=2) { 874 if((n%i) == 0) 875 return 0; 876 if((vlong)i*i >= n) 877 return 1; 878 } 879 } 880 881 char* 882 getwrd(char *word, char *line) 883 { 884 int c, n; 885 886 while(isascii(*line) && isspace(*line) && *line != '\n') 887 line++; 888 for(n = 0; n < Maxword; n++) { 889 c = *line; 890 if(c == '\0' || isascii(c) && isspace(c)) 891 break; 892 line++; 893 *word++ = c; 894 } 895 *word = 0; 896 return line; 897 } 898 899 void 900 hexdump(void *a, int n) 901 { 902 char s1[30], s2[4]; 903 uchar *p; 904 int i; 905 906 p = a; 907 s1[0] = 0; 908 for(i = 0; i < n; i++) { 909 sprint(s2, " %.2ux", p[i]); 910 strcat(s1, s2); 911 if((i&7) == 7) { 912 print("%s\n", s1); 913 s1[0] = 0; 914 } 915 } 916 if(s1[0]) 917 print("%s\n", s1); 918 } 919 920 void* 921 fs_recv(Queue *q, int) 922 { 923 void *a; 924 int i, c; 925 926 if(q == nil) 927 panic("recv null q"); 928 qlock(q); 929 q->waitedfor = 1; 930 while((c = q->count) <= 0) 931 rsleep(&q->empty); 932 i = q->loc; 933 a = q->args[i]; 934 i++; 935 if(i >= q->size) 936 i = 0; 937 q->loc = i; 938 q->count = c-1; 939 rwakeup(&q->full); /* no longer full */ 940 qunlock(q); 941 return a; 942 } 943 944 void 945 fs_send(Queue *q, void *a) 946 { 947 int i, c; 948 949 if(q == nil) 950 panic("send null q"); 951 if(!q->waitedfor) { 952 for (i = 0; i < 5 && !q->waitedfor; i++) 953 sleep(1000); 954 if(!q->waitedfor) { 955 /* likely a bug; don't wait forever */ 956 print("no readers yet for %s q\n", q->name); 957 abort(); 958 } 959 } 960 qlock(q); 961 while((c = q->count) >= q->size) 962 rsleep(&q->full); 963 i = q->loc + c; 964 if(i >= q->size) 965 i -= q->size; 966 q->args[i] = a; 967 q->count = c+1; 968 rwakeup(&q->empty); /* no longer empty */ 969 qunlock(q); 970 } 971 972 Queue* 973 newqueue(int size, char *name) 974 { 975 Queue *q; 976 977 q = malloc(sizeof(Queue) + (size-1)*sizeof(void*)); 978 q->size = size; 979 q->full.l = q->empty.l = &q->QLock; 980 q->name = name; 981 return q; 982 } 983 984 int 985 devread(Device *d, Off b, void *c) 986 { 987 int e; 988 989 for (;;) 990 switch(d->type) { 991 case Devcw: 992 return cwread(d, b, c); 993 994 case Devjuke: 995 d = d->j.m; 996 break; 997 998 case Devro: 999 return roread(d, b, c); 1000 1001 case Devwren: 1002 return wrenread(d, b, c); 1003 1004 case Devworm: 1005 case Devlworm: 1006 return wormread(d, b, c); 1007 1008 case Devfworm: 1009 return fwormread(d, b, c); 1010 1011 case Devmcat: 1012 return mcatread(d, b, c); 1013 1014 case Devmlev: 1015 return mlevread(d, b, c); 1016 1017 case Devmirr: 1018 return mirrread(d, b, c); 1019 1020 case Devpart: 1021 return partread(d, b, c); 1022 1023 case Devswab: 1024 e = devread(d->swab.d, b, c); 1025 if(e == 0) 1026 swab(c, 0); 1027 return e; 1028 1029 case Devnone: 1030 print("read from device none(%lld)\n", (Wideoff)b); 1031 return 1; 1032 default: 1033 panic("illegal device in devread: %Z %lld", 1034 d, (Wideoff)b); 1035 return 1; 1036 } 1037 } 1038 1039 int 1040 devwrite(Device *d, Off b, void *c) 1041 { 1042 int e; 1043 1044 /* 1045 * set readonly to non-0 to prevent all writes; 1046 * mainly for trying dangerous experiments. 1047 */ 1048 if (readonly) 1049 return 0; 1050 for (;;) 1051 switch(d->type) { 1052 case Devcw: 1053 return cwwrite(d, b, c); 1054 1055 case Devjuke: 1056 d = d->j.m; 1057 break; 1058 1059 case Devro: 1060 print("write to ro device %Z(%lld)\n", d, (Wideoff)b); 1061 return 1; 1062 1063 case Devwren: 1064 return wrenwrite(d, b, c); 1065 1066 case Devworm: 1067 case Devlworm: 1068 return wormwrite(d, b, c); 1069 1070 case Devfworm: 1071 return fwormwrite(d, b, c); 1072 1073 case Devmcat: 1074 return mcatwrite(d, b, c); 1075 1076 case Devmlev: 1077 return mlevwrite(d, b, c); 1078 1079 case Devmirr: 1080 return mirrwrite(d, b, c); 1081 1082 case Devpart: 1083 return partwrite(d, b, c); 1084 1085 case Devswab: 1086 swab(c, 1); 1087 e = devwrite(d->swab.d, b, c); 1088 swab(c, 0); 1089 return e; 1090 1091 case Devnone: 1092 /* checktag() can generate blocks with type devnone */ 1093 return 0; 1094 default: 1095 panic("illegal device in devwrite: %Z %lld", 1096 d, (Wideoff)b); 1097 return 1; 1098 } 1099 } 1100 1101 Devsize 1102 devsize(Device *d) 1103 { 1104 for (;;) 1105 switch(d->type) { 1106 case Devcw: 1107 case Devro: 1108 return cwsize(d); 1109 1110 case Devjuke: 1111 d = d->j.m; 1112 break; 1113 1114 case Devwren: 1115 return wrensize(d); 1116 1117 case Devworm: 1118 case Devlworm: 1119 return wormsize(d); 1120 1121 case Devfworm: 1122 return fwormsize(d); 1123 1124 case Devmcat: 1125 return mcatsize(d); 1126 1127 case Devmlev: 1128 return mlevsize(d); 1129 1130 case Devmirr: 1131 return mirrsize(d); 1132 1133 case Devpart: 1134 return partsize(d); 1135 1136 case Devswab: 1137 d = d->swab.d; 1138 break; 1139 default: 1140 panic("illegal device in devsize: %Z", d); 1141 return 0; 1142 } 1143 } 1144 1145 /* result is malloced */ 1146 char * 1147 sdof(Device *d) 1148 { 1149 static char name[256]; 1150 1151 for (;;) 1152 switch(d->type) { 1153 case Devjuke: 1154 d = d->j.j; /* robotics */ 1155 break; 1156 case Devwren: 1157 snprint(name, sizeof name, "/dev/sd%d%d", d->wren.ctrl, 1158 d->wren.targ); 1159 return strdup(name); 1160 case Devswab: 1161 d = d->swab.d; 1162 break; 1163 default: 1164 panic("illegal device in sdof: %Z", d); 1165 return nil; 1166 } 1167 } 1168 1169 Off 1170 superaddr(Device *d) 1171 { 1172 for (;;) 1173 switch(d->type) { 1174 default: 1175 return SUPER_ADDR; 1176 case Devcw: 1177 case Devro: 1178 return cwsaddr(d); 1179 case Devswab: 1180 d = d->swab.d; 1181 break; 1182 } 1183 } 1184 1185 Off 1186 getraddr(Device *d) 1187 { 1188 for (;;) 1189 switch(d->type) { 1190 default: 1191 return ROOT_ADDR; 1192 case Devcw: 1193 case Devro: 1194 return cwraddr(d); 1195 case Devswab: 1196 d = d->swab.d; 1197 break; 1198 } 1199 } 1200 1201 void 1202 devream(Device *d, int top) 1203 { 1204 Device *l; 1205 1206 loop: 1207 print("\tdevream: %Z %d\n", d, top); 1208 switch(d->type) { 1209 default: 1210 print("ream: unknown dev type %Z\n", d); 1211 return; 1212 1213 case Devcw: 1214 devream(d->cw.w, 0); 1215 devream(d->cw.c, 0); 1216 if(top) { 1217 wlock(&mainlock); 1218 cwream(d); 1219 wunlock(&mainlock); 1220 } 1221 devinit(d); 1222 return; 1223 1224 case Devfworm: 1225 devream(d->fw.fw, 0); 1226 fwormream(d); 1227 break; 1228 1229 case Devpart: 1230 devream(d->part.d, 0); 1231 break; 1232 1233 case Devmlev: 1234 case Devmcat: 1235 case Devmirr: 1236 for(l=d->cat.first; l; l=l->link) 1237 devream(l, 0); 1238 break; 1239 1240 case Devjuke: 1241 case Devworm: 1242 case Devlworm: 1243 case Devwren: 1244 break; 1245 1246 case Devswab: 1247 d = d->swab.d; 1248 goto loop; 1249 } 1250 devinit(d); 1251 if(top) { 1252 wlock(&mainlock); 1253 rootream(d, ROOT_ADDR); 1254 superream(d, SUPER_ADDR); 1255 wunlock(&mainlock); 1256 } 1257 } 1258 1259 void 1260 devrecover(Device *d) 1261 { 1262 for (;;) { 1263 print("recover: %Z\n", d); 1264 switch(d->type) { 1265 default: 1266 print("recover: unknown dev type %Z\n", d); 1267 return; 1268 1269 case Devcw: 1270 wlock(&mainlock); /* recover */ 1271 cwrecover(d); 1272 wunlock(&mainlock); 1273 return; 1274 1275 case Devswab: 1276 d = d->swab.d; 1277 break; 1278 } 1279 } 1280 } 1281 1282 void 1283 devinit(Device *d) 1284 { 1285 for (;;) { 1286 if(d->init) 1287 return; 1288 d->init = 1; 1289 print("\tdevinit %Z\n", d); 1290 switch(d->type) { 1291 default: 1292 print("devinit unknown device %Z\n", d); 1293 return; 1294 1295 case Devro: 1296 cwinit(d->ro.parent); 1297 return; 1298 1299 case Devcw: 1300 cwinit(d); 1301 return; 1302 1303 case Devjuke: 1304 jukeinit(d); 1305 return; 1306 1307 case Devwren: 1308 wreninit(d); 1309 return; 1310 1311 case Devworm: 1312 case Devlworm: 1313 return; 1314 1315 case Devfworm: 1316 fworminit(d); 1317 return; 1318 1319 case Devmcat: 1320 mcatinit(d); 1321 return; 1322 1323 case Devmlev: 1324 mlevinit(d); 1325 return; 1326 1327 case Devmirr: 1328 mirrinit(d); 1329 return; 1330 1331 case Devpart: 1332 partinit(d); 1333 return; 1334 1335 case Devswab: 1336 d = d->swab.d; 1337 break; 1338 1339 case Devnone: 1340 print("devinit of Devnone\n"); 1341 return; 1342 } 1343 } 1344 } 1345 1346 void 1347 swab2(void *c) 1348 { 1349 uchar *p; 1350 int t; 1351 1352 p = c; 1353 1354 t = p[0]; 1355 p[0] = p[1]; 1356 p[1] = t; 1357 } 1358 1359 void 1360 swab4(void *c) 1361 { 1362 uchar *p; 1363 int t; 1364 1365 p = c; 1366 1367 t = p[0]; 1368 p[0] = p[3]; 1369 p[3] = t; 1370 1371 t = p[1]; 1372 p[1] = p[2]; 1373 p[2] = t; 1374 } 1375 1376 void 1377 swab8(void *c) 1378 { 1379 uchar *p; 1380 int t; 1381 1382 p = c; 1383 1384 t = p[0]; 1385 p[0] = p[7]; 1386 p[7] = t; 1387 1388 t = p[1]; 1389 p[1] = p[6]; 1390 p[6] = t; 1391 1392 t = p[2]; 1393 p[2] = p[5]; 1394 p[5] = t; 1395 1396 t = p[3]; 1397 p[3] = p[4]; 1398 p[4] = t; 1399 } 1400 1401 /* 1402 * swab a block 1403 * flag = 0 -- convert from foreign to native 1404 * flag = 1 -- convert from native to foreign 1405 */ 1406 void 1407 swab(void *c, int flag) 1408 { 1409 uchar *p; 1410 Tag *t; 1411 int i, j; 1412 Dentry *d; 1413 Cache *h; 1414 Bucket *b; 1415 Superb *s; 1416 Fbuf *f; 1417 Off *l; 1418 1419 /* swab the tag */ 1420 p = (uchar*)c; 1421 t = (Tag*)(p + BUFSIZE); 1422 if(!flag) { 1423 swab2(&t->pad); 1424 swab2(&t->tag); 1425 swaboff(&t->path); 1426 } 1427 1428 /* swab each block type */ 1429 switch(t->tag) { 1430 1431 default: 1432 print("no swab for tag=%G rw=%d\n", t->tag, flag); 1433 for(j=0; j<16; j++) 1434 print(" %.2x", p[BUFSIZE+j]); 1435 print("\n"); 1436 for(i=0; i<16; i++) { 1437 print("%.4x", i*16); 1438 for(j=0; j<16; j++) 1439 print(" %.2x", p[i*16+j]); 1440 print("\n"); 1441 } 1442 panic("swab"); 1443 break; 1444 1445 case Tsuper: 1446 s = (Superb*)p; 1447 swaboff(&s->fbuf.nfree); 1448 for(i=0; i<FEPERBUF; i++) 1449 swaboff(&s->fbuf.free[i]); 1450 swaboff(&s->fstart); 1451 swaboff(&s->fsize); 1452 swaboff(&s->tfree); 1453 swaboff(&s->qidgen); 1454 swaboff(&s->cwraddr); 1455 swaboff(&s->roraddr); 1456 swaboff(&s->last); 1457 swaboff(&s->next); 1458 break; 1459 1460 case Tdir: 1461 for(i=0; i<DIRPERBUF; i++) { 1462 d = (Dentry*)p + i; 1463 swab2(&d->uid); 1464 swab2(&d->gid); 1465 swab2(&d->mode); 1466 swab2(&d->muid); 1467 swaboff(&d->qid.path); 1468 swab4(&d->qid.version); 1469 swaboff(&d->size); 1470 for(j=0; j<NDBLOCK; j++) 1471 swaboff(&d->dblock[j]); 1472 for (j = 0; j < NIBLOCK; j++) 1473 swaboff(&d->iblocks[j]); 1474 swab4(&d->atime); 1475 swab4(&d->mtime); 1476 } 1477 break; 1478 1479 case Tind1: 1480 case Tind2: 1481 #ifndef COMPAT32 1482 case Tind3: 1483 case Tind4: 1484 /* add more Tind tags here ... */ 1485 #endif 1486 l = (Off *)p; 1487 for(i=0; i<INDPERBUF; i++) { 1488 swaboff(l); 1489 l++; 1490 } 1491 break; 1492 1493 case Tfree: 1494 f = (Fbuf*)p; 1495 swaboff(&f->nfree); 1496 for(i=0; i<FEPERBUF; i++) 1497 swaboff(&f->free[i]); 1498 break; 1499 1500 case Tbuck: 1501 for(i=0; i<BKPERBLK; i++) { 1502 b = (Bucket*)p + i; 1503 swab4(&b->agegen); 1504 for(j=0; j<CEPERBK; j++) { 1505 swab2(&b->entry[j].age); 1506 swab2(&b->entry[j].state); 1507 swaboff(&b->entry[j].waddr); 1508 } 1509 } 1510 break; 1511 1512 case Tcache: 1513 h = (Cache*)p; 1514 swaboff(&h->maddr); 1515 swaboff(&h->msize); 1516 swaboff(&h->caddr); 1517 swaboff(&h->csize); 1518 swaboff(&h->fsize); 1519 swaboff(&h->wsize); 1520 swaboff(&h->wmax); 1521 swaboff(&h->sbaddr); 1522 swaboff(&h->cwraddr); 1523 swaboff(&h->roraddr); 1524 swab4(&h->toytime); 1525 swab4(&h->time); 1526 break; 1527 1528 case Tnone: // unitialized 1529 case Tfile: // someone elses problem 1530 case Tvirgo: // bit map -- all bytes 1531 case Tconfig: // configuration string -- all bytes 1532 break; 1533 } 1534 1535 /* swab the tag */ 1536 if(flag) { 1537 swab2(&t->pad); 1538 swab2(&t->tag); 1539 swaboff(&t->path); 1540 } 1541 } 1542