/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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;} voidrefxfs(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;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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;
}