xref: /plan9/sys/src/cmd/usb/lib/fsdir.c (revision 906943f9f6b8411972abb5e3a03ed19f74be7ccc)
1*906943f9SDavid du Colombier #include <u.h>
2*906943f9SDavid du Colombier #include <libc.h>
3*906943f9SDavid du Colombier #include <thread.h>
4*906943f9SDavid du Colombier #include <fcall.h>
5*906943f9SDavid du Colombier #include "usb.h"
6*906943f9SDavid du Colombier #include "usbfs.h"
7*906943f9SDavid du Colombier 
8*906943f9SDavid du Colombier typedef struct Rpc Rpc;
9*906943f9SDavid du Colombier 
10*906943f9SDavid du Colombier enum
11*906943f9SDavid du Colombier {
12*906943f9SDavid du Colombier 	Incr = 3,	/* increments for fs array */
13*906943f9SDavid du Colombier 	Dtop = 0,	/* high 32 bits for / 	*/
14*906943f9SDavid du Colombier 	Qdir = 0,	/* low 32 bits for /devdir */
15*906943f9SDavid du Colombier };
16*906943f9SDavid du Colombier 
17*906943f9SDavid du Colombier QLock fslck;
18*906943f9SDavid du Colombier static Usbfs** fs;
19*906943f9SDavid du Colombier static int nfs;
20*906943f9SDavid du Colombier static int fsused;
21*906943f9SDavid du Colombier static int exitonclose = 1;
22*906943f9SDavid du Colombier 
23*906943f9SDavid du Colombier void
24*906943f9SDavid du Colombier usbfsexits(int y)
25*906943f9SDavid du Colombier {
26*906943f9SDavid du Colombier 	exitonclose = y;
27*906943f9SDavid du Colombier }
28*906943f9SDavid du Colombier 
29*906943f9SDavid du Colombier static int
30*906943f9SDavid du Colombier qiddev(uvlong path)
31*906943f9SDavid du Colombier {
32*906943f9SDavid du Colombier 	return (int)(path>>32) & 0xFF;
33*906943f9SDavid du Colombier }
34*906943f9SDavid du Colombier 
35*906943f9SDavid du Colombier static int
36*906943f9SDavid du Colombier qidfile(uvlong path)
37*906943f9SDavid du Colombier {
38*906943f9SDavid du Colombier 	return (int)(path & 0xFFFFFFFFULL);
39*906943f9SDavid du Colombier }
40*906943f9SDavid du Colombier 
41*906943f9SDavid du Colombier static uvlong
42*906943f9SDavid du Colombier mkqid(int qd, int qf)
43*906943f9SDavid du Colombier {
44*906943f9SDavid du Colombier 	return ((uvlong)qd << 32) | (uvlong)qf;
45*906943f9SDavid du Colombier }
46*906943f9SDavid du Colombier 
47*906943f9SDavid du Colombier void
48*906943f9SDavid du Colombier usbfsdirdump(void)
49*906943f9SDavid du Colombier {
50*906943f9SDavid du Colombier 	int i;
51*906943f9SDavid du Colombier 
52*906943f9SDavid du Colombier 	qlock(&fslck);
53*906943f9SDavid du Colombier 	fprint(2, "%s: fs list: (%d used %d total)\n", argv0, fsused, nfs);
54*906943f9SDavid du Colombier 	for(i = 1; i < nfs; i++)
55*906943f9SDavid du Colombier 		if(fs[i] != nil)
56*906943f9SDavid du Colombier 			if(fs[i]->dev != nil)
57*906943f9SDavid du Colombier 				fprint(2, "%s\t%s dev %#p refs %ld\n",
58*906943f9SDavid du Colombier 					argv0, fs[i]->name, fs[i]->dev, fs[i]->dev->ref);
59*906943f9SDavid du Colombier 			else
60*906943f9SDavid du Colombier 				fprint(2, "%s:\t%s\n", argv0, fs[i]->name);
61*906943f9SDavid du Colombier 	qunlock(&fslck);
62*906943f9SDavid du Colombier }
63*906943f9SDavid du Colombier 
64*906943f9SDavid du Colombier void
65*906943f9SDavid du Colombier usbfsadd(Usbfs *dfs)
66*906943f9SDavid du Colombier {
67*906943f9SDavid du Colombier 	int i, j;
68*906943f9SDavid du Colombier 
69*906943f9SDavid du Colombier 	dprint(2, "%s: fsadd %s\n", argv0, dfs->name);
70*906943f9SDavid du Colombier 	qlock(&fslck);
71*906943f9SDavid du Colombier 	for(i = 1; i < nfs; i++)
72*906943f9SDavid du Colombier 		if(fs[i] == nil)
73*906943f9SDavid du Colombier 			break;
74*906943f9SDavid du Colombier 	if(i >= nfs){
75*906943f9SDavid du Colombier 		if((nfs%Incr) == 0){
76*906943f9SDavid du Colombier 			fs = realloc(fs, sizeof(Usbfs*) * (nfs+Incr));
77*906943f9SDavid du Colombier 			if(fs == nil)
78*906943f9SDavid du Colombier 				sysfatal("realloc: %r");
79*906943f9SDavid du Colombier 			for(j = nfs; j < nfs+Incr; j++)
80*906943f9SDavid du Colombier 				fs[j] = nil;
81*906943f9SDavid du Colombier 		}
82*906943f9SDavid du Colombier 		if(nfs == 0)	/* do not use entry 0 */
83*906943f9SDavid du Colombier 			nfs++;
84*906943f9SDavid du Colombier 		fs[nfs++] = dfs;
85*906943f9SDavid du Colombier 	}else
86*906943f9SDavid du Colombier 		fs[i] = dfs;
87*906943f9SDavid du Colombier 	dfs->qid = mkqid(i, 0);
88*906943f9SDavid du Colombier 	fsused++;
89*906943f9SDavid du Colombier 	qunlock(&fslck);
90*906943f9SDavid du Colombier }
91*906943f9SDavid du Colombier 
92*906943f9SDavid du Colombier static void
93*906943f9SDavid du Colombier usbfsdelnth(int i)
94*906943f9SDavid du Colombier {
95*906943f9SDavid du Colombier 	if(fs[i] != nil){
96*906943f9SDavid du Colombier 		dprint(2, "%s: fsdel %s", argv0, fs[i]->name);
97*906943f9SDavid du Colombier 		if(fs[i]->dev != nil){
98*906943f9SDavid du Colombier 			dprint(2, " dev %#p ref %ld\n",
99*906943f9SDavid du Colombier 				fs[i]->dev, fs[i]->dev->ref);
100*906943f9SDavid du Colombier 		}else
101*906943f9SDavid du Colombier 			dprint(2, "no dev\n");
102*906943f9SDavid du Colombier 		if(fs[i]->end != nil)
103*906943f9SDavid du Colombier 			fs[i]->end(fs[i]);
104*906943f9SDavid du Colombier 		else
105*906943f9SDavid du Colombier 			closedev(fs[i]->dev);
106*906943f9SDavid du Colombier 		fsused--;
107*906943f9SDavid du Colombier 	}
108*906943f9SDavid du Colombier 	fs[i] = nil;
109*906943f9SDavid du Colombier 	if(fsused == 0 && exitonclose != 0){
110*906943f9SDavid du Colombier 		fprint(2, "%s: all file systems gone: exiting\n", argv0);
111*906943f9SDavid du Colombier 		threadexitsall(nil);
112*906943f9SDavid du Colombier 	}
113*906943f9SDavid du Colombier }
114*906943f9SDavid du Colombier 
115*906943f9SDavid du Colombier void
116*906943f9SDavid du Colombier usbfsdel(Usbfs *dfs)
117*906943f9SDavid du Colombier {
118*906943f9SDavid du Colombier 	int i;
119*906943f9SDavid du Colombier 
120*906943f9SDavid du Colombier 	qlock(&fslck);
121*906943f9SDavid du Colombier 	for(i = 0; i < nfs; i++)
122*906943f9SDavid du Colombier 		if(dfs == nil || fs[i] == dfs){
123*906943f9SDavid du Colombier 			usbfsdelnth(i);
124*906943f9SDavid du Colombier 			if(dfs != nil)
125*906943f9SDavid du Colombier 				break;
126*906943f9SDavid du Colombier 		}
127*906943f9SDavid du Colombier 	qunlock(&fslck);
128*906943f9SDavid du Colombier }
129*906943f9SDavid du Colombier 
130*906943f9SDavid du Colombier static void
131*906943f9SDavid du Colombier fsend(Usbfs*)
132*906943f9SDavid du Colombier {
133*906943f9SDavid du Colombier 	dprint(2, "%s: fsend\n", argv0);
134*906943f9SDavid du Colombier 	usbfsdel(nil);
135*906943f9SDavid du Colombier }
136*906943f9SDavid du Colombier 
137*906943f9SDavid du Colombier void
138*906943f9SDavid du Colombier usbfsgone(char *dir)
139*906943f9SDavid du Colombier {
140*906943f9SDavid du Colombier 	int i;
141*906943f9SDavid du Colombier 
142*906943f9SDavid du Colombier 	qlock(&fslck);
143*906943f9SDavid du Colombier 	/* devices may have more than one fs */
144*906943f9SDavid du Colombier 	for(i = 0; i < nfs; i++)
145*906943f9SDavid du Colombier 		if(fs[i] != nil && fs[i]->dev != nil)
146*906943f9SDavid du Colombier 		if(strcmp(fs[i]->dev->dir, dir) == 0)
147*906943f9SDavid du Colombier 			usbfsdelnth(i);
148*906943f9SDavid du Colombier 	qunlock(&fslck);
149*906943f9SDavid du Colombier }
150*906943f9SDavid du Colombier 
151*906943f9SDavid du Colombier static void
152*906943f9SDavid du Colombier fsclone(Usbfs*, Fid *o, Fid *n)
153*906943f9SDavid du Colombier {
154*906943f9SDavid du Colombier 	int qd;
155*906943f9SDavid du Colombier 	Dev *dev;
156*906943f9SDavid du Colombier 	void (*xfsclone)(Usbfs *fs, Fid *of, Fid *nf);
157*906943f9SDavid du Colombier 
158*906943f9SDavid du Colombier 	xfsclone = nil;
159*906943f9SDavid du Colombier 	dev = nil;
160*906943f9SDavid du Colombier 	qd = qiddev(o->qid.path);
161*906943f9SDavid du Colombier 	qlock(&fslck);
162*906943f9SDavid du Colombier 	if(qd != Dtop && fs[qd] != nil && fs[qd]->clone != nil){
163*906943f9SDavid du Colombier 		dev = fs[qd]->dev;
164*906943f9SDavid du Colombier 		if(dev != nil)
165*906943f9SDavid du Colombier 			incref(dev);
166*906943f9SDavid du Colombier 		xfsclone = fs[qd]->clone;
167*906943f9SDavid du Colombier 	}
168*906943f9SDavid du Colombier 	qunlock(&fslck);
169*906943f9SDavid du Colombier 	if(xfsclone != nil){
170*906943f9SDavid du Colombier 		xfsclone(fs[qd], o, n);
171*906943f9SDavid du Colombier 	}
172*906943f9SDavid du Colombier 	if(dev != nil)
173*906943f9SDavid du Colombier 		closedev(dev);
174*906943f9SDavid du Colombier }
175*906943f9SDavid du Colombier 
176*906943f9SDavid du Colombier static int
177*906943f9SDavid du Colombier fswalk(Usbfs*, Fid *fid, char *name)
178*906943f9SDavid du Colombier {
179*906943f9SDavid du Colombier 	Qid q;
180*906943f9SDavid du Colombier 	int qd, qf;
181*906943f9SDavid du Colombier 	int i;
182*906943f9SDavid du Colombier 	int rc;
183*906943f9SDavid du Colombier 	Dev *dev;
184*906943f9SDavid du Colombier 	Dir d;
185*906943f9SDavid du Colombier 	int (*xfswalk)(Usbfs *fs, Fid *f, char *name);
186*906943f9SDavid du Colombier 
187*906943f9SDavid du Colombier 	q = fid->qid;
188*906943f9SDavid du Colombier 	qd = qiddev(q.path);
189*906943f9SDavid du Colombier 	qf = qidfile(q.path);
190*906943f9SDavid du Colombier 
191*906943f9SDavid du Colombier 	q.type = QTDIR;
192*906943f9SDavid du Colombier 	q.vers = 0;
193*906943f9SDavid du Colombier 	if(strcmp(name, "..") == 0)
194*906943f9SDavid du Colombier 		if(qd == Dtop || qf == Qdir){
195*906943f9SDavid du Colombier 			q.path = mkqid(Dtop, Qdir);
196*906943f9SDavid du Colombier 			fid->qid = q;
197*906943f9SDavid du Colombier 			return 0;
198*906943f9SDavid du Colombier 		}
199*906943f9SDavid du Colombier 	if(qd != 0){
200*906943f9SDavid du Colombier 		qlock(&fslck);
201*906943f9SDavid du Colombier 		if(fs[qd] == nil){
202*906943f9SDavid du Colombier 			qunlock(&fslck);
203*906943f9SDavid du Colombier 			werrstr(Eio);
204*906943f9SDavid du Colombier 			return -1;
205*906943f9SDavid du Colombier 		}
206*906943f9SDavid du Colombier 		dev = fs[qd]->dev;
207*906943f9SDavid du Colombier 		if(dev != nil)
208*906943f9SDavid du Colombier 			incref(dev);
209*906943f9SDavid du Colombier 		xfswalk = fs[qd]->walk;
210*906943f9SDavid du Colombier 		qunlock(&fslck);
211*906943f9SDavid du Colombier 		rc = xfswalk(fs[qd], fid, name);
212*906943f9SDavid du Colombier 		if(dev != nil)
213*906943f9SDavid du Colombier 			closedev(dev);
214*906943f9SDavid du Colombier 		return rc;
215*906943f9SDavid du Colombier 	}
216*906943f9SDavid du Colombier 	qlock(&fslck);
217*906943f9SDavid du Colombier 	for(i = 0; i < nfs; i++)
218*906943f9SDavid du Colombier 		if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){
219*906943f9SDavid du Colombier 			q.path = mkqid(i, Qdir);
220*906943f9SDavid du Colombier 			fs[i]->stat(fs[i], q, &d); /* may be a file */
221*906943f9SDavid du Colombier 			fid->qid = d.qid;
222*906943f9SDavid du Colombier 			qunlock(&fslck);
223*906943f9SDavid du Colombier 			return 0;
224*906943f9SDavid du Colombier 		}
225*906943f9SDavid du Colombier 	qunlock(&fslck);
226*906943f9SDavid du Colombier 	werrstr(Enotfound);
227*906943f9SDavid du Colombier 	return -1;
228*906943f9SDavid du Colombier }
229*906943f9SDavid du Colombier 
230*906943f9SDavid du Colombier static int
231*906943f9SDavid du Colombier fsopen(Usbfs*, Fid *fid, int mode)
232*906943f9SDavid du Colombier {
233*906943f9SDavid du Colombier 	int qd;
234*906943f9SDavid du Colombier 	int rc;
235*906943f9SDavid du Colombier 	Dev *dev;
236*906943f9SDavid du Colombier 	int (*xfsopen)(Usbfs *fs, Fid *f, int mode);
237*906943f9SDavid du Colombier 
238*906943f9SDavid du Colombier 	qd = qiddev(fid->qid.path);
239*906943f9SDavid du Colombier 	if(qd == Dtop)
240*906943f9SDavid du Colombier 		return 0;
241*906943f9SDavid du Colombier 	qlock(&fslck);
242*906943f9SDavid du Colombier 	if(fs[qd] == nil){
243*906943f9SDavid du Colombier 		qunlock(&fslck);
244*906943f9SDavid du Colombier 		werrstr(Eio);
245*906943f9SDavid du Colombier 		return -1;
246*906943f9SDavid du Colombier 	}
247*906943f9SDavid du Colombier 	dev = fs[qd]->dev;
248*906943f9SDavid du Colombier 	if(dev != nil)
249*906943f9SDavid du Colombier 		incref(dev);
250*906943f9SDavid du Colombier 	xfsopen = fs[qd]->open;
251*906943f9SDavid du Colombier 	qunlock(&fslck);
252*906943f9SDavid du Colombier 	if(xfsopen != nil)
253*906943f9SDavid du Colombier 		rc = xfsopen(fs[qd], fid, mode);
254*906943f9SDavid du Colombier 	else
255*906943f9SDavid du Colombier 		rc = 0;
256*906943f9SDavid du Colombier 	if(dev != nil)
257*906943f9SDavid du Colombier 		closedev(dev);
258*906943f9SDavid du Colombier 	return rc;
259*906943f9SDavid du Colombier }
260*906943f9SDavid du Colombier 
261*906943f9SDavid du Colombier static int
262*906943f9SDavid du Colombier dirgen(Usbfs*, Qid, int n, Dir *d, void *)
263*906943f9SDavid du Colombier {
264*906943f9SDavid du Colombier 	int i;
265*906943f9SDavid du Colombier 	Dev *dev;
266*906943f9SDavid du Colombier 	char *nm;
267*906943f9SDavid du Colombier 
268*906943f9SDavid du Colombier 	qlock(&fslck);
269*906943f9SDavid du Colombier 	for(i = 0; i < nfs; i++)
270*906943f9SDavid du Colombier 		if(fs[i] != nil && n-- == 0){
271*906943f9SDavid du Colombier 			d->qid.type = QTDIR;
272*906943f9SDavid du Colombier 			d->qid.path = mkqid(i, Qdir);
273*906943f9SDavid du Colombier 			d->qid.vers = 0;
274*906943f9SDavid du Colombier 			dev = fs[i]->dev;
275*906943f9SDavid du Colombier 			if(dev != nil)
276*906943f9SDavid du Colombier 				incref(dev);
277*906943f9SDavid du Colombier 			nm = d->name;
278*906943f9SDavid du Colombier 			fs[i]->stat(fs[i], d->qid, d);
279*906943f9SDavid du Colombier 			d->name = nm;
280*906943f9SDavid du Colombier 			strncpy(d->name, fs[i]->name, Namesz);
281*906943f9SDavid du Colombier 			if(dev != nil)
282*906943f9SDavid du Colombier 				closedev(dev);
283*906943f9SDavid du Colombier 			qunlock(&fslck);
284*906943f9SDavid du Colombier 			return 0;
285*906943f9SDavid du Colombier 		}
286*906943f9SDavid du Colombier 	qunlock(&fslck);
287*906943f9SDavid du Colombier 	return -1;
288*906943f9SDavid du Colombier }
289*906943f9SDavid du Colombier 
290*906943f9SDavid du Colombier static long
291*906943f9SDavid du Colombier fsread(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
292*906943f9SDavid du Colombier {
293*906943f9SDavid du Colombier 	int qd;
294*906943f9SDavid du Colombier 	int rc;
295*906943f9SDavid du Colombier 	Dev *dev;
296*906943f9SDavid du Colombier 	Qid q;
297*906943f9SDavid du Colombier 	long (*xfsread)(Usbfs *fs, Fid *f, void *data, long count, vlong );
298*906943f9SDavid du Colombier 
299*906943f9SDavid du Colombier 	q = fid->qid;
300*906943f9SDavid du Colombier 	qd = qiddev(q.path);
301*906943f9SDavid du Colombier 	if(qd == Dtop)
302*906943f9SDavid du Colombier 		return usbdirread(nil, q, data, cnt, off, dirgen, nil);
303*906943f9SDavid du Colombier 	qlock(&fslck);
304*906943f9SDavid du Colombier 	if(fs[qd] == nil){
305*906943f9SDavid du Colombier 		qunlock(&fslck);
306*906943f9SDavid du Colombier 		werrstr(Eio);
307*906943f9SDavid du Colombier 		return -1;
308*906943f9SDavid du Colombier 	}
309*906943f9SDavid du Colombier 	dev = fs[qd]->dev;
310*906943f9SDavid du Colombier 	if(dev != nil)
311*906943f9SDavid du Colombier 		incref(dev);
312*906943f9SDavid du Colombier 	xfsread = fs[qd]->read;
313*906943f9SDavid du Colombier 	qunlock(&fslck);
314*906943f9SDavid du Colombier 	rc = xfsread(fs[qd], fid, data, cnt, off);
315*906943f9SDavid du Colombier 	if(dev != nil)
316*906943f9SDavid du Colombier 		closedev(dev);
317*906943f9SDavid du Colombier 	return rc;
318*906943f9SDavid du Colombier }
319*906943f9SDavid du Colombier 
320*906943f9SDavid du Colombier static long
321*906943f9SDavid du Colombier fswrite(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
322*906943f9SDavid du Colombier {
323*906943f9SDavid du Colombier 	int qd;
324*906943f9SDavid du Colombier 	int rc;
325*906943f9SDavid du Colombier 	Dev *dev;
326*906943f9SDavid du Colombier 	long (*xfswrite)(Usbfs *fs, Fid *f, void *data, long count, vlong );
327*906943f9SDavid du Colombier 
328*906943f9SDavid du Colombier 	qd = qiddev(fid->qid.path);
329*906943f9SDavid du Colombier 	if(qd == Dtop)
330*906943f9SDavid du Colombier 		sysfatal("fswrite: not for usbd /");
331*906943f9SDavid du Colombier 	qlock(&fslck);
332*906943f9SDavid du Colombier 	if(fs[qd] == nil){
333*906943f9SDavid du Colombier 		qunlock(&fslck);
334*906943f9SDavid du Colombier 		werrstr(Eio);
335*906943f9SDavid du Colombier 		return -1;
336*906943f9SDavid du Colombier 	}
337*906943f9SDavid du Colombier 	dev = fs[qd]->dev;
338*906943f9SDavid du Colombier 	if(dev != nil)
339*906943f9SDavid du Colombier 		incref(dev);
340*906943f9SDavid du Colombier 	xfswrite = fs[qd]->write;
341*906943f9SDavid du Colombier 	qunlock(&fslck);
342*906943f9SDavid du Colombier 	rc = xfswrite(fs[qd], fid, data, cnt, off);
343*906943f9SDavid du Colombier 	if(dev != nil)
344*906943f9SDavid du Colombier 		closedev(dev);
345*906943f9SDavid du Colombier 	return rc;
346*906943f9SDavid du Colombier }
347*906943f9SDavid du Colombier 
348*906943f9SDavid du Colombier 
349*906943f9SDavid du Colombier static void
350*906943f9SDavid du Colombier fsclunk(Usbfs*, Fid* fid)
351*906943f9SDavid du Colombier {
352*906943f9SDavid du Colombier 	int qd;
353*906943f9SDavid du Colombier 	Dev *dev;
354*906943f9SDavid du Colombier 	void (*xfsclunk)(Usbfs *fs, Fid *f);
355*906943f9SDavid du Colombier 
356*906943f9SDavid du Colombier 	dev = nil;
357*906943f9SDavid du Colombier 	qd = qiddev(fid->qid.path);
358*906943f9SDavid du Colombier 	qlock(&fslck);
359*906943f9SDavid du Colombier 	if(qd != Dtop && fs[qd] != nil){
360*906943f9SDavid du Colombier 		dev=fs[qd]->dev;
361*906943f9SDavid du Colombier 		if(dev != nil)
362*906943f9SDavid du Colombier 			incref(dev);
363*906943f9SDavid du Colombier 		xfsclunk = fs[qd]->clunk;
364*906943f9SDavid du Colombier 	}else
365*906943f9SDavid du Colombier 		xfsclunk = nil;
366*906943f9SDavid du Colombier 	qunlock(&fslck);
367*906943f9SDavid du Colombier 	if(xfsclunk != nil){
368*906943f9SDavid du Colombier 		xfsclunk(fs[qd], fid);
369*906943f9SDavid du Colombier 	}
370*906943f9SDavid du Colombier 	if(dev != nil)
371*906943f9SDavid du Colombier 		closedev(dev);
372*906943f9SDavid du Colombier }
373*906943f9SDavid du Colombier 
374*906943f9SDavid du Colombier static int
375*906943f9SDavid du Colombier fsstat(Usbfs*, Qid qid, Dir *d)
376*906943f9SDavid du Colombier {
377*906943f9SDavid du Colombier 	int qd;
378*906943f9SDavid du Colombier 	int rc;
379*906943f9SDavid du Colombier 	Dev *dev;
380*906943f9SDavid du Colombier 	int (*xfsstat)(Usbfs *fs, Qid q, Dir *d);
381*906943f9SDavid du Colombier 
382*906943f9SDavid du Colombier 	qd = qiddev(qid.path);
383*906943f9SDavid du Colombier 	if(qd == Dtop){
384*906943f9SDavid du Colombier 		d->qid = qid;
385*906943f9SDavid du Colombier 		d->name = "usb";
386*906943f9SDavid du Colombier 		d->length = 0;
387*906943f9SDavid du Colombier 		d->mode = 0555|DMDIR;
388*906943f9SDavid du Colombier 		return 0;
389*906943f9SDavid du Colombier 	}
390*906943f9SDavid du Colombier 	qlock(&fslck);
391*906943f9SDavid du Colombier 	if(fs[qd] == nil){
392*906943f9SDavid du Colombier 		qunlock(&fslck);
393*906943f9SDavid du Colombier 		werrstr(Eio);
394*906943f9SDavid du Colombier 		return -1;
395*906943f9SDavid du Colombier 	}
396*906943f9SDavid du Colombier 	xfsstat = fs[qd]->stat;
397*906943f9SDavid du Colombier 	dev = fs[qd]->dev;
398*906943f9SDavid du Colombier 	if(dev != nil)
399*906943f9SDavid du Colombier 		incref(dev);
400*906943f9SDavid du Colombier 	qunlock(&fslck);
401*906943f9SDavid du Colombier 	rc = xfsstat(fs[qd], qid, d);
402*906943f9SDavid du Colombier 	if(dev != nil)
403*906943f9SDavid du Colombier 		closedev(dev);
404*906943f9SDavid du Colombier 	return rc;
405*906943f9SDavid du Colombier }
406*906943f9SDavid du Colombier 
407*906943f9SDavid du Colombier Usbfs usbdirfs =
408*906943f9SDavid du Colombier {
409*906943f9SDavid du Colombier 	.walk = fswalk,
410*906943f9SDavid du Colombier 	.clone = fsclone,
411*906943f9SDavid du Colombier 	.clunk = fsclunk,
412*906943f9SDavid du Colombier 	.open = fsopen,
413*906943f9SDavid du Colombier 	.read = fsread,
414*906943f9SDavid du Colombier 	.write = fswrite,
415*906943f9SDavid du Colombier 	.stat = fsstat,
416*906943f9SDavid du Colombier 	.end = fsend,
417*906943f9SDavid du Colombier };
418*906943f9SDavid du Colombier 
419