Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}