14 fidLock(Fid* fid, int flags)
16 if(flags & FidFWlock){
24 * Callers of file* routines are expected to lock fsys->fs->elk
25 * before making any calls in order to make sure the epoch doesn't
26 * change underfoot. With the exception of Tversion and Tattach,
27 * that implies all 9P functions need to lock on entry and unlock
28 * on exit. Fortunately, the general case is the 9P functions do
29 * fidGet on entry and fidPut on exit, so this is a convenient place
31 * No fsys->fs->elk lock is required if the fid is being created
32 * (Tauth, Tattach and Twalk). FidFCreate is always accompanied by
33 * FidFWlock so the setting and testing of FidFCreate here and in
34 * fidUnlock below is always done under fid->lock.
35 * A side effect is that fidFree is called with the fid locked, and
36 * must call fidUnlock only after it has disposed of any File
37 * resources still held.
39 if(!(flags & FidFCreate))
40 fsysFsRlock(fid->fsys);
46 if(!(fid->flags & FidFCreate))
47 fsysFsRUnlock(fid->fsys);
48 if(fid->flags & FidFWlock){
64 fbox.free = fid->hash;
68 fid = vtmallocz(sizeof(Fid));
77 fid->open = FidOCreate;
78 assert(fid->fsys == nil);
79 assert(fid->file == nil);
80 fid->qid = (Qid){0, 0, 0};
81 assert(fid->uid == nil);
82 assert(fid->uname == nil);
83 assert(fid->db == nil);
84 assert(fid->excl == nil);
85 assert(fid->rpc == nil);
86 assert(fid->cuname == nil);
87 fid->hash = fid->next = fid->prev = nil;
96 fileDecRef(fid->file);
109 if(fid->uname != nil){
116 close(fid->rpc->afd);
117 auth_freerpc(fid->rpc);
120 if(fid->fsys != nil){
124 if(fid->cuname != nil){
132 fid->hash = fbox.free;
147 assert(fid->ref == 0);
149 hash = &fid->con->fidhash[fid->fidno % NFidHash];
150 for(fp = *hash; fp != nil; fp = fp->hash){
160 fid->prev->next = fid->next;
162 fid->con->fhead = fid->next;
164 fid->next->prev = fid->prev;
166 fid->con->ftail = fid->prev;
167 fid->prev = fid->next = nil;
173 fidGet(Con* con, u32int fidno, int flags)
180 hash = &con->fidhash[fidno % NFidHash];
181 qlock(&con->fidlock);
182 for(fid = *hash; fid != nil; fid = fid->hash){
183 if(fid->fidno != fidno)
187 * Already in use is an error
188 * when called from attach, clone or walk.
190 if(flags & FidFCreate){
191 qunlock(&con->fidlock);
192 werrstr("%s: fid 0x%ud in use", argv0, fidno);
196 qunlock(&con->fidlock);
199 if((fid->open & FidOCreate) || fid->fidno == NOFID){
201 werrstr("%s: fid invalid", argv0);
207 if((flags & FidFCreate) && (fid = fidAlloc()) != nil){
208 assert(flags & FidFWlock);
215 if(con->ftail != nil){
216 fid->prev = con->ftail;
217 con->ftail->next = fid;
227 qunlock(&con->fidlock);
230 * The FidOCreate flag is used to prevent any
231 * accidental access to the Fid between unlocking the
232 * hash and acquiring the Fid lock for return.
235 fid->open &= ~FidOCreate;
238 qunlock(&con->fidlock);
240 werrstr("%s: fid not found", argv0);
247 qlock(&fid->con->fidlock);
248 assert(fid->ref > 0);
250 qunlock(&fid->con->fidlock);
252 if(fid->ref == 0 && fid->fidno == NOFID){
262 assert(fid->flags & FidFWlock);
264 qlock(&fid->con->fidlock);
265 assert(fid->ref > 0);
269 qunlock(&fid->con->fidlock);
272 /* not reached - fidUnHash requires ref == 0 */
280 fidClunkAll(Con* con)
285 qlock(&con->fidlock);
286 while(con->fhead != nil){
287 fidno = con->fhead->fidno;
288 qunlock(&con->fidlock);
289 if((fid = fidGet(con, fidno, FidFWlock)) != nil)
291 qlock(&con->fidlock);
293 qunlock(&con->fidlock);