diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/ext2srv/xfile.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/ext2srv/xfile.c')
-rwxr-xr-x | sys/src/cmd/ext2srv/xfile.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/sys/src/cmd/ext2srv/xfile.c b/sys/src/cmd/ext2srv/xfile.c new file mode 100755 index 000000000..2950398a1 --- /dev/null +++ b/sys/src/cmd/ext2srv/xfile.c @@ -0,0 +1,161 @@ +#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; +} |