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
usbfsexits(int y)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
qiddev(uvlong path)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
qidfile(uvlong path)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
mkqid(int qd,int qf)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
usbfsdirdump(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
usbfsadd(Usbfs * dfs)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
usbfsdelnth(int i)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 closedev(fs[i]->dev);
105*906943f9SDavid du Colombier fsused--;
106*906943f9SDavid du Colombier }
107*906943f9SDavid du Colombier fs[i] = nil;
108*906943f9SDavid du Colombier if(fsused == 0 && exitonclose != 0){
109*906943f9SDavid du Colombier fprint(2, "%s: all file systems gone: exiting\n", argv0);
110*906943f9SDavid du Colombier threadexitsall(nil);
111*906943f9SDavid du Colombier }
112*906943f9SDavid du Colombier }
113*906943f9SDavid du Colombier
114*906943f9SDavid du Colombier void
usbfsdel(Usbfs * dfs)115*906943f9SDavid du Colombier usbfsdel(Usbfs *dfs)
116*906943f9SDavid du Colombier {
117*906943f9SDavid du Colombier int i;
118*906943f9SDavid du Colombier
119*906943f9SDavid du Colombier qlock(&fslck);
120*906943f9SDavid du Colombier for(i = 0; i < nfs; i++)
121*906943f9SDavid du Colombier if(dfs == nil || fs[i] == dfs){
122*906943f9SDavid du Colombier usbfsdelnth(i);
123*906943f9SDavid du Colombier if(dfs != nil)
124*906943f9SDavid du Colombier break;
125*906943f9SDavid du Colombier }
126*906943f9SDavid du Colombier qunlock(&fslck);
127*906943f9SDavid du Colombier }
128*906943f9SDavid du Colombier
129*906943f9SDavid du Colombier static void
fsend(Usbfs *)130*906943f9SDavid du Colombier fsend(Usbfs*)
131*906943f9SDavid du Colombier {
132*906943f9SDavid du Colombier dprint(2, "%s: fsend\n", argv0);
133*906943f9SDavid du Colombier usbfsdel(nil);
134*906943f9SDavid du Colombier }
135*906943f9SDavid du Colombier
136*906943f9SDavid du Colombier void
usbfsgone(char * dir)137*906943f9SDavid du Colombier usbfsgone(char *dir)
138*906943f9SDavid du Colombier {
139*906943f9SDavid du Colombier int i;
140*906943f9SDavid du Colombier
141*906943f9SDavid du Colombier qlock(&fslck);
142*906943f9SDavid du Colombier /* devices may have more than one fs */
143*906943f9SDavid du Colombier for(i = 0; i < nfs; i++)
144*906943f9SDavid du Colombier if(fs[i] != nil && fs[i]->dev != nil)
145*906943f9SDavid du Colombier if(strcmp(fs[i]->dev->dir, dir) == 0)
146*906943f9SDavid du Colombier usbfsdelnth(i);
147*906943f9SDavid du Colombier qunlock(&fslck);
148*906943f9SDavid du Colombier }
149*906943f9SDavid du Colombier
150*906943f9SDavid du Colombier static void
fsclone(Usbfs *,Fid * o,Fid * n)151*906943f9SDavid du Colombier fsclone(Usbfs*, Fid *o, Fid *n)
152*906943f9SDavid du Colombier {
153*906943f9SDavid du Colombier int qd;
154*906943f9SDavid du Colombier Dev *dev;
155*906943f9SDavid du Colombier void (*xfsclone)(Usbfs *fs, Fid *of, Fid *nf);
156*906943f9SDavid du Colombier
157*906943f9SDavid du Colombier xfsclone = nil;
158*906943f9SDavid du Colombier dev = nil;
159*906943f9SDavid du Colombier qd = qiddev(o->qid.path);
160*906943f9SDavid du Colombier qlock(&fslck);
161*906943f9SDavid du Colombier if(qd != Dtop && fs[qd] != nil && fs[qd]->clone != nil){
162*906943f9SDavid du Colombier dev = fs[qd]->dev;
163*906943f9SDavid du Colombier if(dev != nil)
164*906943f9SDavid du Colombier incref(dev);
165*906943f9SDavid du Colombier xfsclone = fs[qd]->clone;
166*906943f9SDavid du Colombier }
167*906943f9SDavid du Colombier qunlock(&fslck);
168*906943f9SDavid du Colombier if(xfsclone != nil){
169*906943f9SDavid du Colombier xfsclone(fs[qd], o, n);
170*906943f9SDavid du Colombier }
171*906943f9SDavid du Colombier if(dev != nil)
172*906943f9SDavid du Colombier closedev(dev);
173*906943f9SDavid du Colombier }
174*906943f9SDavid du Colombier
175*906943f9SDavid du Colombier static int
fswalk(Usbfs *,Fid * fid,char * name)176*906943f9SDavid du Colombier fswalk(Usbfs*, Fid *fid, char *name)
177*906943f9SDavid du Colombier {
178*906943f9SDavid du Colombier Qid q;
179*906943f9SDavid du Colombier int qd, qf;
180*906943f9SDavid du Colombier int i;
181*906943f9SDavid du Colombier int rc;
182*906943f9SDavid du Colombier Dev *dev;
183*906943f9SDavid du Colombier Dir d;
184*906943f9SDavid du Colombier int (*xfswalk)(Usbfs *fs, Fid *f, char *name);
185*906943f9SDavid du Colombier
186*906943f9SDavid du Colombier q = fid->qid;
187*906943f9SDavid du Colombier qd = qiddev(q.path);
188*906943f9SDavid du Colombier qf = qidfile(q.path);
189*906943f9SDavid du Colombier
190*906943f9SDavid du Colombier q.type = QTDIR;
191*906943f9SDavid du Colombier q.vers = 0;
192*906943f9SDavid du Colombier if(strcmp(name, "..") == 0)
193*906943f9SDavid du Colombier if(qd == Dtop || qf == Qdir){
194*906943f9SDavid du Colombier q.path = mkqid(Dtop, Qdir);
195*906943f9SDavid du Colombier fid->qid = q;
196*906943f9SDavid du Colombier return 0;
197*906943f9SDavid du Colombier }
198*906943f9SDavid du Colombier if(qd != 0){
199*906943f9SDavid du Colombier qlock(&fslck);
200*906943f9SDavid du Colombier if(fs[qd] == nil){
201*906943f9SDavid du Colombier qunlock(&fslck);
202*906943f9SDavid du Colombier werrstr(Eio);
203*906943f9SDavid du Colombier return -1;
204*906943f9SDavid du Colombier }
205*906943f9SDavid du Colombier dev = fs[qd]->dev;
206*906943f9SDavid du Colombier if(dev != nil)
207*906943f9SDavid du Colombier incref(dev);
208*906943f9SDavid du Colombier xfswalk = fs[qd]->walk;
209*906943f9SDavid du Colombier qunlock(&fslck);
210*906943f9SDavid du Colombier rc = xfswalk(fs[qd], fid, name);
211*906943f9SDavid du Colombier if(dev != nil)
212*906943f9SDavid du Colombier closedev(dev);
213*906943f9SDavid du Colombier return rc;
214*906943f9SDavid du Colombier }
215*906943f9SDavid du Colombier qlock(&fslck);
216*906943f9SDavid du Colombier for(i = 0; i < nfs; i++)
217*906943f9SDavid du Colombier if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){
218*906943f9SDavid du Colombier q.path = mkqid(i, Qdir);
219*906943f9SDavid du Colombier fs[i]->stat(fs[i], q, &d); /* may be a file */
220*906943f9SDavid du Colombier fid->qid = d.qid;
221*906943f9SDavid du Colombier qunlock(&fslck);
222*906943f9SDavid du Colombier return 0;
223*906943f9SDavid du Colombier }
224*906943f9SDavid du Colombier qunlock(&fslck);
225*906943f9SDavid du Colombier werrstr(Enotfound);
226*906943f9SDavid du Colombier return -1;
227*906943f9SDavid du Colombier }
228*906943f9SDavid du Colombier
229*906943f9SDavid du Colombier static int
fsopen(Usbfs *,Fid * fid,int mode)230*906943f9SDavid du Colombier fsopen(Usbfs*, Fid *fid, int mode)
231*906943f9SDavid du Colombier {
232*906943f9SDavid du Colombier int qd;
233*906943f9SDavid du Colombier int rc;
234*906943f9SDavid du Colombier Dev *dev;
235*906943f9SDavid du Colombier int (*xfsopen)(Usbfs *fs, Fid *f, int mode);
236*906943f9SDavid du Colombier
237*906943f9SDavid du Colombier qd = qiddev(fid->qid.path);
238*906943f9SDavid du Colombier if(qd == Dtop)
239*906943f9SDavid du Colombier return 0;
240*906943f9SDavid du Colombier qlock(&fslck);
241*906943f9SDavid du Colombier if(fs[qd] == nil){
242*906943f9SDavid du Colombier qunlock(&fslck);
243*906943f9SDavid du Colombier werrstr(Eio);
244*906943f9SDavid du Colombier return -1;
245*906943f9SDavid du Colombier }
246*906943f9SDavid du Colombier dev = fs[qd]->dev;
247*906943f9SDavid du Colombier if(dev != nil)
248*906943f9SDavid du Colombier incref(dev);
249*906943f9SDavid du Colombier xfsopen = fs[qd]->open;
250*906943f9SDavid du Colombier qunlock(&fslck);
251*906943f9SDavid du Colombier if(xfsopen != nil)
252*906943f9SDavid du Colombier rc = xfsopen(fs[qd], fid, mode);
253*906943f9SDavid du Colombier else
254*906943f9SDavid du Colombier rc = 0;
255*906943f9SDavid du Colombier if(dev != nil)
256*906943f9SDavid du Colombier closedev(dev);
257*906943f9SDavid du Colombier return rc;
258*906943f9SDavid du Colombier }
259*906943f9SDavid du Colombier
260*906943f9SDavid du Colombier static int
dirgen(Usbfs *,Qid,int n,Dir * d,void *)261*906943f9SDavid du Colombier dirgen(Usbfs*, Qid, int n, Dir *d, void *)
262*906943f9SDavid du Colombier {
263*906943f9SDavid du Colombier int i;
264*906943f9SDavid du Colombier Dev *dev;
265*906943f9SDavid du Colombier char *nm;
266*906943f9SDavid du Colombier
267*906943f9SDavid du Colombier qlock(&fslck);
268*906943f9SDavid du Colombier for(i = 0; i < nfs; i++)
269*906943f9SDavid du Colombier if(fs[i] != nil && n-- == 0){
270*906943f9SDavid du Colombier d->qid.type = QTDIR;
271*906943f9SDavid du Colombier d->qid.path = mkqid(i, Qdir);
272*906943f9SDavid du Colombier d->qid.vers = 0;
273*906943f9SDavid du Colombier dev = fs[i]->dev;
274*906943f9SDavid du Colombier if(dev != nil)
275*906943f9SDavid du Colombier incref(dev);
276*906943f9SDavid du Colombier nm = d->name;
277*906943f9SDavid du Colombier fs[i]->stat(fs[i], d->qid, d);
278*906943f9SDavid du Colombier d->name = nm;
279*906943f9SDavid du Colombier strncpy(d->name, fs[i]->name, Namesz);
280*906943f9SDavid du Colombier if(dev != nil)
281*906943f9SDavid du Colombier closedev(dev);
282*906943f9SDavid du Colombier qunlock(&fslck);
283*906943f9SDavid du Colombier return 0;
284*906943f9SDavid du Colombier }
285*906943f9SDavid du Colombier qunlock(&fslck);
286*906943f9SDavid du Colombier return -1;
287*906943f9SDavid du Colombier }
288*906943f9SDavid du Colombier
289*906943f9SDavid du Colombier static long
fsread(Usbfs *,Fid * fid,void * data,long cnt,vlong off)290*906943f9SDavid du Colombier fsread(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
291*906943f9SDavid du Colombier {
292*906943f9SDavid du Colombier int qd;
293*906943f9SDavid du Colombier int rc;
294*906943f9SDavid du Colombier Dev *dev;
295*906943f9SDavid du Colombier Qid q;
296*906943f9SDavid du Colombier long (*xfsread)(Usbfs *fs, Fid *f, void *data, long count, vlong );
297*906943f9SDavid du Colombier
298*906943f9SDavid du Colombier q = fid->qid;
299*906943f9SDavid du Colombier qd = qiddev(q.path);
300*906943f9SDavid du Colombier if(qd == Dtop)
301*906943f9SDavid du Colombier return usbdirread(nil, q, data, cnt, off, dirgen, nil);
302*906943f9SDavid du Colombier qlock(&fslck);
303*906943f9SDavid du Colombier if(fs[qd] == nil){
304*906943f9SDavid du Colombier qunlock(&fslck);
305*906943f9SDavid du Colombier werrstr(Eio);
306*906943f9SDavid du Colombier return -1;
307*906943f9SDavid du Colombier }
308*906943f9SDavid du Colombier dev = fs[qd]->dev;
309*906943f9SDavid du Colombier if(dev != nil)
310*906943f9SDavid du Colombier incref(dev);
311*906943f9SDavid du Colombier xfsread = fs[qd]->read;
312*906943f9SDavid du Colombier qunlock(&fslck);
313*906943f9SDavid du Colombier rc = xfsread(fs[qd], fid, data, cnt, off);
314*906943f9SDavid du Colombier if(dev != nil)
315*906943f9SDavid du Colombier closedev(dev);
316*906943f9SDavid du Colombier return rc;
317*906943f9SDavid du Colombier }
318*906943f9SDavid du Colombier
319*906943f9SDavid du Colombier static long
fswrite(Usbfs *,Fid * fid,void * data,long cnt,vlong off)320*906943f9SDavid du Colombier fswrite(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
321*906943f9SDavid du Colombier {
322*906943f9SDavid du Colombier int qd;
323*906943f9SDavid du Colombier int rc;
324*906943f9SDavid du Colombier Dev *dev;
325*906943f9SDavid du Colombier long (*xfswrite)(Usbfs *fs, Fid *f, void *data, long count, vlong );
326*906943f9SDavid du Colombier
327*906943f9SDavid du Colombier qd = qiddev(fid->qid.path);
328*906943f9SDavid du Colombier if(qd == Dtop)
329*906943f9SDavid du Colombier sysfatal("fswrite: not for usbd /");
330*906943f9SDavid du Colombier qlock(&fslck);
331*906943f9SDavid du Colombier if(fs[qd] == nil){
332*906943f9SDavid du Colombier qunlock(&fslck);
333*906943f9SDavid du Colombier werrstr(Eio);
334*906943f9SDavid du Colombier return -1;
335*906943f9SDavid du Colombier }
336*906943f9SDavid du Colombier dev = fs[qd]->dev;
337*906943f9SDavid du Colombier if(dev != nil)
338*906943f9SDavid du Colombier incref(dev);
339*906943f9SDavid du Colombier xfswrite = fs[qd]->write;
340*906943f9SDavid du Colombier qunlock(&fslck);
341*906943f9SDavid du Colombier rc = xfswrite(fs[qd], fid, data, cnt, off);
342*906943f9SDavid du Colombier if(dev != nil)
343*906943f9SDavid du Colombier closedev(dev);
344*906943f9SDavid du Colombier return rc;
345*906943f9SDavid du Colombier }
346*906943f9SDavid du Colombier
347*906943f9SDavid du Colombier
348*906943f9SDavid du Colombier static void
fsclunk(Usbfs *,Fid * fid)349*906943f9SDavid du Colombier fsclunk(Usbfs*, Fid* fid)
350*906943f9SDavid du Colombier {
351*906943f9SDavid du Colombier int qd;
352*906943f9SDavid du Colombier Dev *dev;
353*906943f9SDavid du Colombier void (*xfsclunk)(Usbfs *fs, Fid *f);
354*906943f9SDavid du Colombier
355*906943f9SDavid du Colombier dev = nil;
356*906943f9SDavid du Colombier qd = qiddev(fid->qid.path);
357*906943f9SDavid du Colombier qlock(&fslck);
358*906943f9SDavid du Colombier if(qd != Dtop && fs[qd] != nil){
359*906943f9SDavid du Colombier dev=fs[qd]->dev;
360*906943f9SDavid du Colombier if(dev != nil)
361*906943f9SDavid du Colombier incref(dev);
362*906943f9SDavid du Colombier xfsclunk = fs[qd]->clunk;
363*906943f9SDavid du Colombier }else
364*906943f9SDavid du Colombier xfsclunk = nil;
365*906943f9SDavid du Colombier qunlock(&fslck);
366*906943f9SDavid du Colombier if(xfsclunk != nil){
367*906943f9SDavid du Colombier xfsclunk(fs[qd], fid);
368*906943f9SDavid du Colombier }
369*906943f9SDavid du Colombier if(dev != nil)
370*906943f9SDavid du Colombier closedev(dev);
371*906943f9SDavid du Colombier }
372*906943f9SDavid du Colombier
373*906943f9SDavid du Colombier static int
fsstat(Usbfs *,Qid qid,Dir * d)374*906943f9SDavid du Colombier fsstat(Usbfs*, Qid qid, Dir *d)
375*906943f9SDavid du Colombier {
376*906943f9SDavid du Colombier int qd;
377*906943f9SDavid du Colombier int rc;
378*906943f9SDavid du Colombier Dev *dev;
379*906943f9SDavid du Colombier int (*xfsstat)(Usbfs *fs, Qid q, Dir *d);
380*906943f9SDavid du Colombier
381*906943f9SDavid du Colombier qd = qiddev(qid.path);
382*906943f9SDavid du Colombier if(qd == Dtop){
383*906943f9SDavid du Colombier d->qid = qid;
384*906943f9SDavid du Colombier d->name = "usb";
385*906943f9SDavid du Colombier d->length = 0;
386*906943f9SDavid du Colombier d->mode = 0555|DMDIR;
387*906943f9SDavid du Colombier return 0;
388*906943f9SDavid du Colombier }
389*906943f9SDavid du Colombier qlock(&fslck);
390*906943f9SDavid du Colombier if(fs[qd] == nil){
391*906943f9SDavid du Colombier qunlock(&fslck);
392*906943f9SDavid du Colombier werrstr(Eio);
393*906943f9SDavid du Colombier return -1;
394*906943f9SDavid du Colombier }
395*906943f9SDavid du Colombier xfsstat = fs[qd]->stat;
396*906943f9SDavid du Colombier dev = fs[qd]->dev;
397*906943f9SDavid du Colombier if(dev != nil)
398*906943f9SDavid du Colombier incref(dev);
399*906943f9SDavid du Colombier qunlock(&fslck);
400*906943f9SDavid du Colombier rc = xfsstat(fs[qd], qid, d);
401*906943f9SDavid du Colombier if(dev != nil)
402*906943f9SDavid du Colombier closedev(dev);
403*906943f9SDavid du Colombier return rc;
404*906943f9SDavid du Colombier }
405*906943f9SDavid du Colombier
406*906943f9SDavid du Colombier Usbfs usbdirfs =
407*906943f9SDavid du Colombier {
408*906943f9SDavid du Colombier .walk = fswalk,
409*906943f9SDavid du Colombier .clone = fsclone,
410*906943f9SDavid du Colombier .clunk = fsclunk,
411*906943f9SDavid du Colombier .open = fsopen,
412*906943f9SDavid du Colombier .read = fsread,
413*906943f9SDavid du Colombier .write = fswrite,
414*906943f9SDavid du Colombier .stat = fsstat,
415*906943f9SDavid du Colombier .end = fsend,
416*906943f9SDavid du Colombier };
417*906943f9SDavid du Colombier
418