Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"all.h"
2
 
3
Lock wpathlock;
4
 
5
struct {
6
	Lock	flock;
7
	File*	ffree;		/* free file structures */
8
	Wpath*	wfree;
9
} suballoc;
10
 
11
enum{
12
	Finc=	128,	/* allocation chunksize for files */
13
	Fmax=	10000,	/* maximum file structures to be allocated */
14
 
15
	Winc=	8*128,	/* allocation chunksize for wpath */
16
	Wmax=	8*10000,	/* maximum wpath structures to be allocated */
17
};
18
 
19
 
20
Filsys*
21
fsstr(char *p)
22
{
23
	Filsys *fs;
24
 
25
	for(fs=filesys; fs->name; fs++)
26
		if(strcmp(fs->name, p) == 0)
27
			return fs;
28
	return 0;
29
}
30
 
31
void
32
fileinit(Chan *cp)
33
{
34
	File *f;
35
	Tlock *t;
36
 
37
loop:
38
	lock(&cp->flock);
39
	f = cp->flist;
40
	if(!f) {
41
		unlock(&cp->flock);
42
		return;
43
	}
44
	cp->flist = f->next;
45
	unlock(&cp->flock);
46
 
47
	qlock(f);
48
	if(t = f->tlock) {
49
		t->time = 0;
50
		f->tlock = 0;
51
	}
52
	if(f->open & FREMOV)
53
		doremove(f, 0);
54
	freewp(f->wpath);
55
	f->open = 0;
56
	f->cp = 0;
57
	qunlock(f);
58
 
59
	goto loop;
60
}
61
 
62
/*
63
 * returns a locked file structure
64
 */
65
File*
66
filep(Chan *cp, int fid, int flag)
67
{
68
	File *f, *prev;
69
 
70
	if(fid == NOF)
71
		return 0;
72
 
73
loop:
74
	lock(&cp->flock);
75
	for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
76
		if(f->fid != fid)
77
			continue;
78
		if(prev) {
79
			prev->next = f->next;
80
			f->next = cp->flist;
81
			cp->flist = f;
82
		}
83
		goto out;
84
	}
85
	if(flag) {
86
		f = newfp(cp);
87
		if(f) {
88
			f->fid = fid;
89
			goto out;
90
		}
91
	}
92
else print("cannot find %p.%d (list=%p)\n", cp, fid, cp->flist);
93
	unlock(&cp->flock);
94
	return 0;
95
 
96
out:
97
	unlock(&cp->flock);
98
	qlock(f);
99
	if(f->fid != fid) {
100
		qunlock(f);
101
		goto loop;
102
	}
103
	return f;
104
}
105
 
106
void
107
sublockinit(void)
108
{
109
	lock(&suballoc.flock);
110
	lock(&wpathlock);
111
	conf.nfile = 0;
112
	conf.nwpath = 0;
113
	unlock(&suballoc.flock);
114
	unlock(&wpathlock);
115
}	
116
 
117
/*
118
 * always called with cp->flock locked
119
 */
120
File*
121
newfp(Chan *cp)
122
{
123
	File *f, *e;
124
 
125
retry:
126
	lock(&suballoc.flock);
127
	f = suballoc.ffree;
128
	if(f != nil){
129
		suballoc.ffree = f->list;
130
		unlock(&suballoc.flock);
131
		f->list = 0;
132
		f->cp = cp;
133
		f->next = cp->flist;
134
		f->wpath = 0;
135
		f->tlock = 0;
136
		f->dslot = 0;
137
		f->doffset = 0;
138
		f->uid = 0;
139
		f->cuid = 0;
140
		cp->flist = f;
141
		return f;
142
	}
143
	unlock(&suballoc.flock);
144
 
145
	if(conf.nfile > Fmax){
146
		print("%d: out of files\n", cp->chan);
147
		return 0;
148
	}
149
 
150
	/*
151
	 *  create a few new files
152
	 */
153
	f = malloc(Finc*sizeof(*f));
154
	memset(f, 0, Finc*sizeof(*f));
155
	lock(&suballoc.flock);
156
	for(e = f+Finc; f < e; f++){
157
		qlock(f);
158
		qunlock(f);
159
		f->list = suballoc.ffree;
160
		suballoc.ffree = f;
161
	}
162
	conf.nfile += Finc;
163
	unlock(&suballoc.flock);
164
	goto retry;
165
}
166
 
167
void
168
freefp(File *fp)
169
{
170
	Chan *cp;
171
	File *f, *prev;
172
 
173
	if(!fp || !(cp = fp->cp))
174
		return;
175
	authfree(fp);
176
	lock(&cp->flock);
177
	for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
178
		if(f != fp)
179
			continue;
180
		if(prev)
181
			prev->next = f->next;
182
		else
183
			cp->flist = f->next;
184
		f->cp = 0;
185
		lock(&suballoc.flock);
186
		f->list = suballoc.ffree;
187
		suballoc.ffree = f;
188
		unlock(&suballoc.flock);
189
		break;
190
	}
191
	unlock(&cp->flock);
192
}
193
 
194
Wpath*
195
newwp(void)
196
{
197
	Wpath *w, *e;
198
 
199
retry:
200
	lock(&wpathlock);
201
	w = suballoc.wfree;
202
	if(w != nil){
203
		suballoc.wfree = w->list;
204
		unlock(&wpathlock);
205
		memset(w, 0, sizeof(*w));
206
		w->refs = 1;
207
		w->up = 0;
208
		return w;
209
	}
210
	unlock(&wpathlock);
211
 
212
	if(conf.nwpath > Wmax){
213
		print("out of wpaths\n");
214
		return 0;
215
	}
216
 
217
	/*
218
	 *  create a few new wpaths
219
	 */
220
	w = malloc(Winc*sizeof(*w));
221
	memset(w, 0, Winc*sizeof(*w));
222
	lock(&wpathlock);
223
	for(e = w+Winc; w < e; w++){
224
		w->list = suballoc.wfree;
225
		suballoc.wfree = w;
226
	}
227
	conf.nwpath += Winc;
228
	unlock(&wpathlock);
229
	goto retry;
230
}
231
 
232
/*
233
 *  increment the references for the whole path
234
 */
235
Wpath*
236
getwp(Wpath *w)
237
{
238
	Wpath *nw;
239
 
240
	lock(&wpathlock);
241
	for(nw = w; nw; nw=nw->up)
242
		nw->refs++;
243
	unlock(&wpathlock);
244
	return w;
245
}
246
 
247
/*
248
 *  decrement the reference for each element of the path
249
 */
250
void
251
freewp(Wpath *w)
252
{
253
	lock(&wpathlock);
254
	for(; w; w=w->up){
255
		w->refs--;
256
		if(w->refs == 0){
257
			w->list = suballoc.wfree;
258
			suballoc.wfree = w;
259
		}
260
	}
261
	unlock(&wpathlock);
262
}
263
 
264
/*
265
 *  decrement the reference for just this element
266
 */
267
void
268
putwp(Wpath *w)
269
{
270
	lock(&wpathlock);
271
	w->refs--;
272
	if(w->refs == 0){
273
		w->list = suballoc.wfree;
274
		suballoc.wfree = w;
275
	}
276
	unlock(&wpathlock);
277
}
278
 
279
int
280
iaccess(File *f, Dentry *d, int m)
281
{
282
	if(wstatallow)
283
		return 0;
284
 
285
	/*
286
	 * owner is next
287
	 */
288
	if(f->uid == d->uid)
289
		if((m<<6) & d->mode)
290
			return 0;
291
	/*
292
	 * group membership is hard
293
	 */
294
	if(ingroup(f->uid, d->gid))
295
		if((m<<3) & d->mode)
296
			return 0;
297
	/*
298
	 * other access for everyone except members of group 9999
299
	 */
300
	if(m & d->mode){
301
		/* 
302
		 *  walk directories regardless.
303
		 *  otherwise its impossible to get
304
		 *  from the root to noworld's directories.
305
		 */
306
		if((d->mode & DDIR) && (m == DEXEC))
307
			return 0;
308
		if(!ingroup(f->uid, 9999))
309
			return 0;
310
	}
311
	return 1;
312
}
313
 
314
Tlock*
315
tlocked(Iobuf *p, Dentry *d)
316
{
317
	Tlock *t, *t1;
318
	long qpath, tim;
319
	Device dev;
320
 
321
	tim = time(0);
322
	qpath = d->qid.path;
323
	dev = p->dev;
324
	t1 = 0;
325
	for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
326
		if(t->qpath == qpath)
327
		if(t->time >= tim)
328
		if(devcmp(t->dev, dev) == 0)
329
			return 0;		/* its locked */
330
		if(!t1 && t->time < tim)
331
			t1 = t;			/* steal first lock */
332
	}
333
	if(t1) {
334
		t1->dev = dev;
335
		t1->qpath = qpath;
336
		t1->time = tim + TLOCK;
337
	}
338
	/* botch
339
	 * out of tlock nodes simulates
340
	 * a locked file
341
	 */
342
	return t1;
343
}
344
 
345
Qid
346
newqid(Device dev)
347
{
348
	Iobuf *p;
349
	Superb *sb;
350
	Qid qid;
351
 
352
	p = getbuf(dev, superaddr(dev), Bread|Bmod);
353
	if(!p || checktag(p, Tsuper, QPSUPER))
354
		panic("newqid: super block");
355
	sb = (Superb*)p->iobuf;
356
	sb->qidgen++;
357
	qid.path = sb->qidgen;
358
	qid.vers = 0;
359
	qid.type = 0;
360
	putbuf(p);
361
	return qid;
362
}
363
 
364
/*
365
 * what are legal characters in a name?
366
 * only disallow control characters.
367
 * a) utf avoids control characters.
368
 * b) '/' may not be the separator
369
 */
370
int
371
checkname(char *n)
372
{
373
	int i, c;
374
 
375
	for(i=0; i<NAMELEN; i++) {
376
		c = *n & 0xff;
377
		if(c == 0) {
378
			if(i == 0)
379
				return 1;
380
			memset(n, 0, NAMELEN-i);
381
			return 0;
382
		}
383
		if(c <= 040)
384
			return 1;
385
		n++;
386
	}
387
	return 1;	/* too long */
388
}
389
 
390
void
391
bfree(Device dev, long addr, int d)
392
{
393
	Iobuf *p;
394
	long a;
395
	int i;
396
 
397
	if(!addr)
398
		return;
399
	if(d > 0) {
400
		d--;
401
		p = getbuf(dev, addr, Bread);
402
		if(p) {
403
			for(i=INDPERBUF-1; i>=0; i--) {
404
				a = ((long*)p->iobuf)[i];
405
				bfree(dev, a, d);
406
			}
407
			putbuf(p);
408
		}
409
	}
410
	/*
411
	 * stop outstanding i/o
412
	 */
413
	p = getbuf(dev, addr, Bprobe);
414
	if(p) {
415
		p->flags &= ~(Bmod|Bimm);
416
		putbuf(p);
417
	}
418
	/*
419
	 * dont put written worm
420
	 * blocks into free list
421
	 */
422
	if(nofree(dev, addr))
423
		return;
424
	p = getbuf(dev, superaddr(dev), Bread|Bmod);
425
	if(!p || checktag(p, Tsuper, QPSUPER))
426
		panic("bfree: super block");
427
	addfree(dev, addr, (Superb*)p->iobuf);
428
	putbuf(p);
429
}
430
 
431
long
432
balloc(Device dev, int tag, long qid)
433
{
434
	Iobuf *bp, *p;
435
	Superb *sb;
436
	long a;
437
	int n;
438
 
439
	p = getbuf(dev, superaddr(dev), Bread|Bmod);
440
	if(!p || checktag(p, Tsuper, QPSUPER))
441
		panic("balloc: super block");
442
	sb = (Superb*)p->iobuf;
443
 
444
loop:
445
	n = --sb->fbuf.nfree;
446
	sb->tfree--;
447
	if(n < 0 || n >= FEPERBUF)
448
		panic("balloc: bad freelist");
449
	a = sb->fbuf.free[n];
450
	if(n <= 0) {
451
		if(a == 0) {
452
			sb->tfree = 0;
453
			sb->fbuf.nfree = 1;
454
			if(devgrow(dev, sb))
455
				goto loop;
456
			putbuf(p);
457
			return 0;
458
		}
459
		bp = getbuf(dev, a, Bread);
460
		if(!bp || checktag(bp, Tfree, QPNONE)) {
461
			if(bp)
462
				putbuf(bp);
463
			putbuf(p);
464
			return 0;
465
		}
466
		memmove(&sb->fbuf, bp->iobuf, (FEPERBUF+1)*sizeof(long));
467
		putbuf(bp);
468
	}
469
	bp = getbuf(dev, a, Bmod);
470
	memset(bp->iobuf, 0, RBUFSIZE);
471
	settag(bp, tag, qid);
472
	if(tag == Tind1 || tag == Tind2 || tag == Tdir)
473
		bp->flags |= Bimm;
474
	putbuf(bp);
475
	putbuf(p);
476
	return a;
477
}
478
 
479
void
480
addfree(Device dev, long addr, Superb *sb)
481
{
482
	int n;
483
	Iobuf *p;
484
 
485
	if(addr >= sb->fsize){
486
		print("addfree: bad addr %lux\n", addr);
487
		return;
488
	}
489
	n = sb->fbuf.nfree;
490
	if(n < 0 || n > FEPERBUF)
491
		panic("addfree: bad freelist");
492
	if(n >= FEPERBUF) {
493
		p = getbuf(dev, addr, Bmod);
494
		if(p == 0)
495
			panic("addfree: getbuf");
496
		memmove(p->iobuf, &sb->fbuf, (FEPERBUF+1)*sizeof(long));
497
		settag(p, Tfree, QPNONE);
498
		putbuf(p);
499
		n = 0;
500
	}
501
	sb->fbuf.free[n++] = addr;
502
	sb->fbuf.nfree = n;
503
	sb->tfree++;
504
	if(addr >= sb->fsize)
505
		sb->fsize = addr+1;
506
}
507
 
508
int
509
Cfmt(Fmt *f1)
510
{
511
	Chan *cp;
512
 
513
	cp = va_arg(f1->args, Chan*);
514
	return fmtprint(f1, "C%d.%.3d", cp->type, cp->chan);
515
}
516
 
517
int
518
Dfmt(Fmt *f1)
519
{
520
	Device d;
521
 
522
	d = va_arg(f1->args, Device);
523
	return fmtprint(f1, "D%d.%d.%d.%d", d.type, d.ctrl, d.unit, d.part);
524
}
525
 
526
int
527
Afmt(Fmt *f1)
528
{
529
	Filta a;
530
 
531
	a = va_arg(f1->args, Filta);
532
	return fmtprint(f1, "%6lud %6lud %6lud",
533
		fdf(a.f->filter[0], a.scale*60),
534
		fdf(a.f->filter[1], a.scale*600),
535
		fdf(a.f->filter[2], a.scale*6000));
536
}
537
 
538
int
539
Gfmt(Fmt *f1)
540
{
541
	int t;
542
 
543
	t = va_arg(f1->args, int);
544
	if(t >= 0 && t < MAXTAG)
545
		return fmtstrcpy(f1, tagnames[t]);
546
	else
547
		return fmtprint(f1, "<badtag %d>", t);
548
}
549
 
550
void
551
formatinit(void)
552
{
553
 
554
	fmtinstall('C', Cfmt);	/* print channels */
555
	fmtinstall('D', Dfmt);	/* print devices */
556
	fmtinstall('A', Afmt);	/* print filters */
557
	fmtinstall('G', Gfmt);	/* print tags */
558
	fmtinstall('T', Tfmt);	/* print times */
559
	fmtinstall('O', ofcallfmt);	/* print old fcalls */
560
}
561
int
562
devcmp(Device d1, Device d2)
563
{
564
 
565
	if(d1.type == d2.type)
566
	if(d1.ctrl == d2.ctrl)
567
	if(d1.unit == d2.unit)
568
	if(d1.part == d2.part)
569
		return 0;
570
	return 1;
571
}
572
 
573
void
574
rootream(Device dev, long addr)
575
{
576
	Iobuf *p;
577
	Dentry *d;
578
 
579
	p = getbuf(dev, addr, Bmod|Bimm);
580
	memset(p->iobuf, 0, RBUFSIZE);
581
	settag(p, Tdir, QPROOT);
582
	d = getdir(p, 0);
583
	strcpy(d->name, "/");
584
	d->uid = -1;
585
	d->gid = -1;
586
	d->mode = DALLOC | DDIR |
587
		((DREAD|DWRITE|DEXEC) << 6) |
588
		((DREAD|DWRITE|DEXEC) << 3) |
589
		((DREAD|DWRITE|DEXEC) << 0);
590
	d->qid = QID9P1(QPROOT|QPDIR,0);
591
	d->atime = time(0);
592
	d->mtime = d->atime;
593
	putbuf(p);
594
}
595
 
596
int
597
superok(Device dev, long addr, int set)
598
{
599
	Iobuf *p;
600
	Superb *s;
601
	int ok;
602
 
603
	p = getbuf(dev, addr, Bread|Bmod|Bimm);
604
	s = (Superb*)p->iobuf;
605
	ok = s->fsok;
606
	s->fsok = set;
607
	putbuf(p);
608
	return ok;
609
}
610
 
611
void
612
superream(Device dev, long addr)
613
{
614
	Iobuf *p;
615
	Superb *s;
616
	long i;
617
 
618
	p = getbuf(dev, addr, Bmod|Bimm);
619
	memset(p->iobuf, 0, RBUFSIZE);
620
	settag(p, Tsuper, QPSUPER);
621
 
622
	s = (Superb*)p->iobuf;
623
	s->fstart = 1;
624
	s->fsize = devsize(dev);
625
	s->fbuf.nfree = 1;
626
	s->qidgen = 10;
627
	for(i=s->fsize-1; i>=addr+2; i--)
628
		addfree(dev, i, s);
629
	putbuf(p);
630
}
631
 
632
/*
633
 * returns 1 if n is prime
634
 * used for adjusting lengths
635
 * of hashing things.
636
 * there is no need to be clever
637
 */
638
int
639
prime(long n)
640
{
641
	long i;
642
 
643
	if((n%2) == 0)
644
		return 0;
645
	for(i=3;; i+=2) {
646
		if((n%i) == 0)
647
			return 0;
648
		if(i*i >= n)
649
			return 1;
650
	}
651
}
652
 
653
void
654
hexdump(void *a, int n)
655
{
656
	char s1[30], s2[4];
657
	uchar *p;
658
	int i;
659
 
660
	p = a;
661
	s1[0] = 0;
662
	for(i=0; i<n; i++) {
663
		sprint(s2, " %.2ux", p[i]);
664
		strcat(s1, s2);
665
		if((i&7) == 7) {
666
			print("%s\n", s1);
667
			s1[0] = 0;
668
		}
669
	}
670
	if(s1[0])
671
		print("%s\n", s1);
672
}
673
 
674
long
675
qidpathgen(Device *dev)
676
{
677
	Iobuf *p;
678
	Superb *sb;
679
	long path;
680
 
681
	p = getbuf(*dev, superaddr((*dev)), Bread|Bmod);
682
	if(!p || checktag(p, Tsuper, QPSUPER))
683
		panic("newqid: super block");
684
	sb = (Superb*)p->iobuf;
685
	sb->qidgen++;
686
	path = sb->qidgen;
687
	putbuf(p);
688
	return path;
689
}
690