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