123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- #include <u.h>
- #include <libc.h>
- #include <fcall.h>
- #include <thread.h>
- #include <9p.h>
- #include "dat.h"
- #include "fns.h"
- static Xfs *xhead;
- static Xfile *freelist;
- static Lock xlock, freelock;
- int client;
- Xfs *
- getxfs(char *name)
- {
- int fd;
- Dir *dir;
- Xfs *xf, *fxf;
- if(name==0 || name[0]==0)
- name = deffile;
- if(name == 0){
- errno = Enofilsys;
- return 0;
- }
- fd = open(name, rdonly ? OREAD : ORDWR);
- if(fd < 0){
- errno = Enonexist;
- return 0;
- }
- if((dir = dirfstat(fd)) == 0){
- errno = Eio;
- close(fd);
- return 0;
- }
- lock(&xlock);
- for(fxf=0, xf=xhead; xf; xf=xf->next){
- if(xf->ref == 0){
- if(fxf == 0)
- fxf = xf;
- continue;
- }
- if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers)
- continue;
- if(strcmp(xf->name, name) != 0 || xf->dev < 0)
- continue;
- chat("incref \"%s\", dev=%d...", xf->name, xf->dev);
- ++xf->ref;
- unlock(&xlock);
- close(fd);
- free(dir);
- return xf;
- }
- if(fxf==0){
- fxf = malloc(sizeof(Xfs));
- if(fxf==0){
- unlock(&xlock);
- close(fd);
- free(dir);
- errno = Enomem;
- return 0;
- }
- fxf->next = xhead;
- xhead = fxf;
- }
- chat("alloc \"%s\", dev=%d...", name, fd);
- fxf->name = strdup(name);
- fxf->ref = 1;
- fxf->qid = dir->qid;
- fxf->dev = fd;
- fxf->fmt = 0;
- fxf->ptr = 0;
- free(dir);
- if( ext2fs(fxf)<0 ){
- xhead = fxf->next;
- free(fxf);
- unlock(&xlock);
- return 0;
- }
- unlock(&xlock);
- return fxf;
- }
- void
- refxfs(Xfs *xf, int delta)
- {
- lock(&xlock);
- xf->ref += delta;
- if(xf->ref == 0){
- /*mchat("free \"%s\", dev=%d...", xf->name, xf->dev);
- dumpbuf();*/
- CleanSuper(xf);
- syncbuf();
- free(xf->name);
- purgebuf(xf);
- if(xf->dev >= 0){
- close(xf->dev);
- xf->dev = -1;
- }
- }
- unlock(&xlock);
- }
- Xfile *
- xfile(Fid *fid, int flag)
- {
- Xfile *f;
- f = (Xfile*)fid->aux;
- switch(flag){
- default:
- panic("xfile");
- case Asis:
- return (f && f->xf && f->xf->dev < 0) ? 0 : f;
- case Clean:
- if (f) chat("Clean and fid->aux already exists\n");
- break;
- case Clunk:
- if(f){
- clean(f);
- lock(&freelock);
- f->next = freelist;
- freelist = f;
- unlock(&freelock);
- fid->aux = 0;
- }
- return 0;
- }
- if(f)
- return clean(f);
- lock(&freelock);
- if(f = freelist){ /* assign = */
- freelist = f->next;
- unlock(&freelock);
- } else {
- unlock(&freelock);
- f = malloc(sizeof(Xfile));
- }
- fid->aux = f;
- f->fid = fid->fid;
- f->client = client;
- f->xf = 0;
- f->ptr = 0;
- f->root = 0;
- return f;
- }
- Xfile *
- clean(Xfile *f)
- {
- if(f->xf && f->root){
- refxfs(f->xf, -1);
- f->xf = 0;
- }
- f->xf = 0;
- f->root = 0;
- f->dirindex = 0;
- return f;
- }
|