1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <thread.h> 5 #include <9p.h> 6 #include "dat.h" 7 #include "fns.h" 8 9 10 static Xfs *xhead; 11 static Xfile *freelist; 12 static Lock xlock, freelock; 13 14 int client; 15 16 Xfs * 17 getxfs(char *name) 18 { 19 int fd; 20 Dir *dir; 21 Xfs *xf, *fxf; 22 23 if(name==0 || name[0]==0) 24 name = deffile; 25 if(name == 0){ 26 errno = Enofilsys; 27 return 0; 28 } 29 fd = open(name, rdonly ? OREAD : ORDWR); 30 if(fd < 0){ 31 errno = Enonexist; 32 return 0; 33 } 34 if((dir = dirfstat(fd)) == 0){ 35 errno = Eio; 36 close(fd); 37 return 0; 38 } 39 lock(&xlock); 40 for(fxf=0, xf=xhead; xf; xf=xf->next){ 41 if(xf->ref == 0){ 42 if(fxf == 0) 43 fxf = xf; 44 continue; 45 } 46 if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers) 47 continue; 48 if(strcmp(xf->name, name) != 0 || xf->dev < 0) 49 continue; 50 chat("incref \"%s\", dev=%d...", xf->name, xf->dev); 51 ++xf->ref; 52 unlock(&xlock); 53 close(fd); 54 free(dir); 55 return xf; 56 } 57 if(fxf==0){ 58 fxf = malloc(sizeof(Xfs)); 59 if(fxf==0){ 60 unlock(&xlock); 61 close(fd); 62 free(dir); 63 errno = Enomem; 64 return 0; 65 } 66 fxf->next = xhead; 67 xhead = fxf; 68 } 69 chat("alloc \"%s\", dev=%d...", name, fd); 70 fxf->name = strdup(name); 71 fxf->ref = 1; 72 fxf->qid = dir->qid; 73 fxf->dev = fd; 74 fxf->fmt = 0; 75 fxf->ptr = 0; 76 free(dir); 77 if( ext2fs(fxf)<0 ){ 78 xhead = fxf->next; 79 free(fxf); 80 unlock(&xlock); 81 return 0; 82 } 83 unlock(&xlock); 84 return fxf; 85 } 86 87 void 88 refxfs(Xfs *xf, int delta) 89 { 90 lock(&xlock); 91 xf->ref += delta; 92 if(xf->ref == 0){ 93 /*mchat("free \"%s\", dev=%d...", xf->name, xf->dev); 94 dumpbuf();*/ 95 CleanSuper(xf); 96 syncbuf(); 97 free(xf->name); 98 purgebuf(xf); 99 if(xf->dev >= 0){ 100 close(xf->dev); 101 xf->dev = -1; 102 } 103 } 104 unlock(&xlock); 105 } 106 107 Xfile * 108 xfile(Fid *fid, int flag) 109 { 110 Xfile *f; 111 112 f = (Xfile*)fid->aux; 113 switch(flag){ 114 default: 115 panic("xfile"); 116 case Asis: 117 return (f && f->xf && f->xf->dev < 0) ? 0 : f; 118 case Clean: 119 if (f) chat("Clean and fid->aux already exists\n"); 120 break; 121 case Clunk: 122 if(f){ 123 clean(f); 124 lock(&freelock); 125 f->next = freelist; 126 freelist = f; 127 unlock(&freelock); 128 fid->aux = 0; 129 } 130 return 0; 131 } 132 if(f) 133 return clean(f); 134 lock(&freelock); 135 if(f = freelist){ /* assign = */ 136 freelist = f->next; 137 unlock(&freelock); 138 } else { 139 unlock(&freelock); 140 f = malloc(sizeof(Xfile)); 141 } 142 fid->aux = f; 143 f->fid = fid->fid; 144 f->client = client; 145 f->xf = 0; 146 f->ptr = 0; 147 f->root = 0; 148 return f; 149 } 150 Xfile * 151 clean(Xfile *f) 152 { 153 if(f->xf && f->root){ 154 refxfs(f->xf, -1); 155 f->xf = 0; 156 } 157 f->xf = 0; 158 f->root = 0; 159 f->dirindex = 0; 160 return f; 161 } 162