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