Keep children in create order.
[rsc] --rw-rw-r-- M 431581 glenda sys 6695 Oct 29 10:54 sys/src/lib9p/file.c
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:10,20 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:10,27
* Always lock child then parent, never parent then child.
* If holding the free file lock, do not lock any Files.
*/
- struct Filelist {
+ struct Filelist
+ {
File *f;
Filelist *link;
};
+ struct Readdir
+ {
+ File *dir;
+ Filelist *fl;
+ };
+
static QLock filelk;
static File *freefilelist;
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:67,72 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:74,112
qunlock(&filelk);
}
+ static void
+ cleanfilelist(File *f)
+ {
+ Filelist **l;
+ Filelist *fl;
+
+ /*
+ * can't delete filelist structures while there
+ * are open readers of this directory, because
+ * they might have references to the structures.
+ * instead, just leave the empty refs in the list
+ * until there is no activity and then clean up.
+ */
+ if(f->readers.ref != 0)
+ return;
+ if(f->nxchild == 0)
+ return;
+
+ /*
+ * no dir readers, file is locked, and
+ * there are empty entries in the file list.
+ * clean them out.
+ */
+ for(l=&f->filelist; fl=*l; ){
+ if(fl->f == nil){
+ *l = (*l)->link;
+ free(fl);
+ }else
+ l = &(*l)->link;
+ }
+ f->nxchild = 0;
+ }
+
void
closefile(File *f)
{
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:125,134 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:165,177
fl->f = nil;
fp->nchild--;
+ fp->nxchild++;
f->parent = nil;
- wunlock(fp);
wunlock(f);
+ cleanfilelist(fp);
+ wunlock(fp);
+
closefile(fp); /* reference from child */
closefile(f); /* reference from tree */
closefile(f);
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:139,145 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:182,188
createfile(File *fp, char *name, char *uid, ulong perm, void *aux)
{
File *f;
- Filelist *fl, *freel;
+ Filelist **l, *fl;
Tree *t;
if((fp->qid.type&QTDIR) == 0){
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:147,170 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:190,215
return nil;
}
- freel = nil;
wlock(fp);
- for(fl=fp->filelist; fl; fl=fl->link){
- if(fl->f == nil)
- freel = fl;
- else if(strcmp(fl->f->name, name) == 0){
+ /*
+ * We might encounter blank spots along the
+ * way due to deleted files that have not yet
+ * been flushed from the file list. Don't reuse
+ * those - some apps (e.g., omero) depend on
+ * the file order reflecting creation order.
+ * Always create at the end of the list.
+ */
+ for(l=&fp->filelist; fl=*l; l=&fl->link){
+ if(fl->f && strcmp(fl->f->name, name) == 0){
wunlock(fp);
werrstr("file already exists");
return nil;
}
}
+
+ fl = emalloc9p(sizeof *fl);
+ *l = fl;
- if(freel == nil){
- freel = emalloc9p(sizeof *freel);
- freel->link = fp->filelist;
- fp->filelist = freel;
- }
-
f = allocfile();
f->name = estrdup9p(name);
f->uid = estrdup9p(uid ? uid : fp->uid);
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:193,199 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:238,244
incref(f); /* being returned */
incref(f); /* for the tree */
- freel->f = f;
+ fl->f = f;
fp->nchild++;
wunlock(fp);
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:245,251 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:290,296
else
nexts = s+strlen(s);
nf = walkfile1(f, s);
- decref(f);
+ closefile(f);
f = nf;
if(f == nil)
break;
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:323,332 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:368,373
free(t);
}
- struct Readdir {
- Filelist *fl;
- };
-
Readdir*
opendirfile(File *dir)
{
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:340,349 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:381,394
r = emalloc9p(sizeof(*r));
/*
- * This reference won't go away while we're using it
- * since we are dir->rdir.
+ * This reference won't go away while we're
+ * using it because file list entries are not freed
+ * until the directory is removed and all refs to
+ * it (our fid is one!) have gone away.
*/
r->fl = dir->filelist;
+ r->dir = dir;
+ incref(&dir->readers);
runlock(dir);
return r;
}
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/file.c:367,371 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/file.c:412,421
void
closedirfile(Readdir *r)
{
+ if(decref(&r->dir->readers) == 0){
+ wlock(r->dir);
+ cleanfilelist(r->dir);
+ wunlock(r->dir);
+ }
free(r);
}
[rsc] --rw-rw-r-- M 431581 glenda sys 16871 Oct 29 10:54 sys/src/lib9p/srv.c
/n/sourcesdump/2005/1029/plan9/sys/src/lib9p/srv.c:218,224 -
/n/sourcesdump/2005/1030/plan9/sys/src/lib9p/srv.c:218,224
r->fid->uid = estrdup9p(r->ifcall.uname);
if(srv->tree){
r->fid->file = srv->tree->root;
- /* BUG? incref(r->fid->file) ??? */
+ incref(r->fid->file);
r->ofcall.qid = r->fid->file->qid;
r->fid->qid = r->ofcall.qid;
}
|