Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / IRIX / osi_vnodeops.c
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 */