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 || tag == Tdir) 516 bp->flags |= Bimm; 517 putbuf(bp); 518 putbuf(p); 519 return a; 520 } 521 522 /* 523 * what are legal characters in a name? 524 * only disallow control characters. 525 * a) utf avoids control characters. 526 * b) '/' may not be the separator 527 */ 528 int 529 checkname(char *n) 530 { 531 int i, c; 532 533 for(i=0; i<NAMELEN; i++) { 534 c = *n & 0xff; 535 if(c == 0) { 536 if(i == 0) 537 return 1; 538 memset(n, 0, NAMELEN-i); 539 return 0; 540 } 541 if(c <= 040) 542 return 1; 543 n++; 544 } 545 return 1; /* too long */ 546 } 547 548 void 549 addfree(Device *dev, Off addr, Superb *sb) 550 { 551 int n; 552 Iobuf *p; 553 554 n = sb->fbuf.nfree; 555 if(n < 0 || n > FEPERBUF) 556 panic("addfree: bad freelist"); 557 if(n >= FEPERBUF) { 558 p = getbuf(dev, addr, Bmod|Bimm); 559 if(p == 0) 560 panic("addfree: getbuf"); 561 *(Fbuf*)p->iobuf = sb->fbuf; 562 settag(p, Tfree, QPNONE); 563 putbuf(p); 564 n = 0; 565 } 566 sb->fbuf.free[n++] = addr; 567 sb->fbuf.nfree = n; 568 sb->tfree++; 569 if(addr >= sb->fsize) 570 sb->fsize = addr+1; 571 } 572 573 /* 574 static int 575 Yfmt(Fmt* fmt) 576 { 577 Chan *cp; 578 char s[20]; 579 580 cp = va_arg(fmt->args, Chan*); 581 sprint(s, "C%d.%.3d", cp->type, cp->chan); 582 return fmtstrcpy(fmt, s); 583 } 584 */ 585 586 static int 587 Zfmt(Fmt* fmt) 588 { 589 Device *d; 590 int c, c1; 591 char s[100]; 592 593 d = va_arg(fmt->args, Device*); 594 if(d == nil) { 595 sprint(s, "Z***"); 596 goto out; 597 } 598 c = c1 = '\0'; 599 switch(d->type) { 600 default: 601 sprint(s, "D%d", d->type); 602 break; 603 case Devwren: 604 c = 'w'; 605 /* fallthrough */ 606 case Devworm: 607 if (c == '\0') 608 c = 'r'; 609 /* fallthrough */ 610 case Devlworm: 611 if (c == '\0') 612 c = 'l'; 613 if(d->wren.ctrl == 0 && d->wren.lun == 0) 614 sprint(s, "%c%d", c, d->wren.targ); 615 else 616 sprint(s, "%c%d.%d.%d", c, d->wren.ctrl, d->wren.targ, 617 d->wren.lun); 618 break; 619 case Devmcat: 620 c = '('; 621 c1 = ')'; 622 /* fallthrough */ 623 case Devmlev: 624 if (c == '\0') { 625 c = '['; 626 c1 = ']'; 627 } 628 /* fallthrough */ 629 case Devmirr: 630 if (c == '\0') { 631 c = '{'; 632 c1 = '}'; 633 } 634 if(d->cat.first == d->cat.last) 635 sprint(s, "%c%Z%c", c, d->cat.first, c1); 636 else if(d->cat.first->link == d->cat.last) 637 sprint(s, "%c%Z%Z%c", c, d->cat.first, d->cat.last, c1); 638 else 639 sprint(s, "%c%Z-%Z%c", c, d->cat.first, d->cat.last, c1); 640 break; 641 case Devro: 642 sprint(s, "o%Z%Z", d->ro.parent->cw.c, d->ro.parent->cw.w); 643 break; 644 case Devcw: 645 sprint(s, "c%Z%Z", d->cw.c, d->cw.w); 646 break; 647 case Devjuke: 648 sprint(s, "j%Z%Z", d->j.j, d->j.m); 649 break; 650 case Devfworm: 651 sprint(s, "f%Z", d->fw.fw); 652 break; 653 case Devpart: 654 sprint(s, "p(%Z)%ld.%ld", d->part.d, d->part.base, d->part.size); 655 break; 656 case Devswab: 657 sprint(s, "x%Z", d->swab.d); 658 break; 659 case Devnone: 660 sprint(s, "n"); 661 break; 662 } 663 out: 664 return fmtstrcpy(fmt, s); 665 } 666 667 static int 668 Gfmt(Fmt* fmt) 669 { 670 int t; 671 char *s; 672 673 t = va_arg(fmt->args, int); 674 s = "<badtag>"; 675 if(t >= 0 && t < MAXTAG) 676 s = tagnames[t]; 677 return fmtstrcpy(fmt, s); 678 } 679 680 void 681 formatinit(void) 682 { 683 quotefmtinstall(); 684 // fmtinstall('Y', Yfmt); /* print channels */ 685 fmtinstall('Z', Zfmt); /* print devices */ 686 fmtinstall('G', Gfmt); /* print tags */ 687 fmtinstall('T', Tfmt); /* print times */ 688 // fmtinstall('E', eipfmt); /* print ether addresses */ 689 fmtinstall('I', eipfmt); /* print ip addresses */ 690 } 691 692 void 693 rootream(Device *dev, Off addr) 694 { 695 Iobuf *p; 696 Dentry *d; 697 698 p = getbuf(dev, addr, Bmod|Bimm); 699 memset(p->iobuf, 0, RBUFSIZE); 700 settag(p, Tdir, QPROOT); 701 d = getdir(p, 0); 702 strcpy(d->name, "/"); 703 d->uid = -1; 704 d->gid = -1; 705 d->mode = DALLOC | DDIR | 706 ((DREAD|DEXEC) << 6) | 707 ((DREAD|DEXEC) << 3) | 708 ((DREAD|DEXEC) << 0); 709 d->qid = QID9P1(QPROOT|QPDIR,0); 710 d->atime = time(nil); 711 d->mtime = d->atime; 712 d->muid = 0; 713 putbuf(p); 714 } 715 716 void 717 superream(Device *dev, Off addr) 718 { 719 Iobuf *p; 720 Superb *s; 721 Off i; 722 723 p = getbuf(dev, addr, Bmod|Bimm); 724 memset(p->iobuf, 0, RBUFSIZE); 725 settag(p, Tsuper, QPSUPER); 726 727 s = (Superb*)p->iobuf; 728 s->fstart = 2; 729 s->fsize = devsize(dev); 730 s->fbuf.nfree = 1; 731 s->qidgen = 10; 732 for(i = s->fsize-1; i >= addr+2; i--) 733 addfree(dev, i, s); 734 putbuf(p); 735 } 736 737 struct 738 { 739 Lock; 740 Msgbuf *smsgbuf; 741 Msgbuf *lmsgbuf; 742 } msgalloc; 743 744 /* 745 * pre-allocate some message buffers at boot time. 746 * if this supply is exhausted, more will be allocated as needed. 747 */ 748 void 749 mbinit(void) 750 { 751 Msgbuf *mb; 752 Rabuf *rb; 753 int i; 754 755 lock(&msgalloc); 756 unlock(&msgalloc); 757 msgalloc.lmsgbuf = 0; 758 msgalloc.smsgbuf = 0; 759 for(i=0; i<conf.nlgmsg; i++) { 760 mb = malloc(sizeof(Msgbuf)); 761 mb->magic = Mbmagic; 762 mb->xdata = malloc(LARGEBUF+Slop); 763 mb->flags = LARGE; 764 mbfree(mb); 765 cons.nlarge++; 766 } 767 for(i=0; i<conf.nsmmsg; i++) { 768 mb = malloc(sizeof(Msgbuf)); 769 mb->magic = Mbmagic; 770 mb->xdata = malloc(SMALLBUF+Slop); 771 mb->flags = 0; 772 mbfree(mb); 773 cons.nsmall++; 774 } 775 memset(mballocs, 0, sizeof(mballocs)); 776 777 lock(&rabuflock); 778 unlock(&rabuflock); 779 rabuffree = 0; 780 for(i=0; i<1000; i++) { 781 rb = malloc(sizeof(*rb)); 782 rb->link = rabuffree; 783 rabuffree = rb; 784 } 785 } 786 787 Msgbuf* 788 mballoc(int count, Chan *cp, int category) 789 { 790 Msgbuf *mb; 791 792 lock(&msgalloc); 793 if(count > SMALLBUF) { 794 if(count > LARGEBUF) 795 panic("msgbuf count"); 796 mb = msgalloc.lmsgbuf; 797 if(mb == nil) { 798 mb = malloc(sizeof(Msgbuf)); 799 mb->xdata = malloc(LARGEBUF+Slop); 800 cons.nlarge++; 801 } else 802 msgalloc.lmsgbuf = mb->next; 803 mb->flags = LARGE; 804 } else { 805 mb = msgalloc.smsgbuf; 806 if(mb == nil) { 807 mb = malloc(sizeof(Msgbuf)); 808 mb->xdata = malloc(SMALLBUF+Slop); 809 cons.nsmall++; 810 } else 811 msgalloc.smsgbuf = mb->next; 812 mb->flags = 0; 813 } 814 mballocs[category]++; 815 unlock(&msgalloc); 816 mb->magic = Mbmagic; 817 mb->count = count; 818 mb->chan = cp; 819 mb->next = 0; 820 mb->param = 0; 821 mb->category = category; 822 mb->data = mb->xdata+Slop; 823 return mb; 824 } 825 826 void 827 mbfree(Msgbuf *mb) 828 { 829 if(mb == nil) 830 return; 831 assert(mb->magic == Mbmagic); 832 if (mb->magic != Mbmagic) 833 panic("mbfree: bad magic 0x%lux", mb->magic); 834 if(mb->flags & BTRACE) 835 print("mbfree: BTRACE cat=%d flags=%ux, caller %#p\n", 836 mb->category, mb->flags, getcallerpc(&mb)); 837 838 if(mb->flags & FREE) 839 panic("mbfree already free"); 840 841 lock(&msgalloc); 842 mballocs[mb->category]--; 843 mb->flags |= FREE; 844 if(mb->flags & LARGE) { 845 mb->next = msgalloc.lmsgbuf; 846 msgalloc.lmsgbuf = mb; 847 } else { 848 mb->next = msgalloc.smsgbuf; 849 msgalloc.smsgbuf = mb; 850 } 851 mb->data = 0; 852 mb->magic = 0; 853 unlock(&msgalloc); 854 } 855 856 /* 857 * returns 1 if n is prime 858 * used for adjusting lengths 859 * of hashing things. 860 * there is no need to be clever 861 */ 862 int 863 prime(vlong n) 864 { 865 long i; 866 867 if((n%2) == 0) 868 return 0; 869 for(i=3;; i+=2) { 870 if((n%i) == 0) 871 return 0; 872 if((vlong)i*i >= n) 873 return 1; 874 } 875 } 876 877 char* 878 getwrd(char *word, char *line) 879 { 880 int c, n; 881 882 while(isascii(*line) && isspace(*line) && *line != '\n') 883 line++; 884 for(n = 0; n < Maxword; n++) { 885 c = *line; 886 if(c == '\0' || isascii(c) && isspace(c)) 887 break; 888 line++; 889 *word++ = c; 890 } 891 *word = 0; 892 return line; 893 } 894 895 void 896 hexdump(void *a, int n) 897 { 898 char s1[30], s2[4]; 899 uchar *p; 900 int i; 901 902 p = a; 903 s1[0] = 0; 904 for(i = 0; i < n; i++) { 905 sprint(s2, " %.2ux", p[i]); 906 strcat(s1, s2); 907 if((i&7) == 7) { 908 print("%s\n", s1); 909 s1[0] = 0; 910 } 911 } 912 if(s1[0]) 913 print("%s\n", s1); 914 } 915 916 void* 917 fs_recv(Queue *q, int) 918 { 919 void *a; 920 int i, c; 921 922 if(q == nil) 923 panic("recv null q"); 924 qlock(q); 925 q->waitedfor = 1; 926 while((c = q->count) <= 0) 927 rsleep(&q->empty); 928 i = q->loc; 929 a = q->args[i]; 930 i++; 931 if(i >= q->size) 932 i = 0; 933 q->loc = i; 934 q->count = c-1; 935 rwakeup(&q->full); /* no longer full */ 936 qunlock(q); 937 return a; 938 } 939 940 void 941 fs_send(Queue *q, void *a) 942 { 943 int i, c; 944 945 if(q == nil) 946 panic("send null q"); 947 if(!q->waitedfor) { 948 for (i = 0; i < 5 && !q->waitedfor; i++) 949 sleep(1000); 950 if(!q->waitedfor) { 951 /* likely a bug; don't wait forever */ 952 print("no readers yet for %s q\n", q->name); 953 abort(); 954 } 955 } 956 qlock(q); 957 while((c = q->count) >= q->size) 958 rsleep(&q->full); 959 i = q->loc + c; 960 if(i >= q->size) 961 i -= q->size; 962 q->args[i] = a; 963 q->count = c+1; 964 rwakeup(&q->empty); /* no longer empty */ 965 qunlock(q); 966 } 967 968 Queue* 969 newqueue(int size, char *name) 970 { 971 Queue *q; 972 973 q = malloc(sizeof(Queue) + (size-1)*sizeof(void*)); 974 q->size = size; 975 q->full.l = q->empty.l = &q->QLock; 976 q->name = name; 977 return q; 978 } 979 980 int 981 devread(Device *d, Off b, void *c) 982 { 983 int e; 984 985 for (;;) 986 switch(d->type) { 987 case Devcw: 988 return cwread(d, b, c); 989 990 case Devjuke: 991 d = d->j.m; 992 break; 993 994 case Devro: 995 return roread(d, b, c); 996 997 case Devwren: 998 return wrenread(d, b, c); 999 1000 case Devworm: 1001 case Devlworm: 1002 return wormread(d, b, c); 1003 1004 case Devfworm: 1005 return fwormread(d, b, c); 1006 1007 case Devmcat: 1008 return mcatread(d, b, c); 1009 1010 case Devmlev: 1011 return mlevread(d, b, c); 1012 1013 case Devmirr: 1014 return mirrread(d, b, c); 1015 1016 case Devpart: 1017 return partread(d, b, c); 1018 1019 case Devswab: 1020 e = devread(d->swab.d, b, c); 1021 if(e == 0) 1022 swab(c, 0); 1023 return e; 1024 1025 case Devnone: 1026 print("read from device none(%lld)\n", (Wideoff)b); 1027 return 1; 1028 default: 1029 panic("illegal device in devread: %Z %lld", 1030 d, (Wideoff)b); 1031 return 1; 1032 } 1033 } 1034 1035 int 1036 devwrite(Device *d, Off b, void *c) 1037 { 1038 int e; 1039 1040 /* 1041 * set readonly to non-0 to prevent all writes; 1042 * mainly for trying dangerous experiments. 1043 */ 1044 if (readonly) 1045 return 0; 1046 for (;;) 1047 switch(d->type) { 1048 case Devcw: 1049 return cwwrite(d, b, c); 1050 1051 case Devjuke: 1052 d = d->j.m; 1053 break; 1054 1055 case Devro: 1056 print("write to ro device %Z(%lld)\n", d, (Wideoff)b); 1057 return 1; 1058 1059 case Devwren: 1060 return wrenwrite(d, b, c); 1061 1062 case Devworm: 1063 case Devlworm: 1064 return wormwrite(d, b, c); 1065 1066 case Devfworm: 1067 return fwormwrite(d, b, c); 1068 1069 case Devmcat: 1070 return mcatwrite(d, b, c); 1071 1072 case Devmlev: 1073 return mlevwrite(d, b, c); 1074 1075 case Devmirr: 1076 return mirrwrite(d, b, c); 1077 1078 case Devpart: 1079 return partwrite(d, b, c); 1080 1081 case Devswab: 1082 swab(c, 1); 1083 e = devwrite(d->swab.d, b, c); 1084 swab(c, 0); 1085 return e; 1086 1087 case Devnone: 1088 /* checktag() can generate blocks with type devnone */ 1089 return 0; 1090 default: 1091 panic("illegal device in devwrite: %Z %lld", 1092 d, (Wideoff)b); 1093 return 1; 1094 } 1095 } 1096 1097 Devsize 1098 devsize(Device *d) 1099 { 1100 for (;;) 1101 switch(d->type) { 1102 case Devcw: 1103 case Devro: 1104 return cwsize(d); 1105 1106 case Devjuke: 1107 d = d->j.m; 1108 break; 1109 1110 case Devwren: 1111 return wrensize(d); 1112 1113 case Devworm: 1114 case Devlworm: 1115 return wormsize(d); 1116 1117 case Devfworm: 1118 return fwormsize(d); 1119 1120 case Devmcat: 1121 return mcatsize(d); 1122 1123 case Devmlev: 1124 return mlevsize(d); 1125 1126 case Devmirr: 1127 return mirrsize(d); 1128 1129 case Devpart: 1130 return partsize(d); 1131 1132 case Devswab: 1133 d = d->swab.d; 1134 break; 1135 default: 1136 panic("illegal device in devsize: %Z", d); 1137 return 0; 1138 } 1139 } 1140 1141 /* result is malloced */ 1142 char * 1143 sdof(Device *d) 1144 { 1145 static char name[256]; 1146 1147 for (;;) 1148 switch(d->type) { 1149 case Devjuke: 1150 d = d->j.j; /* robotics */ 1151 break; 1152 case Devwren: 1153 snprint(name, sizeof name, "/dev/sd%d%d", d->wren.ctrl, 1154 d->wren.targ); 1155 return strdup(name); 1156 case Devswab: 1157 d = d->swab.d; 1158 break; 1159 default: 1160 panic("illegal device in sdof: %Z", d); 1161 return nil; 1162 } 1163 } 1164 1165 Off 1166 superaddr(Device *d) 1167 { 1168 for (;;) 1169 switch(d->type) { 1170 default: 1171 return SUPER_ADDR; 1172 case Devcw: 1173 case Devro: 1174 return cwsaddr(d); 1175 case Devswab: 1176 d = d->swab.d; 1177 break; 1178 } 1179 } 1180 1181 Off 1182 getraddr(Device *d) 1183 { 1184 for (;;) 1185 switch(d->type) { 1186 default: 1187 return ROOT_ADDR; 1188 case Devcw: 1189 case Devro: 1190 return cwraddr(d); 1191 case Devswab: 1192 d = d->swab.d; 1193 break; 1194 } 1195 } 1196 1197 void 1198 devream(Device *d, int top) 1199 { 1200 Device *l; 1201 1202 loop: 1203 print("\tdevream: %Z %d\n", d, top); 1204 switch(d->type) { 1205 default: 1206 print("ream: unknown dev type %Z\n", d); 1207 return; 1208 1209 case Devcw: 1210 devream(d->cw.w, 0); 1211 devream(d->cw.c, 0); 1212 if(top) { 1213 wlock(&mainlock); 1214 cwream(d); 1215 wunlock(&mainlock); 1216 } 1217 devinit(d); 1218 return; 1219 1220 case Devfworm: 1221 devream(d->fw.fw, 0); 1222 fwormream(d); 1223 break; 1224 1225 case Devpart: 1226 devream(d->part.d, 0); 1227 break; 1228 1229 case Devmlev: 1230 case Devmcat: 1231 case Devmirr: 1232 for(l=d->cat.first; l; l=l->link) 1233 devream(l, 0); 1234 break; 1235 1236 case Devjuke: 1237 case Devworm: 1238 case Devlworm: 1239 case Devwren: 1240 break; 1241 1242 case Devswab: 1243 d = d->swab.d; 1244 goto loop; 1245 } 1246 devinit(d); 1247 if(top) { 1248 wlock(&mainlock); 1249 rootream(d, ROOT_ADDR); 1250 superream(d, SUPER_ADDR); 1251 wunlock(&mainlock); 1252 } 1253 } 1254 1255 void 1256 devrecover(Device *d) 1257 { 1258 for (;;) { 1259 print("recover: %Z\n", d); 1260 switch(d->type) { 1261 default: 1262 print("recover: unknown dev type %Z\n", d); 1263 return; 1264 1265 case Devcw: 1266 wlock(&mainlock); /* recover */ 1267 cwrecover(d); 1268 wunlock(&mainlock); 1269 return; 1270 1271 case Devswab: 1272 d = d->swab.d; 1273 break; 1274 } 1275 } 1276 } 1277 1278 void 1279 devinit(Device *d) 1280 { 1281 for (;;) { 1282 if(d->init) 1283 return; 1284 d->init = 1; 1285 print("\tdevinit %Z\n", d); 1286 switch(d->type) { 1287 default: 1288 print("devinit unknown device %Z\n", d); 1289 return; 1290 1291 case Devro: 1292 cwinit(d->ro.parent); 1293 return; 1294 1295 case Devcw: 1296 cwinit(d); 1297 return; 1298 1299 case Devjuke: 1300 jukeinit(d); 1301 return; 1302 1303 case Devwren: 1304 wreninit(d); 1305 return; 1306 1307 case Devworm: 1308 case Devlworm: 1309 return; 1310 1311 case Devfworm: 1312 fworminit(d); 1313 return; 1314 1315 case Devmcat: 1316 mcatinit(d); 1317 return; 1318 1319 case Devmlev: 1320 mlevinit(d); 1321 return; 1322 1323 case Devmirr: 1324 mirrinit(d); 1325 return; 1326 1327 case Devpart: 1328 partinit(d); 1329 return; 1330 1331 case Devswab: 1332 d = d->swab.d; 1333 break; 1334 1335 case Devnone: 1336 print("devinit of Devnone\n"); 1337 return; 1338 } 1339 } 1340 } 1341 1342 void 1343 swab2(void *c) 1344 { 1345 uchar *p; 1346 int t; 1347 1348 p = c; 1349 1350 t = p[0]; 1351 p[0] = p[1]; 1352 p[1] = t; 1353 } 1354 1355 void 1356 swab4(void *c) 1357 { 1358 uchar *p; 1359 int t; 1360 1361 p = c; 1362 1363 t = p[0]; 1364 p[0] = p[3]; 1365 p[3] = t; 1366 1367 t = p[1]; 1368 p[1] = p[2]; 1369 p[2] = t; 1370 } 1371 1372 void 1373 swab8(void *c) 1374 { 1375 uchar *p; 1376 int t; 1377 1378 p = c; 1379 1380 t = p[0]; 1381 p[0] = p[7]; 1382 p[7] = t; 1383 1384 t = p[1]; 1385 p[1] = p[6]; 1386 p[6] = t; 1387 1388 t = p[2]; 1389 p[2] = p[5]; 1390 p[5] = t; 1391 1392 t = p[3]; 1393 p[3] = p[4]; 1394 p[4] = t; 1395 } 1396 1397 /* 1398 * swab a block 1399 * flag = 0 -- convert from foreign to native 1400 * flag = 1 -- convert from native to foreign 1401 */ 1402 void 1403 swab(void *c, int flag) 1404 { 1405 uchar *p; 1406 Tag *t; 1407 int i, j; 1408 Dentry *d; 1409 Cache *h; 1410 Bucket *b; 1411 Superb *s; 1412 Fbuf *f; 1413 Off *l; 1414 1415 /* swab the tag */ 1416 p = (uchar*)c; 1417 t = (Tag*)(p + BUFSIZE); 1418 if(!flag) { 1419 swab2(&t->pad); 1420 swab2(&t->tag); 1421 swaboff(&t->path); 1422 } 1423 1424 /* swab each block type */ 1425 switch(t->tag) { 1426 1427 default: 1428 print("no swab for tag=%G rw=%d\n", t->tag, flag); 1429 for(j=0; j<16; j++) 1430 print(" %.2x", p[BUFSIZE+j]); 1431 print("\n"); 1432 for(i=0; i<16; i++) { 1433 print("%.4x", i*16); 1434 for(j=0; j<16; j++) 1435 print(" %.2x", p[i*16+j]); 1436 print("\n"); 1437 } 1438 panic("swab"); 1439 break; 1440 1441 case Tsuper: 1442 s = (Superb*)p; 1443 swaboff(&s->fbuf.nfree); 1444 for(i=0; i<FEPERBUF; i++) 1445 swaboff(&s->fbuf.free[i]); 1446 swaboff(&s->fstart); 1447 swaboff(&s->fsize); 1448 swaboff(&s->tfree); 1449 swaboff(&s->qidgen); 1450 swaboff(&s->cwraddr); 1451 swaboff(&s->roraddr); 1452 swaboff(&s->last); 1453 swaboff(&s->next); 1454 break; 1455 1456 case Tdir: 1457 for(i=0; i<DIRPERBUF; i++) { 1458 d = (Dentry*)p + i; 1459 swab2(&d->uid); 1460 swab2(&d->gid); 1461 swab2(&d->mode); 1462 swab2(&d->muid); 1463 swaboff(&d->qid.path); 1464 swab4(&d->qid.version); 1465 swaboff(&d->size); 1466 for(j=0; j<NDBLOCK; j++) 1467 swaboff(&d->dblock[j]); 1468 for (j = 0; j < NIBLOCK; j++) 1469 swaboff(&d->iblocks[j]); 1470 swab4(&d->atime); 1471 swab4(&d->mtime); 1472 } 1473 break; 1474 1475 case Tind1: 1476 case Tind2: 1477 #ifndef COMPAT32 1478 case Tind3: 1479 case Tind4: 1480 /* add more Tind tags here ... */ 1481 #endif 1482 l = (Off *)p; 1483 for(i=0; i<INDPERBUF; i++) { 1484 swaboff(l); 1485 l++; 1486 } 1487 break; 1488 1489 case Tfree: 1490 f = (Fbuf*)p; 1491 swaboff(&f->nfree); 1492 for(i=0; i<FEPERBUF; i++) 1493 swaboff(&f->free[i]); 1494 break; 1495 1496 case Tbuck: 1497 for(i=0; i<BKPERBLK; i++) { 1498 b = (Bucket*)p + i; 1499 swab4(&b->agegen); 1500 for(j=0; j<CEPERBK; j++) { 1501 swab2(&b->entry[j].age); 1502 swab2(&b->entry[j].state); 1503 swaboff(&b->entry[j].waddr); 1504 } 1505 } 1506 break; 1507 1508 case Tcache: 1509 h = (Cache*)p; 1510 swaboff(&h->maddr); 1511 swaboff(&h->msize); 1512 swaboff(&h->caddr); 1513 swaboff(&h->csize); 1514 swaboff(&h->fsize); 1515 swaboff(&h->wsize); 1516 swaboff(&h->wmax); 1517 swaboff(&h->sbaddr); 1518 swaboff(&h->cwraddr); 1519 swaboff(&h->roraddr); 1520 swab4(&h->toytime); 1521 swab4(&h->time); 1522 break; 1523 1524 case Tnone: // unitialized 1525 case Tfile: // someone elses problem 1526 case Tvirgo: // bit map -- all bytes 1527 case Tconfig: // configuration string -- all bytes 1528 break; 1529 } 1530 1531 /* swab the tag */ 1532 if(flag) { 1533 swab2(&t->pad); 1534 swab2(&t->tag); 1535 swaboff(&t->path); 1536 } 1537 } 1538