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