Blame


1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
2 6f4d00ee 2013-09-23 0intro
3 6f4d00ee 2013-09-23 0intro #include "9.h"
4 6f4d00ee 2013-09-23 0intro
5 6f4d00ee 2013-09-23 0intro static struct {
6 4b576658 2013-09-23 0intro QLock lock;
7 6f4d00ee 2013-09-23 0intro
8 6f4d00ee 2013-09-23 0intro Fid* free;
9 6f4d00ee 2013-09-23 0intro int nfree;
10 6f4d00ee 2013-09-23 0intro int inuse;
11 6f4d00ee 2013-09-23 0intro } fbox;
12 6f4d00ee 2013-09-23 0intro
13 6f4d00ee 2013-09-23 0intro static void
14 6f4d00ee 2013-09-23 0intro fidLock(Fid* fid, int flags)
15 6f4d00ee 2013-09-23 0intro {
16 6f4d00ee 2013-09-23 0intro if(flags & FidFWlock){
17 4b576658 2013-09-23 0intro wlock(&fid->lock);
18 6f4d00ee 2013-09-23 0intro fid->flags = flags;
19 6f4d00ee 2013-09-23 0intro }
20 6f4d00ee 2013-09-23 0intro else
21 4b576658 2013-09-23 0intro rlock(&fid->lock);
22 6f4d00ee 2013-09-23 0intro
23 6f4d00ee 2013-09-23 0intro /*
24 6f4d00ee 2013-09-23 0intro * Callers of file* routines are expected to lock fsys->fs->elk
25 6f4d00ee 2013-09-23 0intro * before making any calls in order to make sure the epoch doesn't
26 6f4d00ee 2013-09-23 0intro * change underfoot. With the exception of Tversion and Tattach,
27 6f4d00ee 2013-09-23 0intro * that implies all 9P functions need to lock on entry and unlock
28 6f4d00ee 2013-09-23 0intro * on exit. Fortunately, the general case is the 9P functions do
29 6f4d00ee 2013-09-23 0intro * fidGet on entry and fidPut on exit, so this is a convenient place
30 6f4d00ee 2013-09-23 0intro * to do the locking.
31 6f4d00ee 2013-09-23 0intro * No fsys->fs->elk lock is required if the fid is being created
32 6f4d00ee 2013-09-23 0intro * (Tauth, Tattach and Twalk). FidFCreate is always accompanied by
33 6f4d00ee 2013-09-23 0intro * FidFWlock so the setting and testing of FidFCreate here and in
34 6f4d00ee 2013-09-23 0intro * fidUnlock below is always done under fid->lock.
35 6f4d00ee 2013-09-23 0intro * A side effect is that fidFree is called with the fid locked, and
36 6f4d00ee 2013-09-23 0intro * must call fidUnlock only after it has disposed of any File
37 6f4d00ee 2013-09-23 0intro * resources still held.
38 6f4d00ee 2013-09-23 0intro */
39 6f4d00ee 2013-09-23 0intro if(!(flags & FidFCreate))
40 6f4d00ee 2013-09-23 0intro fsysFsRlock(fid->fsys);
41 6f4d00ee 2013-09-23 0intro }
42 6f4d00ee 2013-09-23 0intro
43 6f4d00ee 2013-09-23 0intro static void
44 6f4d00ee 2013-09-23 0intro fidUnlock(Fid* fid)
45 6f4d00ee 2013-09-23 0intro {
46 6f4d00ee 2013-09-23 0intro if(!(fid->flags & FidFCreate))
47 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fid->fsys);
48 6f4d00ee 2013-09-23 0intro if(fid->flags & FidFWlock){
49 6f4d00ee 2013-09-23 0intro fid->flags = 0;
50 4b576658 2013-09-23 0intro wunlock(&fid->lock);
51 6f4d00ee 2013-09-23 0intro return;
52 6f4d00ee 2013-09-23 0intro }
53 4b576658 2013-09-23 0intro runlock(&fid->lock);
54 6f4d00ee 2013-09-23 0intro }
55 6f4d00ee 2013-09-23 0intro
56 6f4d00ee 2013-09-23 0intro static Fid*
57 6f4d00ee 2013-09-23 0intro fidAlloc(void)
58 6f4d00ee 2013-09-23 0intro {
59 6f4d00ee 2013-09-23 0intro Fid *fid;
60 6f4d00ee 2013-09-23 0intro
61 4b576658 2013-09-23 0intro qlock(&fbox.lock);
62 6f4d00ee 2013-09-23 0intro if(fbox.nfree > 0){
63 6f4d00ee 2013-09-23 0intro fid = fbox.free;
64 6f4d00ee 2013-09-23 0intro fbox.free = fid->hash;
65 6f4d00ee 2013-09-23 0intro fbox.nfree--;
66 6f4d00ee 2013-09-23 0intro }
67 6f4d00ee 2013-09-23 0intro else{
68 4b576658 2013-09-23 0intro fid = vtmallocz(sizeof(Fid));
69 6f4d00ee 2013-09-23 0intro }
70 6f4d00ee 2013-09-23 0intro fbox.inuse++;
71 4b576658 2013-09-23 0intro qunlock(&fbox.lock);
72 6f4d00ee 2013-09-23 0intro
73 6f4d00ee 2013-09-23 0intro fid->con = nil;
74 6f4d00ee 2013-09-23 0intro fid->fidno = NOFID;
75 6f4d00ee 2013-09-23 0intro fid->ref = 0;
76 6f4d00ee 2013-09-23 0intro fid->flags = 0;
77 6f4d00ee 2013-09-23 0intro fid->open = FidOCreate;
78 6f4d00ee 2013-09-23 0intro assert(fid->fsys == nil);
79 6f4d00ee 2013-09-23 0intro assert(fid->file == nil);
80 6f4d00ee 2013-09-23 0intro fid->qid = (Qid){0, 0, 0};
81 6f4d00ee 2013-09-23 0intro assert(fid->uid == nil);
82 6f4d00ee 2013-09-23 0intro assert(fid->uname == nil);
83 6f4d00ee 2013-09-23 0intro assert(fid->db == nil);
84 6f4d00ee 2013-09-23 0intro assert(fid->excl == nil);
85 6f4d00ee 2013-09-23 0intro assert(fid->rpc == nil);
86 6f4d00ee 2013-09-23 0intro assert(fid->cuname == nil);
87 6f4d00ee 2013-09-23 0intro fid->hash = fid->next = fid->prev = nil;
88 6f4d00ee 2013-09-23 0intro
89 6f4d00ee 2013-09-23 0intro return fid;
90 6f4d00ee 2013-09-23 0intro }
91 6f4d00ee 2013-09-23 0intro
92 6f4d00ee 2013-09-23 0intro static void
93 6f4d00ee 2013-09-23 0intro fidFree(Fid* fid)
94 6f4d00ee 2013-09-23 0intro {
95 6f4d00ee 2013-09-23 0intro if(fid->file != nil){
96 6f4d00ee 2013-09-23 0intro fileDecRef(fid->file);
97 6f4d00ee 2013-09-23 0intro fid->file = nil;
98 6f4d00ee 2013-09-23 0intro }
99 6f4d00ee 2013-09-23 0intro if(fid->db != nil){
100 6f4d00ee 2013-09-23 0intro dirBufFree(fid->db);
101 6f4d00ee 2013-09-23 0intro fid->db = nil;
102 6f4d00ee 2013-09-23 0intro }
103 6f4d00ee 2013-09-23 0intro fidUnlock(fid);
104 6f4d00ee 2013-09-23 0intro
105 6f4d00ee 2013-09-23 0intro if(fid->uid != nil){
106 4b576658 2013-09-23 0intro vtfree(fid->uid);
107 6f4d00ee 2013-09-23 0intro fid->uid = nil;
108 6f4d00ee 2013-09-23 0intro }
109 6f4d00ee 2013-09-23 0intro if(fid->uname != nil){
110 4b576658 2013-09-23 0intro vtfree(fid->uname);
111 6f4d00ee 2013-09-23 0intro fid->uname = nil;
112 6f4d00ee 2013-09-23 0intro }
113 6f4d00ee 2013-09-23 0intro if(fid->excl != nil)
114 6f4d00ee 2013-09-23 0intro exclFree(fid);
115 6f4d00ee 2013-09-23 0intro if(fid->rpc != nil){
116 6f4d00ee 2013-09-23 0intro close(fid->rpc->afd);
117 6f4d00ee 2013-09-23 0intro auth_freerpc(fid->rpc);
118 6f4d00ee 2013-09-23 0intro fid->rpc = nil;
119 6f4d00ee 2013-09-23 0intro }
120 6f4d00ee 2013-09-23 0intro if(fid->fsys != nil){
121 6f4d00ee 2013-09-23 0intro fsysPut(fid->fsys);
122 6f4d00ee 2013-09-23 0intro fid->fsys = nil;
123 6f4d00ee 2013-09-23 0intro }
124 6f4d00ee 2013-09-23 0intro if(fid->cuname != nil){
125 4b576658 2013-09-23 0intro vtfree(fid->cuname);
126 6f4d00ee 2013-09-23 0intro fid->cuname = nil;
127 6f4d00ee 2013-09-23 0intro }
128 6f4d00ee 2013-09-23 0intro
129 4b576658 2013-09-23 0intro qlock(&fbox.lock);
130 6f4d00ee 2013-09-23 0intro fbox.inuse--;
131 6f4d00ee 2013-09-23 0intro if(fbox.nfree < 10){
132 6f4d00ee 2013-09-23 0intro fid->hash = fbox.free;
133 6f4d00ee 2013-09-23 0intro fbox.free = fid;
134 6f4d00ee 2013-09-23 0intro fbox.nfree++;
135 6f4d00ee 2013-09-23 0intro }
136 6f4d00ee 2013-09-23 0intro else{
137 4b576658 2013-09-23 0intro vtfree(fid);
138 6f4d00ee 2013-09-23 0intro }
139 4b576658 2013-09-23 0intro qunlock(&fbox.lock);
140 6f4d00ee 2013-09-23 0intro }
141 6f4d00ee 2013-09-23 0intro
142 6f4d00ee 2013-09-23 0intro static void
143 6f4d00ee 2013-09-23 0intro fidUnHash(Fid* fid)
144 6f4d00ee 2013-09-23 0intro {
145 6f4d00ee 2013-09-23 0intro Fid *fp, **hash;
146 6f4d00ee 2013-09-23 0intro
147 6f4d00ee 2013-09-23 0intro assert(fid->ref == 0);
148 6f4d00ee 2013-09-23 0intro
149 6f4d00ee 2013-09-23 0intro hash = &fid->con->fidhash[fid->fidno % NFidHash];
150 6f4d00ee 2013-09-23 0intro for(fp = *hash; fp != nil; fp = fp->hash){
151 6f4d00ee 2013-09-23 0intro if(fp == fid){
152 6f4d00ee 2013-09-23 0intro *hash = fp->hash;
153 6f4d00ee 2013-09-23 0intro break;
154 6f4d00ee 2013-09-23 0intro }
155 6f4d00ee 2013-09-23 0intro hash = &fp->hash;
156 6f4d00ee 2013-09-23 0intro }
157 6f4d00ee 2013-09-23 0intro assert(fp == fid);
158 6f4d00ee 2013-09-23 0intro
159 6f4d00ee 2013-09-23 0intro if(fid->prev != nil)
160 6f4d00ee 2013-09-23 0intro fid->prev->next = fid->next;
161 6f4d00ee 2013-09-23 0intro else
162 6f4d00ee 2013-09-23 0intro fid->con->fhead = fid->next;
163 6f4d00ee 2013-09-23 0intro if(fid->next != nil)
164 6f4d00ee 2013-09-23 0intro fid->next->prev = fid->prev;
165 6f4d00ee 2013-09-23 0intro else
166 6f4d00ee 2013-09-23 0intro fid->con->ftail = fid->prev;
167 6f4d00ee 2013-09-23 0intro fid->prev = fid->next = nil;
168 6f4d00ee 2013-09-23 0intro
169 6f4d00ee 2013-09-23 0intro fid->con->nfid--;
170 6f4d00ee 2013-09-23 0intro }
171 6f4d00ee 2013-09-23 0intro
172 6f4d00ee 2013-09-23 0intro Fid*
173 6f4d00ee 2013-09-23 0intro fidGet(Con* con, u32int fidno, int flags)
174 6f4d00ee 2013-09-23 0intro {
175 6f4d00ee 2013-09-23 0intro Fid *fid, **hash;
176 6f4d00ee 2013-09-23 0intro
177 6f4d00ee 2013-09-23 0intro if(fidno == NOFID)
178 6f4d00ee 2013-09-23 0intro return nil;
179 6f4d00ee 2013-09-23 0intro
180 6f4d00ee 2013-09-23 0intro hash = &con->fidhash[fidno % NFidHash];
181 4b576658 2013-09-23 0intro qlock(&con->fidlock);
182 6f4d00ee 2013-09-23 0intro for(fid = *hash; fid != nil; fid = fid->hash){
183 6f4d00ee 2013-09-23 0intro if(fid->fidno != fidno)
184 6f4d00ee 2013-09-23 0intro continue;
185 6f4d00ee 2013-09-23 0intro
186 6f4d00ee 2013-09-23 0intro /*
187 6f4d00ee 2013-09-23 0intro * Already in use is an error
188 6f4d00ee 2013-09-23 0intro * when called from attach, clone or walk.
189 6f4d00ee 2013-09-23 0intro */
190 6f4d00ee 2013-09-23 0intro if(flags & FidFCreate){
191 4b576658 2013-09-23 0intro qunlock(&con->fidlock);
192 4b576658 2013-09-23 0intro werrstr("%s: fid 0x%ud in use", argv0, fidno);
193 6f4d00ee 2013-09-23 0intro return nil;
194 6f4d00ee 2013-09-23 0intro }
195 6f4d00ee 2013-09-23 0intro fid->ref++;
196 4b576658 2013-09-23 0intro qunlock(&con->fidlock);
197 6f4d00ee 2013-09-23 0intro
198 6f4d00ee 2013-09-23 0intro fidLock(fid, flags);
199 6f4d00ee 2013-09-23 0intro if((fid->open & FidOCreate) || fid->fidno == NOFID){
200 6f4d00ee 2013-09-23 0intro fidPut(fid);
201 4b576658 2013-09-23 0intro werrstr("%s: fid invalid", argv0);
202 6f4d00ee 2013-09-23 0intro return nil;
203 6f4d00ee 2013-09-23 0intro }
204 6f4d00ee 2013-09-23 0intro return fid;
205 6f4d00ee 2013-09-23 0intro }
206 6f4d00ee 2013-09-23 0intro
207 6f4d00ee 2013-09-23 0intro if((flags & FidFCreate) && (fid = fidAlloc()) != nil){
208 6f4d00ee 2013-09-23 0intro assert(flags & FidFWlock);
209 6f4d00ee 2013-09-23 0intro fid->con = con;
210 6f4d00ee 2013-09-23 0intro fid->fidno = fidno;
211 6f4d00ee 2013-09-23 0intro fid->ref = 1;
212 6f4d00ee 2013-09-23 0intro
213 6f4d00ee 2013-09-23 0intro fid->hash = *hash;
214 6f4d00ee 2013-09-23 0intro *hash = fid;
215 6f4d00ee 2013-09-23 0intro if(con->ftail != nil){
216 6f4d00ee 2013-09-23 0intro fid->prev = con->ftail;
217 6f4d00ee 2013-09-23 0intro con->ftail->next = fid;
218 6f4d00ee 2013-09-23 0intro }
219 6f4d00ee 2013-09-23 0intro else{
220 6f4d00ee 2013-09-23 0intro con->fhead = fid;
221 6f4d00ee 2013-09-23 0intro fid->prev = nil;
222 6f4d00ee 2013-09-23 0intro }
223 6f4d00ee 2013-09-23 0intro con->ftail = fid;
224 6f4d00ee 2013-09-23 0intro fid->next = nil;
225 6f4d00ee 2013-09-23 0intro
226 6f4d00ee 2013-09-23 0intro con->nfid++;
227 4b576658 2013-09-23 0intro qunlock(&con->fidlock);
228 6f4d00ee 2013-09-23 0intro
229 6f4d00ee 2013-09-23 0intro /*
230 6f4d00ee 2013-09-23 0intro * The FidOCreate flag is used to prevent any
231 6f4d00ee 2013-09-23 0intro * accidental access to the Fid between unlocking the
232 6f4d00ee 2013-09-23 0intro * hash and acquiring the Fid lock for return.
233 6f4d00ee 2013-09-23 0intro */
234 6f4d00ee 2013-09-23 0intro fidLock(fid, flags);
235 6f4d00ee 2013-09-23 0intro fid->open &= ~FidOCreate;
236 6f4d00ee 2013-09-23 0intro return fid;
237 6f4d00ee 2013-09-23 0intro }
238 4b576658 2013-09-23 0intro qunlock(&con->fidlock);
239 6f4d00ee 2013-09-23 0intro
240 4b576658 2013-09-23 0intro werrstr("%s: fid not found", argv0);
241 6f4d00ee 2013-09-23 0intro return nil;
242 6f4d00ee 2013-09-23 0intro }
243 6f4d00ee 2013-09-23 0intro
244 6f4d00ee 2013-09-23 0intro void
245 6f4d00ee 2013-09-23 0intro fidPut(Fid* fid)
246 6f4d00ee 2013-09-23 0intro {
247 4b576658 2013-09-23 0intro qlock(&fid->con->fidlock);
248 6f4d00ee 2013-09-23 0intro assert(fid->ref > 0);
249 6f4d00ee 2013-09-23 0intro fid->ref--;
250 4b576658 2013-09-23 0intro qunlock(&fid->con->fidlock);
251 6f4d00ee 2013-09-23 0intro
252 6f4d00ee 2013-09-23 0intro if(fid->ref == 0 && fid->fidno == NOFID){
253 6f4d00ee 2013-09-23 0intro fidFree(fid);
254 6f4d00ee 2013-09-23 0intro return;
255 6f4d00ee 2013-09-23 0intro }
256 6f4d00ee 2013-09-23 0intro fidUnlock(fid);
257 6f4d00ee 2013-09-23 0intro }
258 6f4d00ee 2013-09-23 0intro
259 6f4d00ee 2013-09-23 0intro void
260 6f4d00ee 2013-09-23 0intro fidClunk(Fid* fid)
261 6f4d00ee 2013-09-23 0intro {
262 6f4d00ee 2013-09-23 0intro assert(fid->flags & FidFWlock);
263 6f4d00ee 2013-09-23 0intro
264 4b576658 2013-09-23 0intro qlock(&fid->con->fidlock);
265 6f4d00ee 2013-09-23 0intro assert(fid->ref > 0);
266 6f4d00ee 2013-09-23 0intro fid->ref--;
267 6f4d00ee 2013-09-23 0intro fidUnHash(fid);
268 6f4d00ee 2013-09-23 0intro fid->fidno = NOFID;
269 4b576658 2013-09-23 0intro qunlock(&fid->con->fidlock);
270 6f4d00ee 2013-09-23 0intro
271 6f4d00ee 2013-09-23 0intro if(fid->ref > 0){
272 6f4d00ee 2013-09-23 0intro /* not reached - fidUnHash requires ref == 0 */
273 6f4d00ee 2013-09-23 0intro fidUnlock(fid);
274 6f4d00ee 2013-09-23 0intro return;
275 6f4d00ee 2013-09-23 0intro }
276 6f4d00ee 2013-09-23 0intro fidFree(fid);
277 6f4d00ee 2013-09-23 0intro }
278 6f4d00ee 2013-09-23 0intro
279 6f4d00ee 2013-09-23 0intro void
280 6f4d00ee 2013-09-23 0intro fidClunkAll(Con* con)
281 6f4d00ee 2013-09-23 0intro {
282 6f4d00ee 2013-09-23 0intro Fid *fid;
283 6f4d00ee 2013-09-23 0intro u32int fidno;
284 6f4d00ee 2013-09-23 0intro
285 4b576658 2013-09-23 0intro qlock(&con->fidlock);
286 6f4d00ee 2013-09-23 0intro while(con->fhead != nil){
287 6f4d00ee 2013-09-23 0intro fidno = con->fhead->fidno;
288 4b576658 2013-09-23 0intro qunlock(&con->fidlock);
289 6f4d00ee 2013-09-23 0intro if((fid = fidGet(con, fidno, FidFWlock)) != nil)
290 6f4d00ee 2013-09-23 0intro fidClunk(fid);
291 4b576658 2013-09-23 0intro qlock(&con->fidlock);
292 6f4d00ee 2013-09-23 0intro }
293 4b576658 2013-09-23 0intro qunlock(&con->fidlock);
294 6f4d00ee 2013-09-23 0intro }
295 6f4d00ee 2013-09-23 0intro
296 6f4d00ee 2013-09-23 0intro void
297 6f4d00ee 2013-09-23 0intro fidInit(void)
298 6f4d00ee 2013-09-23 0intro {
299 6f4d00ee 2013-09-23 0intro }