Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | /* | |
11 | * SGI specific vnodeops + other misc interface glue | |
12 | */ | |
13 | #include <afsconfig.h> | |
14 | #include "afs/param.h" | |
15 | ||
16 | ||
17 | #ifdef AFS_SGI62_ENV | |
18 | #include "afs/sysincludes.h" /* Standard vendor system headers */ | |
19 | #include "afsincludes.h" /* Afs-based standard headers */ | |
20 | #include "afs/afs_stats.h" /* statistics */ | |
21 | #include "sys/flock.h" | |
22 | #include "afs/nfsclient.h" | |
23 | ||
24 | /* AFSBSIZE must be at least the size of a page, else the client will hang. | |
25 | * For 64 bit platforms, the page size is more than 8K. | |
26 | */ | |
27 | #define AFSBSIZE _PAGESZ | |
28 | extern struct afs_exporter *root_exported; | |
29 | extern void afs_chkpgoob(vnode_t *, pgno_t); | |
30 | ||
31 | static void afs_strategy(); | |
32 | static int afs_xread(), afs_xwrite(); | |
33 | static int afs_xbmap(), afs_map(), afs_reclaim(); | |
34 | #ifndef AFS_SGI65_ENV | |
35 | static int afs_addmap(), afs_delmap(); | |
36 | #endif | |
37 | extern int afs_open(), afs_close(), afs_ioctl(), afs_getattr(), afs_setattr(); | |
38 | extern int afs_access(), afs_lookup(); | |
39 | extern int afs_create(), afs_remove(), afs_link(), afs_rename(); | |
40 | extern int afs_mkdir(), afs_rmdir(), afs_readdir(); | |
41 | extern int afs_symlink(), afs_readlink(), afs_fsync(), afs_fid(), | |
42 | afs_frlock(); | |
43 | static int afs_seek(OSI_VC_DECL(a), off_t b, off_t * c); | |
44 | #ifdef AFS_SGI64_ENV | |
45 | extern int afs_xinactive(); | |
46 | #else | |
47 | extern void afs_xinactive(); | |
48 | #endif | |
49 | ||
50 | extern void afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T b); | |
51 | extern void afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T b); | |
52 | ||
53 | extern int afs_fid2(); | |
54 | ||
55 | static int afsrwvp(struct vcache *avc, struct uio *uio, | |
56 | enum uio_rw rw, int ioflag, | |
57 | #ifdef AFS_SGI64_ENV | |
58 | struct cred *cr, struct flid *flp); | |
59 | #else | |
60 | struct cred *cr); | |
61 | #endif | |
62 | #ifdef MP | |
63 | static void mp_afs_rwlock(OSI_VN_DECL(a), AFS_RWLOCK_T b); | |
64 | static void mp_afs_rwunlock(OSI_VN_DECL(a), AFS_RWLOCK_T b); | |
65 | struct vnodeops afs_lockedvnodeops = | |
66 | #else | |
67 | struct vnodeops Afs_vnodeops = | |
68 | #endif | |
69 | { | |
70 | #ifdef AFS_SGI64_ENV | |
71 | #ifdef AFS_SGI65_ENV | |
72 | BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE), | |
73 | #else | |
74 | VNODE_POSITION_BASE, | |
75 | #endif | |
76 | #endif | |
77 | afs_open, | |
78 | afs_close, | |
79 | afs_xread, | |
80 | afs_xwrite, | |
81 | afs_ioctl, | |
82 | fs_setfl, | |
83 | afs_getattr, | |
84 | afs_setattr, | |
85 | afs_access, | |
86 | afs_lookup, | |
87 | afs_create, | |
88 | afs_remove, | |
89 | afs_link, | |
90 | afs_rename, | |
91 | afs_mkdir, | |
92 | afs_rmdir, | |
93 | afs_readdir, | |
94 | afs_symlink, | |
95 | afs_readlink, | |
96 | afs_fsync, | |
97 | afs_xinactive, | |
98 | afs_fid, | |
99 | afs_fid2, | |
100 | afs_rwlock, | |
101 | afs_rwunlock, | |
102 | afs_seek, | |
103 | fs_cmp, | |
104 | afs_frlock, | |
105 | fs_nosys, /* realvp */ | |
106 | afs_xbmap, | |
107 | afs_strategy, | |
108 | afs_map, | |
109 | #ifdef AFS_SGI65_ENV | |
110 | fs_noerr, /* addmap - devices only */ | |
111 | fs_noerr, /* delmap - devices only */ | |
112 | #else | |
113 | afs_addmap, | |
114 | afs_delmap, | |
115 | #endif | |
116 | fs_poll, /* poll */ | |
117 | fs_nosys, /* dump */ | |
118 | fs_pathconf, | |
119 | fs_nosys, /* allocstore */ | |
120 | fs_nosys, /* fcntl */ | |
121 | afs_reclaim, /* reclaim */ | |
122 | fs_nosys, /* attr_get */ | |
123 | fs_nosys, /* attr_set */ | |
124 | fs_nosys, /* attr_remove */ | |
125 | fs_nosys, /* attr_list */ | |
126 | #ifdef AFS_SGI64_ENV | |
127 | #ifdef AFS_SGI65_ENV | |
128 | fs_cover, | |
129 | (vop_link_removed_t) fs_noval, | |
130 | fs_vnode_change, | |
131 | fs_tosspages, | |
132 | fs_flushinval_pages, | |
133 | fs_flush_pages, | |
134 | fs_invalfree_pages, | |
135 | fs_pages_sethole, | |
136 | (vop_commit_t) fs_nosys, | |
137 | (vop_readbuf_t) fs_nosys, | |
138 | fs_strgetmsg, | |
139 | fs_strputmsg, | |
140 | #else | |
141 | fs_mount, | |
142 | #endif | |
143 | #endif | |
144 | }; | |
145 | ||
146 | #ifndef MP | |
147 | struct vnodeops *afs_ops = &Afs_vnodeops; | |
148 | #endif | |
149 | ||
150 | int | |
151 | afs_frlock(OSI_VN_DECL(vp), int cmd, struct flock *lfp, int flag, | |
152 | off_t offset, | |
153 | #ifdef AFS_SGI65_ENV | |
154 | vrwlock_t vrwlock, | |
155 | #endif | |
156 | cred_t * cr) | |
157 | { | |
158 | int error; | |
159 | OSI_VN_CONVERT(vp); | |
160 | #ifdef AFS_SGI65_ENV | |
161 | struct flid flid; | |
162 | int pid; | |
163 | get_current_flid(&flid); | |
164 | pid = flid.fl_pid; | |
165 | #endif | |
166 | ||
167 | /* | |
168 | * Since AFS doesn't support byte-wise locks (and simply | |
169 | * says yes! we handle byte locking locally only. | |
170 | * This makes lots of things work much better | |
171 | * XXX This doesn't properly handle moving from a | |
172 | * byte-wise lock up to a full file lock (we should | |
173 | * remove the byte locks ..) Of course neither did the | |
174 | * regular AFS way ... | |
175 | * | |
176 | * For GETLK we do a bit more - we first check any byte-wise | |
177 | * locks - if none then check for full AFS file locks | |
178 | */ | |
179 | if (cmd == F_GETLK || lfp->l_whence != 0 || lfp->l_start != 0 | |
180 | || (lfp->l_len != MAXEND && lfp->l_len != 0)) { | |
181 | AFS_RWLOCK(vp, VRWLOCK_WRITE); | |
182 | AFS_GUNLOCK(); | |
183 | #ifdef AFS_SGI65_ENV | |
184 | error = | |
185 | fs_frlock(OSI_VN_ARG(vp), cmd, lfp, flag, offset, vrwlock, cr); | |
186 | #else | |
187 | error = fs_frlock(vp, cmd, lfp, flag, offset, cr); | |
188 | #endif | |
189 | AFS_GLOCK(); | |
190 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
191 | if (error || cmd != F_GETLK) | |
192 | return error; | |
193 | if (lfp->l_type != F_UNLCK) | |
194 | /* found some blocking lock */ | |
195 | return 0; | |
196 | /* fall through to check for full AFS file locks */ | |
197 | } | |
198 | ||
199 | /* map BSD style to plain - we don't call reclock() | |
200 | * and its only there that the difference is important | |
201 | */ | |
202 | switch (cmd) { | |
203 | case F_GETLK: | |
204 | case F_RGETLK: | |
205 | break; | |
206 | case F_SETLK: | |
207 | case F_RSETLK: | |
208 | break; | |
209 | case F_SETBSDLK: | |
210 | cmd = F_SETLK; | |
211 | break; | |
212 | case F_SETLKW: | |
213 | case F_RSETLKW: | |
214 | break; | |
215 | case F_SETBSDLKW: | |
216 | cmd = F_SETLKW; | |
217 | break; | |
218 | default: | |
219 | return EINVAL; | |
220 | } | |
221 | ||
222 | AFS_GUNLOCK(); | |
223 | ||
224 | error = convoff(vp, lfp, 0, offset, SEEKLIMIT | |
225 | #ifdef AFS_SGI64_ENV | |
226 | , OSI_GET_CURRENT_CRED() | |
227 | #endif /* AFS_SGI64_ENV */ | |
228 | ); | |
229 | ||
230 | AFS_GLOCK(); | |
231 | if (!error) { | |
232 | #ifdef AFS_SGI65_ENV | |
233 | error = afs_lockctl(vp, lfp, cmd, cr, pid); | |
234 | #else | |
235 | error = afs_lockctl(vp, lfp, cmd, cr, OSI_GET_CURRENT_PID()); | |
236 | #endif | |
237 | } | |
238 | return error; | |
239 | } | |
240 | ||
241 | ||
242 | /* | |
243 | * We need to get the cache hierarchy right. | |
244 | * First comes the page cache - pages are hashed based on afs | |
245 | * vnode and offset. It is important to have things hashed here | |
246 | * for the VM/paging system to work. | |
247 | * Note that the paging system calls VOP_READ with the UIO_NOSPACE - | |
248 | * it simply requires that somehow the page is hashed | |
249 | * upon successful return. | |
250 | * This means in afs_read we | |
251 | * must call the 'chunk' code that handles page insertion. In order | |
252 | * to actually get the data, 'chunk' calls the VOP_STRATEGY routine. | |
253 | * This is basically the std afs_read routine - validating and | |
254 | * getting the info into the Dcache, then calling VOP_READ. | |
255 | * The only bad thing here is that by calling VOP_READ (and VOP_WRITE | |
256 | * to fill the cache) we will get 2 copies of these pages into the | |
257 | * page cache - one hashed on afs vnode and one on efs vnode. THis | |
258 | * is wasteful but does no harm. A potential solution involves | |
259 | * causing an ASYNC flush of the newly fetched cache data and | |
260 | * doing direct I/O on the read side.... | |
261 | */ | |
262 | /* ARGSUSED */ | |
263 | #ifdef AFS_SGI64_ENV | |
264 | static int | |
265 | afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr, flp) | |
266 | struct flid *flp; | |
267 | #else | |
268 | static int | |
269 | afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr) | |
270 | #endif | |
271 | OSI_VC_DECL(avc); | |
272 | struct uio *uiop; | |
273 | int ioflag; | |
274 | struct cred *cr; | |
275 | { | |
276 | int code; | |
277 | OSI_VC_CONVERT(avc); | |
278 | ||
279 | osi_Assert(avc->v.v_count > 0); | |
280 | if (avc->v.v_type != VREG) | |
281 | return EISDIR; | |
282 | ||
283 | #ifdef AFS_SGI64_ENV | |
284 | #ifdef AFS_SGI65_ENV | |
285 | if (!(ioflag & IO_ISLOCKED)) | |
286 | AFS_RWLOCK((vnode_t *) avc, VRWLOCK_READ); | |
287 | #endif | |
288 | code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr, flp); | |
289 | #ifdef AFS_SGI65_ENV | |
290 | if (!(ioflag & IO_ISLOCKED)) | |
291 | AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_READ); | |
292 | #endif | |
293 | #else | |
294 | code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr); | |
295 | #endif | |
296 | return code; | |
297 | } | |
298 | ||
299 | /* ARGSUSED */ | |
300 | #ifdef AFS_SGI64_ENV | |
301 | static int | |
302 | afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr, flp) | |
303 | struct flid *flp; | |
304 | #else | |
305 | static int | |
306 | afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr) | |
307 | #endif | |
308 | OSI_VC_DECL(avc); | |
309 | struct uio *uiop; | |
310 | int ioflag; | |
311 | struct cred *cr; | |
312 | { | |
313 | int code; | |
314 | OSI_VC_CONVERT(avc); | |
315 | ||
316 | osi_Assert(avc->v.v_count > 0); | |
317 | if (avc->v.v_type != VREG) | |
318 | return EISDIR; | |
319 | ||
320 | if (ioflag & IO_APPEND) | |
321 | uiop->uio_offset = avc->f.m.Length; | |
322 | #ifdef AFS_SGI64_ENV | |
323 | #ifdef AFS_SGI65_ENV | |
324 | if (!(ioflag & IO_ISLOCKED)) | |
325 | AFS_RWLOCK(((vnode_t *) avc), VRWLOCK_WRITE); | |
326 | #endif | |
327 | code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr, flp); | |
328 | #ifdef AFS_SGI65_ENV | |
329 | if (!(ioflag & IO_ISLOCKED)) | |
330 | AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE); | |
331 | #endif | |
332 | #else | |
333 | code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr); | |
334 | #endif | |
335 | return code; | |
336 | } | |
337 | ||
338 | static int prra = 0; | |
339 | static int prnra = 0; | |
340 | static int acchk = 0; | |
341 | static int acdrop = 0; | |
342 | ||
343 | static int | |
344 | afsrwvp(struct vcache *avc, struct uio *uio, enum uio_rw rw, | |
345 | int ioflag, | |
346 | #ifdef AFS_SGI64_ENV | |
347 | struct cred *cr, struct flid *flp) | |
348 | #else | |
349 | struct cred *cr) | |
350 | #endif | |
351 | { | |
352 | struct vnode *vp = AFSTOV(avc); | |
353 | struct buf *bp; | |
354 | daddr_t bn; | |
355 | off_t acnt, cnt; | |
356 | off_t off, newoff; | |
357 | off_t bsize, rem, len; | |
358 | int error; | |
359 | struct bmapval bmv[2]; | |
360 | int nmaps, didFakeOpen = 0; | |
361 | struct vrequest treq; | |
362 | struct dcache *tdc; | |
363 | int counter = 0; | |
364 | ||
365 | osi_Assert((valusema(&avc->vc_rwlock) <= 0) | |
366 | && (OSI_GET_LOCKID() == avc->vc_rwlockid)); | |
367 | ||
368 | ||
369 | newoff = uio->uio_resid + uio->uio_offset; | |
370 | if (uio->uio_resid <= 0) { | |
371 | return (0); | |
372 | } | |
373 | if (uio->uio_offset < 0 || newoff < 0) { | |
374 | return (EINVAL); | |
375 | } | |
376 | if (ioflag & IO_DIRECT) | |
377 | return EINVAL; | |
378 | ||
379 | if (rw == UIO_WRITE && vp->v_type == VREG && newoff > uio->uio_limit) { | |
380 | return (EFBIG); | |
381 | } | |
382 | ||
383 | afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, avc, | |
384 | ICL_TYPE_INT32, ioflag, ICL_TYPE_INT32, rw, ICL_TYPE_INT32, 0); | |
385 | ||
386 | /* get a validated vcache entry */ | |
387 | error = afs_InitReq(&treq, cr); | |
388 | if (error) | |
389 | return afs_CheckCode(error, NULL, 63); | |
390 | ||
391 | error = afs_VerifyVCache(avc, &treq); | |
392 | if (error) | |
393 | return afs_CheckCode(error, &treq, 51); | |
394 | ||
395 | /* | |
396 | * flush any stale pages - this will unmap | |
397 | * and invalidate all pages for vp (NOT writing them back!) | |
398 | */ | |
399 | osi_FlushPages(avc, cr); | |
400 | ||
401 | if (cr && AFS_NFSXLATORREQ(cr) && rw == UIO_READ) { | |
402 | if (!afs_AccessOK | |
403 | (avc, PRSFS_READ, &treq, | |
404 | CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) | |
405 | return EACCES; | |
406 | } | |
407 | /* | |
408 | * To handle anonymous calls to VOP_STRATEGY from afs_sync/sync/bdflush | |
409 | * we need better than the callers credentials. So we squirrel away | |
410 | * the last writers credentials | |
411 | */ | |
412 | if (rw == UIO_WRITE || (rw == UIO_READ && avc->cred == NULL)) { | |
413 | ObtainWriteLock(&avc->lock, 92); | |
414 | if (avc->cred) | |
415 | crfree(avc->cred); | |
416 | crhold(cr); | |
417 | avc->cred = cr; | |
418 | ReleaseWriteLock(&avc->lock); | |
419 | } | |
420 | ||
421 | /* | |
422 | * We have to bump the open/exwriters field here | |
423 | * courtesy of the nfs xlator | |
424 | * because there're no open/close nfs rpc's to call our afs_open/close. | |
425 | */ | |
426 | if (root_exported && rw == UIO_WRITE) { | |
427 | ObtainWriteLock(&avc->lock, 234); | |
428 | if (root_exported) { | |
429 | didFakeOpen = 1; | |
430 | afs_FakeOpen(avc); | |
431 | } | |
432 | ReleaseWriteLock(&avc->lock); | |
433 | } | |
434 | error = 0; | |
435 | ||
436 | if (rw == UIO_WRITE) { | |
437 | ObtainWriteLock(&avc->lock, 330); | |
438 | avc->f.states |= CDirty; | |
439 | ReleaseWriteLock(&avc->lock); | |
440 | } | |
441 | ||
442 | AFS_GUNLOCK(); | |
443 | ||
444 | do { | |
445 | /* If v_dpages is set SGI 5.3 will convert those pages to | |
446 | * B_DELWRI in chunkread and getchunk. Write the pages out | |
447 | * before we trigger that behavior. For 6.1, dirty pages stay | |
448 | * around too long and we should get rid of them as quickly | |
449 | * as possible. | |
450 | */ | |
451 | while (VN_GET_DPAGES(vp)) | |
452 | pdflush(vp, 0); | |
453 | ||
454 | if (avc->vc_error) { | |
455 | error = avc->vc_error; | |
456 | break; | |
457 | } | |
458 | bsize = AFSBSIZE; /* why not?? */ | |
459 | off = uio->uio_offset % bsize; | |
460 | bn = BTOBBT(uio->uio_offset - off); | |
461 | /* | |
462 | * decrease bsize - otherwise we will | |
463 | * get 'extra' pages in the cache for this | |
464 | * vnode that we would need to flush when | |
465 | * calling e.g. ptossvp. | |
466 | * So we can use Length in ptossvp, | |
467 | * we make sure we never go more than to the file size | |
468 | * rounded up to a page boundary. | |
469 | * That doesn't quite work, since we may get a page hashed to | |
470 | * the vnode w/o updating the length. Thus we always use | |
471 | * MAXLONG in ptossvp to be safe. | |
472 | */ | |
473 | if (rw == UIO_READ) { | |
474 | /* | |
475 | * read/paging in a normal file | |
476 | */ | |
477 | rem = avc->f.m.Length - uio->uio_offset; | |
478 | if (rem <= 0) | |
479 | /* EOF */ | |
480 | break; | |
481 | /* | |
482 | * compute minimum of rest of block and rest of file | |
483 | */ | |
484 | cnt = MIN(bsize - off, rem); | |
485 | osi_Assert((off + cnt) <= bsize); | |
486 | bsize = ctob(btoc(off + cnt)); | |
487 | len = BTOBBT(bsize); | |
488 | nmaps = 1; | |
489 | bmv[0].bn = bmv[0].offset = bn; | |
490 | bmv[0].length = len; | |
491 | bmv[0].bsize = bsize; | |
492 | bmv[0].pboff = off; | |
493 | bmv[0].pbsize = MIN(cnt, uio->uio_resid); | |
494 | bmv[0].eof = 0; | |
495 | #ifdef AFS_SGI64_ENV | |
496 | bmv[0].pbdev = vp->v_rdev; | |
497 | bmv[0].pmp = uio->uio_pmp; | |
498 | #endif | |
499 | osi_Assert(cnt > 0); | |
500 | /* | |
501 | * initiate read-ahead if it looks like | |
502 | * we are reading sequentially OR they want | |
503 | * more than one 'bsize' (==AFSBSIZE) worth | |
504 | * XXXHack - to avoid DELWRI buffers we can't | |
505 | * do read-ahead on any file that has potentially | |
506 | * dirty mmap pages. | |
507 | */ | |
508 | if ((avc->lastr + BTOBB(AFSBSIZE) == bn | |
509 | || uio->uio_resid > AFSBSIZE) | |
510 | #ifdef AFS_SGI61_ENV | |
511 | && (!AFS_VN_MAPPED(vp)) | |
512 | #else /* AFS_SGI61_ENV */ | |
513 | && ((vp->v_flag & VWASMAP) == 0) | |
514 | #endif /* AFS_SGI61_ENV */ | |
515 | ) { | |
516 | rem -= cnt; | |
517 | if (rem > 0) { | |
518 | bsize = AFSBSIZE; | |
519 | bmv[1].bn = bmv[1].offset = bn + len; | |
520 | osi_Assert((BBTOB(bn + len) % bsize) == 0); | |
521 | acnt = MIN(bsize, rem); | |
522 | bsize = ctob(btoc(acnt)); | |
523 | len = BTOBBT(bsize); | |
524 | nmaps = 2; | |
525 | bmv[1].length = len; | |
526 | bmv[1].eof = 0; | |
527 | bmv[1].bsize = bsize; | |
528 | bmv[1].pboff = 0; | |
529 | bmv[1].pbsize = acnt; | |
530 | #ifdef AFS_SGI64_ENV | |
531 | bmv[1].pmp = uio->uio_pmp; | |
532 | bmv[1].pbdev = vp->v_rdev; | |
533 | #endif | |
534 | } | |
535 | } | |
536 | #ifdef DEBUG | |
537 | else if (prnra) | |
538 | printf | |
539 | ("NRA:vp 0x%x lastr %d bn %d len %d cnt %d bsize %d rem %d resid %d\n", | |
540 | vp, avc->lastr, bn, len, cnt, bsize, rem, | |
541 | uio->uio_resid); | |
542 | #endif | |
543 | ||
544 | avc->lastr = bn; | |
545 | bp = chunkread(vp, bmv, nmaps, cr); | |
546 | /* | |
547 | * If at a chunk boundary, start prefetch of next chunk. | |
548 | */ | |
549 | if (counter == 0 || AFS_CHUNKOFFSET(off) == 0) { | |
550 | AFS_GLOCK(); | |
551 | ObtainWriteLock(&avc->lock, 562); | |
552 | tdc = afs_FindDCache(avc, off); | |
553 | if (tdc) { | |
554 | if (!(tdc->mflags & DFNextStarted)) | |
555 | afs_PrefetchChunk(avc, tdc, cr, &treq); | |
556 | afs_PutDCache(tdc); | |
557 | } | |
558 | ReleaseWriteLock(&avc->lock); | |
559 | AFS_GUNLOCK(); | |
560 | } | |
561 | counter++; | |
562 | } else { | |
563 | /* | |
564 | * writing a normal file | |
565 | */ | |
566 | /* | |
567 | * Purge dirty chunks of file if there are too many dirty chunks. | |
568 | * Inside the write loop, we only do this at a chunk boundary. | |
569 | * Clean up partial chunk if necessary at end of loop. | |
570 | */ | |
571 | if (counter > 0 && AFS_CHUNKOFFSET(uio->uio_offset) == 0) { | |
572 | AFS_GLOCK(); | |
573 | ObtainWriteLock(&avc->lock, 90); | |
574 | error = afs_DoPartialWrite(avc, &treq); | |
575 | if (error == 0) | |
576 | avc->f.states |= CDirty; | |
577 | ReleaseWriteLock(&avc->lock); | |
578 | AFS_GUNLOCK(); | |
579 | if (error) | |
580 | break; | |
581 | } | |
582 | counter++; | |
583 | ||
584 | cnt = MIN(bsize - off, uio->uio_resid); | |
585 | bsize = ctob(btoc(off + cnt)); | |
586 | len = BTOBBT(bsize); | |
587 | bmv[0].bn = bn; | |
588 | bmv[0].offset = bn; | |
589 | bmv[0].length = len; | |
590 | bmv[0].eof = 0; | |
591 | bmv[0].bsize = bsize; | |
592 | bmv[0].pboff = off; | |
593 | bmv[0].pbsize = cnt; | |
594 | #ifdef AFS_SGI64_ENV | |
595 | bmv[0].pmp = uio->uio_pmp; | |
596 | #endif | |
597 | ||
598 | if (cnt == bsize) | |
599 | bp = getchunk(vp, bmv, cr); | |
600 | else | |
601 | bp = chunkread(vp, bmv, 1, cr); | |
602 | ||
603 | avc->f.m.Date = osi_Time(); /* Set file date (for ranlib) */ | |
604 | } | |
605 | if (bp->b_flags & B_ERROR) { | |
606 | /* | |
607 | * Since we compile -signed, b_error is a signed | |
608 | * char when it should be an unsigned char. | |
609 | * This can cause some errors codes to be interpreted | |
610 | * as negative #s | |
611 | */ | |
612 | error = (unsigned char)(bp->b_error); | |
613 | if (!error) | |
614 | error = EIO; | |
615 | #ifdef DEBUG | |
616 | if (acchk && error) { | |
617 | cmn_err(CE_WARN, "bp 0x%x has error %d\n", bp, error); | |
618 | if (acdrop) | |
619 | debug("AFS"); | |
620 | } | |
621 | #endif | |
622 | brelse(bp); | |
623 | break; | |
624 | } | |
625 | ||
626 | osi_Assert(bp->b_error == 0); | |
627 | ||
628 | if (uio->uio_segflg != UIO_NOSPACE) | |
629 | (void)bp_mapin(bp); | |
630 | AFS_UIOMOVE(bp->b_un.b_addr + bmv[0].pboff, cnt, rw, uio, error); | |
631 | if (rw == UIO_READ || error) { | |
632 | if (bp->b_flags & B_DELWRI) { | |
633 | bawrite(bp); | |
634 | } else | |
635 | brelse(bp); | |
636 | } else { | |
637 | /* | |
638 | * m.Length is the maximum number of bytes known to be in the file. | |
639 | * Make sure it is at least as high as the last byte we just wrote | |
640 | * into the buffer. | |
641 | */ | |
642 | if (avc->f.m.Length < uio->uio_offset) { | |
643 | AFS_GLOCK(); | |
644 | ObtainWriteLock(&avc->lock, 235); | |
645 | avc->f.m.Length = uio->uio_offset; | |
646 | ReleaseWriteLock(&avc->lock); | |
647 | AFS_GUNLOCK(); | |
648 | } | |
649 | if (uio->uio_fmode & FSYNC) { | |
650 | error = bwrite(bp); | |
651 | } else if (off + cnt < bsize) { | |
652 | bawrite(bp); /* was bdwrite */ | |
653 | } else { | |
654 | bp->b_flags |= B_AGE; | |
655 | bawrite(bp); | |
656 | } | |
657 | /* | |
658 | * Since EIO on an unlinked file is non-intuitive - give some | |
659 | * explanation | |
660 | */ | |
661 | if (error) { | |
662 | if (avc->f.m.LinkCount == 0) | |
663 | cmn_err(CE_WARN, | |
664 | "AFS: Process pid %d write error %d writing to unlinked file.", | |
665 | OSI_GET_CURRENT_PID(), error); | |
666 | } | |
667 | } | |
668 | } while (!error && uio->uio_resid > 0); | |
669 | afs_chkpgoob(&avc->v, btoc(avc->f.m.Length)); | |
670 | ||
671 | AFS_GLOCK(); | |
672 | ||
673 | if (rw == UIO_WRITE && error == 0 && (avc->f.states & CDirty)) { | |
674 | ObtainWriteLock(&avc->lock, 405); | |
675 | error = afs_DoPartialWrite(avc, &treq); | |
676 | ReleaseWriteLock(&avc->lock); | |
677 | } | |
678 | ||
679 | if (!error) { | |
680 | #ifdef AFS_SGI61_ENV | |
681 | if (((ioflag & IO_SYNC) || (ioflag & IO_DSYNC)) && (rw == UIO_WRITE) | |
682 | && !AFS_NFSXLATORREQ(cr)) { | |
683 | error = afs_fsync(avc, 0, cr | |
684 | #ifdef AFS_SGI65_ENV | |
685 | , 0, 0 | |
686 | #endif | |
687 | ); | |
688 | } | |
689 | #else /* AFS_SGI61_ENV */ | |
690 | if ((ioflag & IO_SYNC) && (rw == UIO_WRITE) && !AFS_NFSXLATORREQ(cr)) { | |
691 | error = afs_fsync(avc, 0, cr); | |
692 | } | |
693 | #endif /* AFS_SGI61_ENV */ | |
694 | } | |
695 | if (didFakeOpen) { | |
696 | ObtainWriteLock(&avc->lock, 236); | |
697 | afs_FakeClose(avc, cr); /* XXXX For nfs trans XXXX */ | |
698 | ReleaseWriteLock(&avc->lock); | |
699 | } | |
700 | afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, avc, | |
701 | ICL_TYPE_INT32, ioflag, ICL_TYPE_INT32, rw, ICL_TYPE_INT32, | |
702 | error); | |
703 | ||
704 | return (error); | |
705 | } | |
706 | ||
707 | int | |
708 | afs_xbmap(OSI_VC_ARG(avc), offset, count, flag, cr, bmv, nbmv) | |
709 | OSI_VC_DECL(avc); | |
710 | off_t offset; | |
711 | ssize_t count; | |
712 | int flag; | |
713 | struct cred *cr; | |
714 | struct bmapval *bmv; | |
715 | int *nbmv; | |
716 | { | |
717 | int bsize; /* server's block size in bytes */ | |
718 | off_t off; | |
719 | size_t rem, cnt; | |
720 | OSI_VC_CONVERT(avc); | |
721 | ||
722 | bsize = AFSBSIZE; | |
723 | off = offset % bsize; /* offset into block */ | |
724 | bmv->bn = BTOBBT(offset - off); | |
725 | bmv->offset = bmv->bn; | |
726 | bmv->pboff = off; | |
727 | rem = avc->f.m.Length - offset; | |
728 | if (rem <= 0) | |
729 | cnt = 0; /* EOF */ | |
730 | else | |
731 | cnt = MIN(bsize - off, rem); | |
732 | ||
733 | /* | |
734 | * It is benign to ignore *nbmv > 1, since it is only for requesting | |
735 | * readahead. | |
736 | */ | |
737 | ||
738 | /* | |
739 | * Don't map more than up to next page if at end of file | |
740 | * See comment in afsrwvp | |
741 | */ | |
742 | osi_Assert((off + cnt) <= bsize); | |
743 | bsize = ctob(btoc(off + cnt)); | |
744 | bmv->pbsize = MIN(cnt, count); | |
745 | bmv->eof = 0; | |
746 | #ifdef AFS_SGI64_ENV | |
747 | bmv->pmp = NULL; | |
748 | bmv->pbdev = avc->v.v_rdev; | |
749 | #endif | |
750 | bmv->bsize = bsize; | |
751 | bmv->length = BTOBBT(bsize); | |
752 | *nbmv = 1; | |
753 | return (0); | |
754 | } | |
755 | ||
756 | /* | |
757 | * called out of chunkread from afs_xread & clusterwrite to push dirty | |
758 | * pages back - this routine | |
759 | * actually does the reading/writing by calling afs_read/afs_write | |
760 | * bp points to a set of pages that have been inserted into | |
761 | * the page cache hashed on afs vp. | |
762 | */ | |
763 | static void | |
764 | afs_strategy(OSI_VC_ARG(avc), bp) | |
765 | OSI_VC_DECL(avc); | |
766 | struct buf *bp; | |
767 | { | |
768 | uio_t auio; | |
769 | uio_t *uio = &auio; | |
770 | iovec_t aiovec; | |
771 | int error; | |
772 | struct cred *cr; | |
773 | OSI_VC_CONVERT(avc); | |
774 | vnode_t *vp = (vnode_t *) avc; | |
775 | ||
776 | /* | |
777 | * We can't afford DELWRI buffers for 2 reasons: | |
778 | * 1) Since we can call underlying EFS, we can require a | |
779 | * buffer to flush a buffer. This leads to 2 potential | |
780 | * recursions/deadlocks | |
781 | * a) if all buffers are DELWRI afs buffers, then | |
782 | * ngeteblk -> bwrite -> afs_strategy -> afs_write -> | |
783 | * UFS_Write -> efs_write -> ngeteblk .... could | |
784 | * recurse a long ways! | |
785 | * b) brelse -> chunkhold which can call dchunkpush | |
786 | * will look for any DELWRI buffers and call strategy | |
787 | * on them. This can then end up via UFS_Write | |
788 | * recursing | |
789 | * Current hack: | |
790 | * a) We never do bdwrite(s) on AFS buffers. | |
791 | * b) We call pdflush with B_ASYNC | |
792 | * c) in chunkhold where it can set a buffer DELWRI | |
793 | * we immediatly do a clusterwrite for AFS vp's | |
794 | * XXX Alas, 'c' got dropped in 5.1 so its possible to get DELWRI | |
795 | * buffers if someone has mmaped the file and dirtied it then | |
796 | * reads/faults it again. | |
797 | * Instead - wherever we call chunkread/getchunk we check for a | |
798 | * returned bp with DELWRI set, and write it out immediately | |
799 | */ | |
800 | if (CheckLock(&avc->lock) && VN_GET_DBUF(vp)) { | |
801 | printf("WARN: afs_strategy vp=%x, v_dbuf=%x bp=%x\n", vp, | |
802 | VN_GET_DBUF(vp), bp); | |
803 | bp->b_error = EIO; | |
804 | bp->b_flags |= B_ERROR; | |
805 | iodone(bp); | |
806 | return; | |
807 | } | |
808 | if (bp->b_error != 0) | |
809 | printf("WARNING: afs_strategy3 vp=%x, bp=%x, err=%x\n", vp, bp, | |
810 | bp->b_error); | |
811 | ||
812 | /* | |
813 | * To get credentials somewhat correct (we may be called from bdflush/ | |
814 | * sync) we use saved credentials in Vcache. | |
815 | * We must hold them since someone else could change them | |
816 | */ | |
817 | ObtainReadLock(&avc->lock); | |
818 | if (bp->b_flags & B_READ) { | |
819 | if (BBTOB(bp->b_blkno) >= avc->f.m.Length) { | |
820 | /* we are responsible for zero'ing the page */ | |
821 | caddr_t c; | |
822 | c = bp_mapin(bp); | |
823 | memset(c, 0, bp->b_bcount); | |
824 | iodone(bp); | |
825 | ReleaseReadLock(&avc->lock); | |
826 | return; | |
827 | } | |
828 | } else if ((avc->f.states & CWritingUFS) && (bp->b_flags & B_DELWRI)) { | |
829 | bp->b_ref = 3; | |
830 | ReleaseReadLock(&avc->lock); | |
831 | iodone(bp); | |
832 | return; | |
833 | } | |
834 | cr = avc->cred; | |
835 | osi_Assert(cr); | |
836 | crhold(cr); | |
837 | ReleaseReadLock(&avc->lock); | |
838 | ||
839 | aiovec.iov_base = bp_mapin(bp); | |
840 | uio->uio_iov = &aiovec; | |
841 | uio->uio_iovcnt = 1; | |
842 | uio->uio_resid = aiovec.iov_len = bp->b_bcount; | |
843 | uio->uio_offset = BBTOB(bp->b_blkno); | |
844 | uio->uio_segflg = UIO_SYSSPACE; | |
845 | uio->uio_limit = RLIM_INFINITY; /* we checked the limit earlier */ | |
846 | #ifdef AFS_SGI64_ENV | |
847 | uio->uio_pmp = NULL; | |
848 | #endif | |
849 | ||
850 | if (bp->b_flags & B_READ) { | |
851 | uio->uio_fmode = FREAD; | |
852 | error = afs_read(vp, uio, cr, 0); | |
853 | } else { | |
854 | uio->uio_fmode = FWRITE; | |
855 | error = afs_write(vp, uio, 0, cr, 0); | |
856 | } | |
857 | crfree(cr); | |
858 | ||
859 | #ifdef DEBUG | |
860 | if (acchk && error) { | |
861 | cmn_err(CE_WARN, "vp 0x%x has error %d\n", vp, error); | |
862 | if (acdrop) | |
863 | debug("AFS"); | |
864 | } | |
865 | #endif | |
866 | if (error) { | |
867 | bp->b_error = error; | |
868 | bp->b_flags |= B_ERROR; | |
869 | if ((uio->uio_fmode == FWRITE) && !avc->vc_error) | |
870 | avc->vc_error = error; | |
871 | } | |
872 | iodone(bp); | |
873 | return; | |
874 | } | |
875 | ||
876 | /* ARGSUSED */ | |
877 | static int | |
878 | afs_seek(OSI_VC_ARG(avc), ooff, noffp) | |
879 | OSI_VC_DECL(avc); | |
880 | off_t ooff; | |
881 | off_t *noffp; | |
882 | { | |
883 | return *noffp < 0 ? EINVAL : 0; | |
884 | } | |
885 | ||
886 | #if !defined(AFS_SGI65_ENV) | |
887 | /* Irix 6.5 uses addmap/delmap only for devices. */ | |
888 | /* ARGSUSED */ | |
889 | static int | |
890 | afs_addmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot, flags, cr) | |
891 | off_t off; | |
892 | OSI_VC_DECL(avc); | |
893 | struct pregion *prp; | |
894 | addr_t addr; | |
895 | size_t len; | |
896 | u_int prot, maxprot; | |
897 | u_int flags; | |
898 | struct cred *cr; | |
899 | { | |
900 | OSI_VC_CONVERT(avc); | |
901 | struct vnode *vp = AFSTOV(avc); | |
902 | ||
903 | if (vp->v_flag & VNOMAP) | |
904 | return ENOSYS; | |
905 | if (len == 0) | |
906 | return 0; | |
907 | AFS_RWLOCK(vp, VRWLOCK_WRITE); | |
908 | if (avc->mapcnt == 0) { | |
909 | /* on first mapping add a open reference */ | |
910 | ObtainWriteLock(&avc->lock, 237); | |
911 | avc->execsOrWriters++; | |
912 | avc->opens++; | |
913 | ReleaseWriteLock(&avc->lock); | |
914 | } | |
915 | avc->mapcnt += btoc(len); | |
916 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
917 | return 0; | |
918 | } | |
919 | ||
920 | /*ARGSUSED*/ static int | |
921 | afs_delmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot, flags, acred) | |
922 | off_t off; | |
923 | OSI_VC_DECL(avc); | |
924 | struct pregion *prp; | |
925 | addr_t addr; | |
926 | size_t len; | |
927 | u_int prot, maxprot; | |
928 | u_int flags; | |
929 | struct cred *acred; | |
930 | { | |
931 | OSI_VC_CONVERT(avc); | |
932 | struct vnode *vp = AFSTOV(avc); | |
933 | struct brequest *tb; | |
934 | struct vrequest treq; | |
935 | afs_int32 code; | |
936 | ||
937 | if (vp->v_flag & VNOMAP) | |
938 | return ENOSYS; | |
939 | if (len == 0) | |
940 | return 0; | |
941 | AFS_RWLOCK(vp, VRWLOCK_WRITE); | |
942 | osi_Assert(avc->mapcnt > 0); | |
943 | avc->mapcnt -= btoc(len); | |
944 | osi_Assert(avc->mapcnt >= 0); | |
945 | if (avc->mapcnt == 0) { | |
946 | /* on last mapping push back and remove our reference */ | |
947 | osi_Assert(avc->execsOrWriters > 0); | |
948 | osi_Assert(avc->opens > 0); | |
949 | if (avc->f.m.LinkCount == 0) { | |
950 | ObtainWriteLock(&avc->lock, 238); | |
951 | AFS_GUNLOCK(); | |
952 | PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG); | |
953 | AFS_GLOCK(); | |
954 | ReleaseWriteLock(&avc->lock); | |
955 | } | |
956 | /* | |
957 | * mimic afs_close | |
958 | */ | |
959 | code = afs_InitReq(&treq, acred); | |
960 | if (code) { | |
961 | code = afs_CheckCode(code, NULL, 64); | |
962 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
963 | } else if (afs_BBusy()) { | |
964 | /* do it yourself if daemons are all busy */ | |
965 | ObtainWriteLock(&avc->lock, 239); | |
966 | code = afs_StoreOnLastReference(avc, &treq); | |
967 | ReleaseWriteLock(&avc->lock); | |
968 | /* BStore does CheckCode so we should also */ | |
969 | /* VNOVNODE is "acceptable" error code from close, since | |
970 | * may happen when deleting a file on another machine while | |
971 | * it is open here. */ | |
972 | if (code == VNOVNODE) | |
973 | code = 0; | |
974 | if (code) { | |
975 | afs_StoreWarn(code, avc->f.fid.Fid.Volume, /* /dev/console */ | |
976 | 1); | |
977 | } | |
978 | code = afs_CheckCode(code, &treq, 52); | |
979 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
980 | } else { | |
981 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
982 | /* at least one daemon is idle, so ask it to do the store. | |
983 | * Also, note that we don't lock it any more... */ | |
984 | tb = afs_BQueue(BOP_STORE, avc, 0, 1, acred, | |
985 | (afs_size_t) afs_cr_uid(acred), 0L, (void *)0, | |
986 | (void *)0, (void *)0); | |
987 | /* sleep waiting for the store to start, then retrieve error code */ | |
988 | while ((tb->flags & BUVALID) == 0) { | |
989 | tb->flags |= BUWAIT; | |
990 | afs_osi_Sleep(tb); | |
991 | } | |
992 | afs_BRelease(tb); | |
993 | } | |
994 | } else { | |
995 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
996 | } | |
997 | return 0; | |
998 | } | |
999 | #endif /* ! AFS_SGI65_ENV */ | |
1000 | ||
1001 | ||
1002 | /* ARGSUSED */ | |
1003 | /* | |
1004 | * Note - if mapping in an ELF interpreter, one can get called without vp | |
1005 | * ever having been 'opened' | |
1006 | */ | |
1007 | #ifdef AFS_SGI65_ENV | |
1008 | static int | |
1009 | afs_map(OSI_VC_ARG(avc), off, len, prot, flags, cr, vpp) | |
1010 | off_t off; | |
1011 | OSI_VC_DECL(avc); | |
1012 | size_t len; | |
1013 | mprot_t prot; | |
1014 | u_int flags; | |
1015 | struct cred *cr; | |
1016 | vnode_t **vpp; | |
1017 | #else | |
1018 | static int | |
1019 | afs_map(OSI_VC_ARG(avc), off, prp, addrp, len, prot, maxprot, flags, cr) | |
1020 | off_t off; | |
1021 | OSI_VC_DECL(avc); | |
1022 | struct pregion *prp; | |
1023 | addr_t *addrp; | |
1024 | size_t len; | |
1025 | u_int prot, maxprot; | |
1026 | u_int flags; | |
1027 | struct cred *cr; | |
1028 | #endif | |
1029 | { | |
1030 | OSI_VC_CONVERT(avc); | |
1031 | struct vnode *vp = AFSTOV(avc); | |
1032 | struct vrequest treq; | |
1033 | int error; | |
1034 | ||
1035 | /* get a validated vcache entry */ | |
1036 | error = afs_InitReq(&treq, cr); | |
1037 | if (error) | |
1038 | return afs_CheckCode(error, NULL, 65); | |
1039 | ||
1040 | error = afs_VerifyVCache(avc, &treq); | |
1041 | if (error) | |
1042 | return afs_CheckCode(error, &treq, 53); | |
1043 | ||
1044 | osi_FlushPages(avc, cr); /* ensure old pages are gone */ | |
1045 | #ifdef AFS_SGI65_ENV | |
1046 | /* If the vnode is currently opened for write, there's the potential | |
1047 | * that this mapping might (now or in the future) have PROT_WRITE. | |
1048 | * So assume it does and we'll have to call afs_StoreOnLastReference. | |
1049 | */ | |
1050 | AFS_RWLOCK(vp, VRWLOCK_WRITE); | |
1051 | ObtainWriteLock(&avc->lock, 501); | |
1052 | if (avc->execsOrWriters > 0) { | |
1053 | avc->execsOrWriters++; | |
1054 | avc->opens++; | |
1055 | avc->mapcnt++; /* count eow's due to mappings. */ | |
1056 | } | |
1057 | ReleaseWriteLock(&avc->lock); | |
1058 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
1059 | #else | |
1060 | AFS_RWLOCK(vp, VRWLOCK_WRITE); | |
1061 | AFS_GUNLOCK(); | |
1062 | error = | |
1063 | fs_map_subr(vp, (off_t) avc->f.m.Length, (u_int) avc->f.m.Mode, off, prp, | |
1064 | *addrp, len, prot, maxprot, flags, cr); | |
1065 | AFS_GLOCK(); | |
1066 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
1067 | #endif /* AFS_SGI65_ENV */ | |
1068 | afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vp, | |
1069 | #ifdef AFS_SGI65_ENV | |
1070 | ICL_TYPE_POINTER, NULL, | |
1071 | #else | |
1072 | ICL_TYPE_POINTER, *addrp, | |
1073 | #endif | |
1074 | ICL_TYPE_INT32, len, ICL_TYPE_INT32, off); | |
1075 | return error; | |
1076 | } | |
1077 | ||
1078 | ||
1079 | extern afs_rwlock_t afs_xvcache; | |
1080 | extern afs_lock_t afs_xdcache; | |
1081 | #ifdef AFS_SGI64_ENV | |
1082 | int | |
1083 | #else | |
1084 | void | |
1085 | #endif | |
1086 | afs_xinactive(OSI_VC_ARG(avc), acred) | |
1087 | OSI_VC_DECL(avc); | |
1088 | struct ucred *acred; | |
1089 | { | |
1090 | int s; | |
1091 | OSI_VC_CONVERT(avc); | |
1092 | vnode_t *vp = (vnode_t *) avc; | |
1093 | int mapcnt = avc->mapcnt; /* We just clear off this many. */ | |
1094 | ||
1095 | AFS_STATCNT(afs_inactive); | |
1096 | ||
1097 | s = VN_LOCK(vp); | |
1098 | if (!(vp->v_flag & VINACT) || (vp->v_count > 0)) { | |
1099 | /* inactive was already done, or someone did a VN_HOLD; just return */ | |
1100 | vp->v_flag &= ~VINACT; | |
1101 | VN_UNLOCK(vp, s); | |
1102 | #ifdef AFS_SGI64_ENV | |
1103 | return VN_INACTIVE_CACHE; | |
1104 | #else | |
1105 | return; | |
1106 | #endif | |
1107 | } | |
1108 | osi_Assert((vp->v_flag & VSHARE) == 0); | |
1109 | vp->v_flag &= ~VINACT; | |
1110 | /* Removed broadcast to waiters, since no one ever will. Only for vnodes | |
1111 | * in common pool. | |
1112 | */ | |
1113 | VN_UNLOCK(vp, s); | |
1114 | ||
1115 | #ifdef AFS_SGI65_ENV | |
1116 | /* In Irix 6.5, the last unmap of a dirty mmap'd file does not | |
1117 | * get an explicit vnode op. Instead we only find out at VOP_INACTIVE. | |
1118 | */ | |
1119 | if (!afs_rwlock_nowait((vnode_t *) avc, VRWLOCK_WRITE)) { | |
1120 | return VN_INACTIVE_CACHE; | |
1121 | } | |
1122 | if (NBObtainWriteLock(&avc->lock, 502)) { | |
1123 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
1124 | return VN_INACTIVE_CACHE; | |
1125 | } | |
1126 | if (avc->f.states & CUnlinked) { | |
1127 | if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) { | |
1128 | avc->f.states |= CUnlinkedDel; | |
1129 | ReleaseWriteLock(&avc->lock); | |
1130 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
1131 | } else { | |
1132 | ReleaseWriteLock(&avc->lock); | |
1133 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
1134 | afs_remunlink(avc, 1); /* ignore any return code */ | |
1135 | } | |
1136 | return VN_INACTIVE_CACHE; | |
1137 | } | |
1138 | if ((avc->f.states & CDirty) || (avc->execsOrWriters > 0)) { | |
1139 | /* File either already has dirty chunks (CDirty) or was mapped at | |
1140 | * time in its life with the potential for being written into. | |
1141 | * Note that afs_close defers storebacks if the vnode's ref count | |
1142 | * if more than 1. | |
1143 | */ | |
1144 | int code; | |
1145 | struct vrequest treq; | |
1146 | if (!afs_InitReq(&treq, acred)) { | |
1147 | int s; | |
1148 | ||
1149 | VN_HOLD(vp); | |
1150 | avc->execsOrWriters -= mapcnt - 1; | |
1151 | avc->opens -= mapcnt - 1; | |
1152 | avc->mapcnt -= mapcnt; | |
1153 | code = afs_StoreOnLastReference(avc, &treq); | |
1154 | /* The following behavior mimics the behavior in afs_close. */ | |
1155 | if (code == VNOVNODE) | |
1156 | code = 0; | |
1157 | if (code) { | |
1158 | if (mapcnt) { | |
1159 | cmn_err(CE_WARN, | |
1160 | "AFS: Failed to store FID (%x:%lu.%lu.%lu) in VOP_INACTIVE, error = %d\n", | |
1161 | (int)(avc->f.fid.Cell) & 0xffffffff, | |
1162 | avc->f.fid.Fid.Volume, avc->f.fid.Fid.Vnode, | |
1163 | avc->f.fid.Fid.Unique, code); | |
1164 | } | |
1165 | afs_InvalidateAllSegments(avc); | |
1166 | } | |
1167 | s = VN_LOCK(vp); | |
1168 | vp->v_count--; | |
1169 | code = (vp->v_count == 0); | |
1170 | VN_UNLOCK(vp, s); | |
1171 | /* If the vnode is now in use by someone else, return early. */ | |
1172 | if (!code) { | |
1173 | ReleaseWriteLock(&avc->lock); | |
1174 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
1175 | return VN_INACTIVE_CACHE; | |
1176 | } | |
1177 | } | |
1178 | } | |
1179 | #endif | |
1180 | ||
1181 | osi_Assert((avc->f.states & (CCore | CMAPPED)) == 0); | |
1182 | ||
1183 | if (avc->cred) { | |
1184 | crfree(avc->cred); | |
1185 | avc->cred = NULL; | |
1186 | } | |
1187 | ReleaseWriteLock(&avc->lock); | |
1188 | AFS_RWUNLOCK(vp, VRWLOCK_WRITE); | |
1189 | ||
1190 | /* | |
1191 | * If someone unlinked a file and this is the last hurrah - | |
1192 | * nuke all the pages. | |
1193 | */ | |
1194 | if (avc->f.m.LinkCount == 0) { | |
1195 | AFS_GUNLOCK(); | |
1196 | PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG); | |
1197 | AFS_GLOCK(); | |
1198 | } | |
1199 | #ifndef AFS_SGI65_ENV | |
1200 | osi_Assert(avc->mapcnt == 0); | |
1201 | afs_chkpgoob(&avc->v, btoc(avc->f.m.Length)); | |
1202 | ||
1203 | avc->f.states &= ~CDirty; /* Give up on store-backs */ | |
1204 | if (avc->f.states & CUnlinked) { | |
1205 | if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) { | |
1206 | avc->f.states |= CUnlinkedDel; | |
1207 | } else { | |
1208 | afs_remunlink(avc, 1); /* ignore any return code */ | |
1209 | } | |
1210 | } | |
1211 | #endif | |
1212 | #ifdef AFS_SGI64_ENV | |
1213 | return VN_INACTIVE_CACHE; | |
1214 | #endif | |
1215 | } | |
1216 | ||
1217 | static int | |
1218 | afs_reclaim(OSI_VC_DECL(avc), int flag) | |
1219 | { | |
1220 | #ifdef AFS_SGI64_ENV | |
1221 | /* Get's called via VOP_RELCAIM in afs_FlushVCache to clear repl_vnodeops */ | |
1222 | return 0; | |
1223 | #else | |
1224 | panic("afs_reclaim"); | |
1225 | #endif | |
1226 | } | |
1227 | ||
1228 | void | |
1229 | afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag) | |
1230 | { | |
1231 | OSI_VN_CONVERT(vp); | |
1232 | struct vcache *avc = VTOAFS(vp); | |
1233 | ||
1234 | if (OSI_GET_LOCKID() == avc->vc_rwlockid) { | |
1235 | avc->vc_locktrips++; | |
1236 | return; | |
1237 | } | |
1238 | AFS_GUNLOCK(); | |
1239 | psema(&avc->vc_rwlock, PINOD); | |
1240 | AFS_GLOCK(); | |
1241 | avc->vc_rwlockid = OSI_GET_LOCKID(); | |
1242 | } | |
1243 | ||
1244 | void | |
1245 | afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag) | |
1246 | { | |
1247 | OSI_VN_CONVERT(vp); | |
1248 | struct vcache *avc = VTOAFS(vp); | |
1249 | ||
1250 | AFS_ASSERT_GLOCK(); | |
1251 | osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid); | |
1252 | if (avc->vc_locktrips > 0) { | |
1253 | --avc->vc_locktrips; | |
1254 | return; | |
1255 | } | |
1256 | avc->vc_rwlockid = OSI_NO_LOCKID; | |
1257 | vsema(&avc->vc_rwlock); | |
1258 | } | |
1259 | ||
1260 | ||
1261 | /* The flag argument is for symmetry with the afs_rwlock and afs_rwunlock | |
1262 | * calls. SGI currently only uses the flag to assert if the unlock flag | |
1263 | * does not match the corresponding lock flag. But they may start using this | |
1264 | * flag for a real rw lock at some time. | |
1265 | */ | |
1266 | int | |
1267 | afs_rwlock_nowait(vnode_t * vp, AFS_RWLOCK_T flag) | |
1268 | { | |
1269 | struct vcache *avc = VTOAFS(vp); | |
1270 | ||
1271 | AFS_ASSERT_GLOCK(); | |
1272 | if (OSI_GET_LOCKID() == avc->vc_rwlockid) { | |
1273 | avc->vc_locktrips++; | |
1274 | return 1; | |
1275 | } | |
1276 | if (cpsema(&avc->vc_rwlock)) { | |
1277 | avc->vc_rwlockid = OSI_GET_LOCKID(); | |
1278 | return 1; | |
1279 | } | |
1280 | return 0; | |
1281 | } | |
1282 | ||
1283 | #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR) | |
1284 | int | |
1285 | afs_fid2(OSI_VC_DECL(avc), struct fid *fidp) | |
1286 | { | |
1287 | struct cell *tcell; | |
1288 | afs_fid2_t *afid = (afs_fid2_t *) fidp; | |
1289 | OSI_VC_CONVERT(avc); | |
1290 | ||
1291 | osi_Assert(sizeof(fid_t) >= sizeof(afs_fid2_t)); | |
1292 | afid->af_len = sizeof(afs_fid2_t) - sizeof(afid->af_len); | |
1293 | ||
1294 | tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK); | |
1295 | afid->af_cell = tcell->cellIndex & 0xffff; | |
1296 | afs_PutCell(tcell, READ_LOCK); | |
1297 | ||
1298 | afid->af_volid = avc->f.fid.Fid.Volume; | |
1299 | afid->af_vno = avc->f.fid.Fid.Vnode; | |
1300 | afid->af_uniq = avc->f.fid.Fid.Unique; | |
1301 | ||
1302 | return 0; | |
1303 | } | |
1304 | #else | |
1305 | /* Only use so far is in checkpoint/restart for IRIX 6.4. In ckpt_fid, a | |
1306 | * return of ENOSYS would make the code fail over to VOP_FID. We can't let | |
1307 | * that happen, since we do a VN_HOLD there in the expectation that | |
1308 | * posthandle will be called to release the vnode. | |
1309 | * | |
1310 | * afs_fid2 is used to support the R5000 workarounds (_R5000_CVT_WAR) | |
1311 | */ | |
1312 | int | |
1313 | afs_fid2(OSI_VC_DECL(avc), struct fid *fidp) | |
1314 | { | |
1315 | #if defined(_R5000_CVT_WAR) | |
1316 | extern int R5000_cvt_war; | |
1317 | ||
1318 | if (R5000_cvt_war) | |
1319 | return ENOSYS; | |
1320 | else | |
1321 | return EINVAL; | |
1322 | #else | |
1323 | return EINVAL; | |
1324 | #endif | |
1325 | } | |
1326 | #endif /* AFS_SGI64_ENV && CKPT */ | |
1327 | ||
1328 | ||
1329 | /* | |
1330 | * check for any pages hashed that shouldn't be! | |
1331 | * Only valid if PGCACHEDEBUG is set in os/page.c | |
1332 | * Drop the global lock here, since we may not actually do the call. | |
1333 | */ | |
1334 | void | |
1335 | afs_chkpgoob(vnode_t * vp, pgno_t pgno) | |
1336 | { | |
1337 | #undef PGDEBUG | |
1338 | #ifdef PGDEBUG | |
1339 | AFS_GUNLOCK(); | |
1340 | pfindanyoob(vp, pgno); | |
1341 | AFS_GLOCK(); | |
1342 | #endif | |
1343 | } | |
1344 | ||
1345 | ||
1346 | #ifdef MP | |
1347 | ||
1348 | #ifdef AFS_SGI64_ENV | |
1349 | #define AFS_MP_VC_ARG(A) bhv_desc_t A | |
1350 | #else | |
1351 | #define AFS_MP_VC_ARG(A) vnode_t A | |
1352 | #endif | |
1353 | ||
1354 | #ifdef AFS_SGI64_ENV | |
1355 | int | |
1356 | mp_afs_open(bhv_desc_t * bhp, vnode_t ** a, mode_t b, struct cred *c) | |
1357 | #else | |
1358 | int | |
1359 | mp_afs_open(vnode_t ** a, mode_t b, struct cred *c) | |
1360 | #endif | |
1361 | { | |
1362 | int rv; | |
1363 | AFS_GLOCK(); | |
1364 | #ifdef AFS_SGI64_ENV | |
1365 | rv = afs_lockedvnodeops.vop_open(bhp, a, b, c); | |
1366 | #else | |
1367 | rv = afs_lockedvnodeops.vop_open(a, b, c); | |
1368 | #endif | |
1369 | AFS_GUNLOCK(); | |
1370 | return rv; | |
1371 | } | |
1372 | ||
1373 | #if defined(AFS_SGI64_ENV) | |
1374 | #if defined(AFS_SGI65_ENV) | |
1375 | int | |
1376 | mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, struct cred *d) | |
1377 | #else | |
1378 | int | |
1379 | mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e, | |
1380 | struct flid *f) | |
1381 | #endif | |
1382 | #else | |
1383 | int | |
1384 | mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e) | |
1385 | #endif | |
1386 | { | |
1387 | int rv; | |
1388 | AFS_GLOCK(); | |
1389 | rv = afs_lockedvnodeops.vop_close(a, b, c, d | |
1390 | #if !defined(AFS_SGI65_ENV) | |
1391 | , e | |
1392 | #if defined(AFS_SGI64_ENV) | |
1393 | , f | |
1394 | #endif | |
1395 | #endif | |
1396 | ); | |
1397 | ||
1398 | AFS_GUNLOCK(); | |
1399 | return rv; | |
1400 | } | |
1401 | ||
1402 | #ifdef AFS_SGI64_ENV | |
1403 | int | |
1404 | mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d, | |
1405 | struct flid *f) | |
1406 | #else | |
1407 | int | |
1408 | mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d) | |
1409 | #endif | |
1410 | { | |
1411 | int rv; | |
1412 | AFS_GLOCK(); | |
1413 | #ifdef AFS_SGI64_ENV | |
1414 | rv = afs_lockedvnodeops.vop_read(a, b, c, d, f); | |
1415 | #else | |
1416 | rv = afs_lockedvnodeops.vop_read(a, b, c, d); | |
1417 | #endif | |
1418 | AFS_GUNLOCK(); | |
1419 | return rv; | |
1420 | } | |
1421 | ||
1422 | ||
1423 | #ifdef AFS_SGI64_ENV | |
1424 | int | |
1425 | mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d, | |
1426 | struct flid *f) | |
1427 | #else | |
1428 | int | |
1429 | mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d) | |
1430 | #endif | |
1431 | { | |
1432 | int rv; | |
1433 | AFS_GLOCK(); | |
1434 | #ifdef AFS_SGI64_ENV | |
1435 | rv = afs_lockedvnodeops.vop_write(a, b, c, d, f); | |
1436 | #else | |
1437 | rv = afs_lockedvnodeops.vop_write(a, b, c, d); | |
1438 | #endif | |
1439 | AFS_GUNLOCK(); | |
1440 | return rv; | |
1441 | } | |
1442 | ||
1443 | int | |
1444 | mp_afs_ioctl(AFS_MP_VC_ARG(*a), int b, void *c, int d, struct cred *e, int *f | |
1445 | #ifdef AFS_SGI65_ENV | |
1446 | , struct vopbd *vbds | |
1447 | #endif | |
1448 | ) | |
1449 | { | |
1450 | int rv; | |
1451 | AFS_GLOCK(); | |
1452 | rv = afs_lockedvnodeops.vop_ioctl(a, b, c, d, e, f | |
1453 | #ifdef AFS_SGI65_ENV | |
1454 | , vbds | |
1455 | #endif | |
1456 | ); | |
1457 | AFS_GUNLOCK(); | |
1458 | return rv; | |
1459 | } | |
1460 | ||
1461 | int | |
1462 | mp_fs_setfl(AFS_MP_VC_ARG(*a), int b, int c, struct cred *d) | |
1463 | { | |
1464 | int rv; | |
1465 | AFS_GLOCK(); | |
1466 | rv = afs_lockedvnodeops.vop_setfl(a, b, c, d); | |
1467 | AFS_GUNLOCK(); | |
1468 | return rv; | |
1469 | } | |
1470 | ||
1471 | int | |
1472 | mp_afs_getattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d) | |
1473 | { | |
1474 | int rv; | |
1475 | AFS_GLOCK(); | |
1476 | rv = afs_lockedvnodeops.vop_getattr(a, b, c, d); | |
1477 | AFS_GUNLOCK(); | |
1478 | return rv; | |
1479 | } | |
1480 | ||
1481 | int | |
1482 | mp_afs_setattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d) | |
1483 | { | |
1484 | int rv; | |
1485 | AFS_GLOCK(); | |
1486 | rv = afs_lockedvnodeops.vop_setattr(a, b, c, d); | |
1487 | AFS_GUNLOCK(); | |
1488 | return rv; | |
1489 | } | |
1490 | ||
1491 | int | |
1492 | mp_afs_access(AFS_MP_VC_ARG(*a), int b, | |
1493 | #ifndef AFS_SGI65_ENV | |
1494 | int c, | |
1495 | #endif | |
1496 | struct cred *d) | |
1497 | { | |
1498 | int rv; | |
1499 | AFS_GLOCK(); | |
1500 | rv = afs_lockedvnodeops.vop_access(a, b, | |
1501 | #ifndef AFS_SGI65_ENV | |
1502 | c, | |
1503 | #endif | |
1504 | d); | |
1505 | AFS_GUNLOCK(); | |
1506 | return rv; | |
1507 | } | |
1508 | ||
1509 | int | |
1510 | mp_afs_lookup(AFS_MP_VC_ARG(*a), char *b, vnode_t ** c, struct pathname *d, | |
1511 | int e, vnode_t * f, struct cred *g) | |
1512 | { | |
1513 | int rv; | |
1514 | AFS_GLOCK(); | |
1515 | rv = afs_lockedvnodeops.vop_lookup(a, b, c, d, e, f, g); | |
1516 | AFS_GUNLOCK(); | |
1517 | return rv; | |
1518 | } | |
1519 | ||
1520 | #ifdef AFS_SGI64_ENV | |
1521 | int | |
1522 | mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, int d, int e, | |
1523 | vnode_t ** f, struct cred *g) | |
1524 | #else | |
1525 | int | |
1526 | mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, enum vcexcl d, | |
1527 | int e, vnode_t ** f, struct cred *g) | |
1528 | #endif | |
1529 | { | |
1530 | int rv; | |
1531 | AFS_GLOCK(); | |
1532 | rv = afs_lockedvnodeops.vop_create(a, b, c, d, e, f, g); | |
1533 | AFS_GUNLOCK(); | |
1534 | return rv; | |
1535 | } | |
1536 | ||
1537 | int | |
1538 | mp_afs_remove(AFS_MP_VC_ARG(*a), char *b, struct cred *c) | |
1539 | { | |
1540 | int rv; | |
1541 | AFS_GLOCK(); | |
1542 | rv = afs_lockedvnodeops.vop_remove(a, b, c); | |
1543 | AFS_GUNLOCK(); | |
1544 | return rv; | |
1545 | } | |
1546 | ||
1547 | int | |
1548 | mp_afs_link(AFS_MP_VC_ARG(*a), vnode_t * b, char *c, struct cred *d) | |
1549 | { | |
1550 | int rv; | |
1551 | AFS_GLOCK(); | |
1552 | rv = afs_lockedvnodeops.vop_link(a, b, c, d); | |
1553 | AFS_GUNLOCK(); | |
1554 | return rv; | |
1555 | } | |
1556 | ||
1557 | int | |
1558 | mp_afs_rename(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, char *d, | |
1559 | struct pathname *e, struct cred *f) | |
1560 | { | |
1561 | int rv; | |
1562 | AFS_GLOCK(); | |
1563 | rv = afs_lockedvnodeops.vop_rename(a, b, c, d, e, f); | |
1564 | AFS_GUNLOCK(); | |
1565 | return rv; | |
1566 | } | |
1567 | ||
1568 | int | |
1569 | mp_afs_mkdir(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, vnode_t ** d, | |
1570 | struct cred *e) | |
1571 | { | |
1572 | int rv; | |
1573 | AFS_GLOCK(); | |
1574 | rv = afs_lockedvnodeops.vop_mkdir(a, b, c, d, e); | |
1575 | AFS_GUNLOCK(); | |
1576 | return rv; | |
1577 | } | |
1578 | ||
1579 | int | |
1580 | mp_afs_rmdir(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, struct cred *d) | |
1581 | { | |
1582 | int rv; | |
1583 | AFS_GLOCK(); | |
1584 | rv = afs_lockedvnodeops.vop_rmdir(a, b, c, d); | |
1585 | AFS_GUNLOCK(); | |
1586 | return rv; | |
1587 | } | |
1588 | ||
1589 | int | |
1590 | mp_afs_readdir(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c, int *d) | |
1591 | { | |
1592 | int rv; | |
1593 | AFS_GLOCK(); | |
1594 | rv = afs_lockedvnodeops.vop_readdir(a, b, c, d); | |
1595 | AFS_GUNLOCK(); | |
1596 | return rv; | |
1597 | } | |
1598 | ||
1599 | int | |
1600 | mp_afs_symlink(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, char *d, | |
1601 | struct cred *e) | |
1602 | { | |
1603 | int rv; | |
1604 | AFS_GLOCK(); | |
1605 | rv = afs_lockedvnodeops.vop_symlink(a, b, c, d, e); | |
1606 | AFS_GUNLOCK(); | |
1607 | return rv; | |
1608 | } | |
1609 | ||
1610 | int | |
1611 | mp_afs_readlink(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c) | |
1612 | { | |
1613 | int rv; | |
1614 | AFS_GLOCK(); | |
1615 | rv = afs_lockedvnodeops.vop_readlink(a, b, c); | |
1616 | AFS_GUNLOCK(); | |
1617 | return rv; | |
1618 | } | |
1619 | ||
1620 | int | |
1621 | mp_afs_fsync(AFS_MP_VC_ARG(*a), int b, struct cred *c | |
1622 | #ifdef AFS_SGI65_ENV | |
1623 | , off_t start, off_t stop | |
1624 | #endif | |
1625 | ) | |
1626 | { | |
1627 | int rv; | |
1628 | AFS_GLOCK(); | |
1629 | rv = afs_lockedvnodeops.vop_fsync(a, b, c | |
1630 | #ifdef AFS_SGI65_ENV | |
1631 | , start, stop | |
1632 | #endif | |
1633 | ); | |
1634 | AFS_GUNLOCK(); | |
1635 | return rv; | |
1636 | } | |
1637 | ||
1638 | void | |
1639 | mp_afs_inactive(AFS_MP_VC_ARG(*a), struct cred *b) | |
1640 | { | |
1641 | AFS_GLOCK(); | |
1642 | afs_lockedvnodeops.vop_inactive(a, b); | |
1643 | AFS_GUNLOCK(); | |
1644 | return; | |
1645 | } | |
1646 | ||
1647 | int | |
1648 | mp_afs_fid(AFS_MP_VC_ARG(*a), struct fid **b) | |
1649 | { | |
1650 | int rv; | |
1651 | AFS_GLOCK(); | |
1652 | rv = afs_lockedvnodeops.vop_fid(a, b); | |
1653 | AFS_GUNLOCK(); | |
1654 | return rv; | |
1655 | } | |
1656 | ||
1657 | int | |
1658 | mp_afs_fid2(AFS_MP_VC_ARG(*a), struct fid *b) | |
1659 | { | |
1660 | int rv; | |
1661 | AFS_GLOCK(); | |
1662 | rv = afs_lockedvnodeops.vop_fid2(a, b); | |
1663 | AFS_GUNLOCK(); | |
1664 | return rv; | |
1665 | } | |
1666 | ||
1667 | void | |
1668 | mp_afs_rwlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b) | |
1669 | { | |
1670 | AFS_GLOCK(); | |
1671 | afs_rwlock(a, VRWLOCK_WRITE); | |
1672 | AFS_GUNLOCK(); | |
1673 | } | |
1674 | ||
1675 | void | |
1676 | mp_afs_rwunlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b) | |
1677 | { | |
1678 | AFS_GLOCK(); | |
1679 | afs_rwunlock(a, VRWLOCK_WRITE); | |
1680 | AFS_GUNLOCK(); | |
1681 | } | |
1682 | ||
1683 | int | |
1684 | mp_afs_seek(AFS_MP_VC_ARG(*a), off_t b, off_t * c) | |
1685 | { | |
1686 | int rv; | |
1687 | AFS_GLOCK(); | |
1688 | rv = afs_lockedvnodeops.vop_seek(a, b, c); | |
1689 | AFS_GUNLOCK(); | |
1690 | return rv; | |
1691 | } | |
1692 | ||
1693 | int | |
1694 | mp_fs_cmp(AFS_MP_VC_ARG(*a), vnode_t * b) | |
1695 | { | |
1696 | int rv; | |
1697 | AFS_GLOCK(); | |
1698 | rv = afs_lockedvnodeops.vop_cmp(a, b); | |
1699 | AFS_GUNLOCK(); | |
1700 | return rv; | |
1701 | } | |
1702 | ||
1703 | int | |
1704 | mp_afs_frlock(AFS_MP_VC_ARG(*a), int b, struct flock *c, int d, off_t e, | |
1705 | #ifdef AFS_SGI65_ENV | |
1706 | vrwlock_t vrwlock, | |
1707 | #endif | |
1708 | struct cred *f) | |
1709 | { | |
1710 | int rv; | |
1711 | AFS_GLOCK(); | |
1712 | rv = afs_lockedvnodeops.vop_frlock(a, b, c, d, e, | |
1713 | #ifdef AFS_SGI65_ENV | |
1714 | vrwlock, | |
1715 | #endif | |
1716 | f); | |
1717 | AFS_GUNLOCK(); | |
1718 | return rv; | |
1719 | } | |
1720 | ||
1721 | int | |
1722 | mp_afs_realvp(AFS_MP_VC_ARG(*a), vnode_t ** b) | |
1723 | { | |
1724 | int rv; | |
1725 | AFS_GLOCK(); | |
1726 | rv = afs_lockedvnodeops.vop_realvp(a, b); | |
1727 | AFS_GUNLOCK(); | |
1728 | return rv; | |
1729 | } | |
1730 | ||
1731 | int | |
1732 | mp_afs_bmap(AFS_MP_VC_ARG(*a), off_t b, ssize_t c, int d, struct cred *e, | |
1733 | struct bmapval *f, int *g) | |
1734 | { | |
1735 | int rv; | |
1736 | AFS_GLOCK(); | |
1737 | rv = afs_lockedvnodeops.vop_bmap(a, b, c, d, e, f, g); | |
1738 | AFS_GUNLOCK(); | |
1739 | return rv; | |
1740 | } | |
1741 | ||
1742 | void | |
1743 | mp_afs_strategy(AFS_MP_VC_ARG(*a), struct buf *b) | |
1744 | { | |
1745 | int rv; | |
1746 | AFS_GLOCK(); | |
1747 | afs_lockedvnodeops.vop_strategy(a, b); | |
1748 | AFS_GUNLOCK(); | |
1749 | return; | |
1750 | } | |
1751 | ||
1752 | #ifdef AFS_SGI65_ENV | |
1753 | int | |
1754 | mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, size_t c, mprot_t d, u_int e, | |
1755 | struct cred *f, vnode_t ** g) | |
1756 | #else | |
1757 | int | |
1758 | mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, char **d, size_t e, | |
1759 | u_int f, u_int g, u_int h, struct cred *i) | |
1760 | #endif | |
1761 | { | |
1762 | int rv; | |
1763 | AFS_GLOCK(); | |
1764 | rv = afs_lockedvnodeops.vop_map(a, b, c, d, e, f, g | |
1765 | #ifndef AFS_SGI65_ENV | |
1766 | , h, i | |
1767 | #endif | |
1768 | ); | |
1769 | AFS_GUNLOCK(); | |
1770 | return rv; | |
1771 | } | |
1772 | ||
1773 | ||
1774 | #ifndef AFS_SGI65_ENV | |
1775 | /* As of Irix 6.5, addmap and delmap are only for devices */ | |
1776 | int | |
1777 | mp_afs_addmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d, | |
1778 | size_t e, u_int f, u_int g, u_int h, struct cred *i) | |
1779 | { | |
1780 | int rv; | |
1781 | AFS_GLOCK(); | |
1782 | rv = afs_lockedvnodeops.vop_addmap(a, b, c, d, e, f, g, h, i); | |
1783 | AFS_GUNLOCK(); | |
1784 | return rv; | |
1785 | } | |
1786 | ||
1787 | int | |
1788 | mp_afs_delmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d, | |
1789 | size_t e, u_int f, u_int g, u_int h, struct cred *i) | |
1790 | { | |
1791 | int rv; | |
1792 | AFS_GLOCK(); | |
1793 | rv = afs_lockedvnodeops.vop_delmap(a, b, c, d, e, f, g, h, i); | |
1794 | AFS_GUNLOCK(); | |
1795 | return rv; | |
1796 | } | |
1797 | #endif /* ! AFS_SGI65_ENV */ | |
1798 | ||
1799 | int | |
1800 | mp_fs_poll(AFS_MP_VC_ARG(*a), short b, int c, short *d, struct pollhead **e | |
1801 | #ifdef AFS_SGI65_ENV | |
1802 | , unsigned int *f | |
1803 | #endif | |
1804 | ) | |
1805 | { | |
1806 | int rv; | |
1807 | AFS_GLOCK(); | |
1808 | rv = afs_lockedvnodeops.vop_poll(a, b, c, d, e | |
1809 | #ifdef AFS_SGI65_ENV | |
1810 | , f | |
1811 | #endif | |
1812 | ); | |
1813 | AFS_GUNLOCK(); | |
1814 | return rv; | |
1815 | } | |
1816 | ||
1817 | ||
1818 | struct vnodeops Afs_vnodeops = { | |
1819 | #ifdef AFS_SGI64_ENV | |
1820 | #ifdef AFS_SGI65_ENV | |
1821 | BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE), | |
1822 | #else | |
1823 | VNODE_POSITION_BASE, | |
1824 | #endif | |
1825 | #endif | |
1826 | mp_afs_open, | |
1827 | mp_afs_close, | |
1828 | mp_afs_read, | |
1829 | mp_afs_write, | |
1830 | mp_afs_ioctl, | |
1831 | mp_fs_setfl, | |
1832 | mp_afs_getattr, | |
1833 | mp_afs_setattr, | |
1834 | mp_afs_access, | |
1835 | mp_afs_lookup, | |
1836 | mp_afs_create, | |
1837 | mp_afs_remove, | |
1838 | mp_afs_link, | |
1839 | mp_afs_rename, | |
1840 | mp_afs_mkdir, | |
1841 | mp_afs_rmdir, | |
1842 | mp_afs_readdir, | |
1843 | mp_afs_symlink, | |
1844 | mp_afs_readlink, | |
1845 | mp_afs_fsync, | |
1846 | mp_afs_inactive, | |
1847 | mp_afs_fid, | |
1848 | mp_afs_fid2, | |
1849 | mp_afs_rwlock, | |
1850 | mp_afs_rwunlock, | |
1851 | mp_afs_seek, | |
1852 | mp_fs_cmp, | |
1853 | mp_afs_frlock, | |
1854 | fs_nosys, /* realvp */ | |
1855 | mp_afs_bmap, | |
1856 | mp_afs_strategy, | |
1857 | mp_afs_map, | |
1858 | #ifdef AFS_SGI65_ENV | |
1859 | fs_noerr, /* addmap - devices only */ | |
1860 | fs_noerr, /* delmap - devices only */ | |
1861 | #else | |
1862 | mp_afs_addmap, | |
1863 | mp_afs_delmap, | |
1864 | #endif | |
1865 | mp_fs_poll, /* poll */ | |
1866 | fs_nosys, /* dump */ | |
1867 | fs_pathconf, | |
1868 | fs_nosys, /* allocstore */ | |
1869 | fs_nosys, /* fcntl */ | |
1870 | afs_reclaim, /* reclaim */ | |
1871 | fs_nosys, /* attr_get */ | |
1872 | fs_nosys, /* attr_set */ | |
1873 | fs_nosys, /* attr_remove */ | |
1874 | fs_nosys, /* attr_list */ | |
1875 | #ifdef AFS_SGI64_ENV | |
1876 | #ifdef AFS_SGI65_ENV | |
1877 | fs_cover, | |
1878 | (vop_link_removed_t) fs_noval, | |
1879 | fs_vnode_change, | |
1880 | fs_tosspages, | |
1881 | fs_flushinval_pages, | |
1882 | fs_flush_pages, | |
1883 | fs_invalfree_pages, | |
1884 | fs_pages_sethole, | |
1885 | (vop_commit_t) fs_nosys, | |
1886 | (vop_readbuf_t) fs_nosys, | |
1887 | fs_strgetmsg, | |
1888 | fs_strputmsg, | |
1889 | #else | |
1890 | fs_mount, | |
1891 | #endif | |
1892 | #endif | |
1893 | }; | |
1894 | struct vnodeops *afs_ops = &Afs_vnodeops; | |
1895 | #endif /* MP */ | |
1896 | ||
1897 | ||
1898 | /* Support for XFS caches. The assumption here is that the size of | |
1899 | * a cache file also does not exceed 32 bits. | |
1900 | */ | |
1901 | ||
1902 | /* Initialized in osi_InitCacheFSType(). Used to determine inode type. */ | |
1903 | vnodeops_t *afs_xfs_vnodeopsp; | |
1904 | ||
1905 | ino_t | |
1906 | VnodeToIno(vnode_t * vp) | |
1907 | { | |
1908 | int code; | |
1909 | struct vattr vattr; | |
1910 | ||
1911 | vattr.va_mask = AT_FSID | AT_NODEID; /* quick return using this mask. */ | |
1912 | AFS_GUNLOCK(); | |
1913 | AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code); | |
1914 | AFS_GLOCK(); | |
1915 | if (code) { | |
1916 | osi_Panic("VnodeToIno"); | |
1917 | } | |
1918 | return vattr.va_nodeid; | |
1919 | } | |
1920 | ||
1921 | dev_t | |
1922 | VnodeToDev(vnode_t * vp) | |
1923 | { | |
1924 | int code; | |
1925 | struct vattr vattr; | |
1926 | ||
1927 | vattr.va_mask = AT_FSID | AT_NODEID; /* quick return using this mask. */ | |
1928 | AFS_GUNLOCK(); | |
1929 | AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code); | |
1930 | AFS_GLOCK(); | |
1931 | if (code) { | |
1932 | osi_Panic("VnodeToDev"); | |
1933 | } | |
1934 | return (dev_t) vattr.va_fsid; | |
1935 | } | |
1936 | ||
1937 | off_t | |
1938 | VnodeToSize(vnode_t * vp) | |
1939 | { | |
1940 | int code; | |
1941 | struct vattr vattr; | |
1942 | ||
1943 | vattr.va_mask = AT_SIZE; | |
1944 | AFS_GUNLOCK(); | |
1945 | AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code); | |
1946 | AFS_GLOCK(); | |
1947 | if (code) { | |
1948 | osi_Panic("VnodeToSize"); | |
1949 | } | |
1950 | return vattr.va_size; | |
1951 | } | |
1952 | #endif /* AFS_SGI62_ENV */ |