xref: /plan9-contrib/sys/src/cmd/ext2srv/xfile.c (revision dc5a79c1208f0704eeb474acc990728f8b4854f5)
1*dc5a79c1SDavid du Colombier #include <u.h>
2*dc5a79c1SDavid du Colombier #include <libc.h>
3*dc5a79c1SDavid du Colombier #include <fcall.h>
4*dc5a79c1SDavid du Colombier #include <thread.h>
5*dc5a79c1SDavid du Colombier #include <9p.h>
6*dc5a79c1SDavid du Colombier #include "dat.h"
7*dc5a79c1SDavid du Colombier #include "fns.h"
8*dc5a79c1SDavid du Colombier 
9*dc5a79c1SDavid du Colombier 
10*dc5a79c1SDavid du Colombier static Xfs	*xhead;
11*dc5a79c1SDavid du Colombier static Xfile *freelist;
12*dc5a79c1SDavid du Colombier static Lock	xlock, freelock;
13*dc5a79c1SDavid du Colombier 
14*dc5a79c1SDavid du Colombier int	client;
15*dc5a79c1SDavid du Colombier 
16*dc5a79c1SDavid du Colombier Xfs *
getxfs(char * name)17*dc5a79c1SDavid du Colombier getxfs(char *name)
18*dc5a79c1SDavid du Colombier {
19*dc5a79c1SDavid du Colombier 	int fd;
20*dc5a79c1SDavid du Colombier 	Dir *dir;
21*dc5a79c1SDavid du Colombier 	Xfs *xf, *fxf;
22*dc5a79c1SDavid du Colombier 
23*dc5a79c1SDavid du Colombier 	if(name==0 || name[0]==0)
24*dc5a79c1SDavid du Colombier 		name = deffile;
25*dc5a79c1SDavid du Colombier 	if(name == 0){
26*dc5a79c1SDavid du Colombier 		errno = Enofilsys;
27*dc5a79c1SDavid du Colombier 		return 0;
28*dc5a79c1SDavid du Colombier 	}
29*dc5a79c1SDavid du Colombier 	fd = open(name, rdonly ? OREAD : ORDWR);
30*dc5a79c1SDavid du Colombier 	if(fd < 0){
31*dc5a79c1SDavid du Colombier 		errno = Enonexist;
32*dc5a79c1SDavid du Colombier 		return 0;
33*dc5a79c1SDavid du Colombier 	}
34*dc5a79c1SDavid du Colombier 	if((dir = dirfstat(fd)) == 0){
35*dc5a79c1SDavid du Colombier 		errno = Eio;
36*dc5a79c1SDavid du Colombier 		close(fd);
37*dc5a79c1SDavid du Colombier 		return 0;
38*dc5a79c1SDavid du Colombier 	}
39*dc5a79c1SDavid du Colombier 	lock(&xlock);
40*dc5a79c1SDavid du Colombier 	for(fxf=0, xf=xhead; xf; xf=xf->next){
41*dc5a79c1SDavid du Colombier 		if(xf->ref == 0){
42*dc5a79c1SDavid du Colombier 			if(fxf == 0)
43*dc5a79c1SDavid du Colombier 				fxf = xf;
44*dc5a79c1SDavid du Colombier 			continue;
45*dc5a79c1SDavid du Colombier 		}
46*dc5a79c1SDavid du Colombier 		if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers)
47*dc5a79c1SDavid du Colombier 			continue;
48*dc5a79c1SDavid du Colombier 		if(strcmp(xf->name, name) != 0 || xf->dev < 0)
49*dc5a79c1SDavid du Colombier 			continue;
50*dc5a79c1SDavid du Colombier 		chat("incref \"%s\", dev=%d...", xf->name, xf->dev);
51*dc5a79c1SDavid du Colombier 		++xf->ref;
52*dc5a79c1SDavid du Colombier 		unlock(&xlock);
53*dc5a79c1SDavid du Colombier 		close(fd);
54*dc5a79c1SDavid du Colombier 		free(dir);
55*dc5a79c1SDavid du Colombier 		return xf;
56*dc5a79c1SDavid du Colombier 	}
57*dc5a79c1SDavid du Colombier 	if(fxf==0){
58*dc5a79c1SDavid du Colombier 		fxf = malloc(sizeof(Xfs));
59*dc5a79c1SDavid du Colombier 		if(fxf==0){
60*dc5a79c1SDavid du Colombier 			unlock(&xlock);
61*dc5a79c1SDavid du Colombier 			close(fd);
62*dc5a79c1SDavid du Colombier 			free(dir);
63*dc5a79c1SDavid du Colombier 			errno = Enomem;
64*dc5a79c1SDavid du Colombier 			return 0;
65*dc5a79c1SDavid du Colombier 		}
66*dc5a79c1SDavid du Colombier 		fxf->next = xhead;
67*dc5a79c1SDavid du Colombier 		xhead = fxf;
68*dc5a79c1SDavid du Colombier 	}
69*dc5a79c1SDavid du Colombier 	chat("alloc \"%s\", dev=%d...", name, fd);
70*dc5a79c1SDavid du Colombier 	fxf->name = strdup(name);
71*dc5a79c1SDavid du Colombier 	fxf->ref = 1;
72*dc5a79c1SDavid du Colombier 	fxf->qid = dir->qid;
73*dc5a79c1SDavid du Colombier 	fxf->dev = fd;
74*dc5a79c1SDavid du Colombier 	fxf->fmt = 0;
75*dc5a79c1SDavid du Colombier 	fxf->ptr = 0;
76*dc5a79c1SDavid du Colombier 	free(dir);
77*dc5a79c1SDavid du Colombier 	if( ext2fs(fxf)<0 ){
78*dc5a79c1SDavid du Colombier 		xhead = fxf->next;
79*dc5a79c1SDavid du Colombier 		free(fxf);
80*dc5a79c1SDavid du Colombier 		unlock(&xlock);
81*dc5a79c1SDavid du Colombier 		return 0;
82*dc5a79c1SDavid du Colombier 	}
83*dc5a79c1SDavid du Colombier 	unlock(&xlock);
84*dc5a79c1SDavid du Colombier 	return fxf;
85*dc5a79c1SDavid du Colombier }
86*dc5a79c1SDavid du Colombier 
87*dc5a79c1SDavid du Colombier void
refxfs(Xfs * xf,int delta)88*dc5a79c1SDavid du Colombier refxfs(Xfs *xf, int delta)
89*dc5a79c1SDavid du Colombier {
90*dc5a79c1SDavid du Colombier 	lock(&xlock);
91*dc5a79c1SDavid du Colombier 	xf->ref += delta;
92*dc5a79c1SDavid du Colombier 	if(xf->ref == 0){
93*dc5a79c1SDavid du Colombier 		/*mchat("free \"%s\", dev=%d...", xf->name, xf->dev);
94*dc5a79c1SDavid du Colombier 		dumpbuf();*/
95*dc5a79c1SDavid du Colombier 		CleanSuper(xf);
96*dc5a79c1SDavid du Colombier 		syncbuf();
97*dc5a79c1SDavid du Colombier 		free(xf->name);
98*dc5a79c1SDavid du Colombier 		purgebuf(xf);
99*dc5a79c1SDavid du Colombier 		if(xf->dev >= 0){
100*dc5a79c1SDavid du Colombier 			close(xf->dev);
101*dc5a79c1SDavid du Colombier 			xf->dev = -1;
102*dc5a79c1SDavid du Colombier 		}
103*dc5a79c1SDavid du Colombier 	}
104*dc5a79c1SDavid du Colombier 	unlock(&xlock);
105*dc5a79c1SDavid du Colombier }
106*dc5a79c1SDavid du Colombier 
107*dc5a79c1SDavid du Colombier Xfile *
xfile(Fid * fid,int flag)108*dc5a79c1SDavid du Colombier xfile(Fid *fid, int flag)
109*dc5a79c1SDavid du Colombier {
110*dc5a79c1SDavid du Colombier 	Xfile *f;
111*dc5a79c1SDavid du Colombier 
112*dc5a79c1SDavid du Colombier 	f = (Xfile*)fid->aux;
113*dc5a79c1SDavid du Colombier 	switch(flag){
114*dc5a79c1SDavid du Colombier 	default:
115*dc5a79c1SDavid du Colombier 		panic("xfile");
116*dc5a79c1SDavid du Colombier 	case Asis:
117*dc5a79c1SDavid du Colombier 		return (f && f->xf && f->xf->dev < 0) ? 0 : f;
118*dc5a79c1SDavid du Colombier 	case Clean:
119*dc5a79c1SDavid du Colombier 		if (f) chat("Clean and fid->aux already exists\n");
120*dc5a79c1SDavid du Colombier 		break;
121*dc5a79c1SDavid du Colombier 	case Clunk:
122*dc5a79c1SDavid du Colombier 		if(f){
123*dc5a79c1SDavid du Colombier 			clean(f);
124*dc5a79c1SDavid du Colombier 			lock(&freelock);
125*dc5a79c1SDavid du Colombier 			f->next = freelist;
126*dc5a79c1SDavid du Colombier 			freelist = f;
127*dc5a79c1SDavid du Colombier 			unlock(&freelock);
128*dc5a79c1SDavid du Colombier 			fid->aux = 0;
129*dc5a79c1SDavid du Colombier 		}
130*dc5a79c1SDavid du Colombier 		return 0;
131*dc5a79c1SDavid du Colombier 	}
132*dc5a79c1SDavid du Colombier 	if(f)
133*dc5a79c1SDavid du Colombier 		return clean(f);
134*dc5a79c1SDavid du Colombier 	lock(&freelock);
135*dc5a79c1SDavid du Colombier 	if(f = freelist){	/* assign = */
136*dc5a79c1SDavid du Colombier 		freelist = f->next;
137*dc5a79c1SDavid du Colombier 		unlock(&freelock);
138*dc5a79c1SDavid du Colombier 	} else {
139*dc5a79c1SDavid du Colombier 		unlock(&freelock);
140*dc5a79c1SDavid du Colombier 		f = malloc(sizeof(Xfile));
141*dc5a79c1SDavid du Colombier 	}
142*dc5a79c1SDavid du Colombier 	fid->aux = f;
143*dc5a79c1SDavid du Colombier 	f->fid = fid->fid;
144*dc5a79c1SDavid du Colombier 	f->client = client;
145*dc5a79c1SDavid du Colombier 	f->xf = 0;
146*dc5a79c1SDavid du Colombier 	f->ptr = 0;
147*dc5a79c1SDavid du Colombier 	f->root = 0;
148*dc5a79c1SDavid du Colombier 	return f;
149*dc5a79c1SDavid du Colombier }
150*dc5a79c1SDavid du Colombier Xfile *
clean(Xfile * f)151*dc5a79c1SDavid du Colombier clean(Xfile *f)
152*dc5a79c1SDavid du Colombier {
153*dc5a79c1SDavid du Colombier 	if(f->xf && f->root){
154*dc5a79c1SDavid du Colombier 		refxfs(f->xf, -1);
155*dc5a79c1SDavid du Colombier 		f->xf = 0;
156*dc5a79c1SDavid du Colombier 	}
157*dc5a79c1SDavid du Colombier 	f->xf = 0;
158*dc5a79c1SDavid du Colombier 	f->root = 0;
159*dc5a79c1SDavid du Colombier 	f->dirindex = 0;
160*dc5a79c1SDavid du Colombier 	return f;
161*dc5a79c1SDavid du Colombier }
162