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; }