Translate faultcode_t return values from vm routines into errno codes.
[openafs.git] / src / afs / SOLARIS / 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 #include <afsconfig.h>
11 #include "../afs/param.h"
12
13 RCSID("$Header$");
14
15 #if     defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
16 /*
17  * SOLARIS/osi_vnodeops.c
18  *
19  * Implements:
20  *
21  * Functions: AFS_TRYUP, _init, _info, _fini, afs_addmap, afs_delmap,
22  * afs_vmread, afs_vmwrite, afs_getpage, afs_GetOnePage, afs_putpage,
23  * afs_putapage, afs_nfsrdwr, afs_map, afs_PageLeft, afs_pathconf/afs_cntl,
24  * afs_ioctl, afs_rwlock, afs_rwunlock, afs_seek, afs_space, afs_dump,
25  * afs_cmp, afs_realvp, afs_pageio, afs_dumpctl, afs_dispose, afs_setsecattr,
26  * afs_getsecattr, gafs_open, gafs_close, gafs_getattr, gafs_setattr,
27  * gafs_access, gafs_lookup, gafs_create, gafs_remove, gafs_link,
28  * gafs_rename, gafs_mkdir, gafs_rmdir, gafs_readdir, gafs_symlink,
29  * gafs_readlink, gafs_fsync, afs_inactive, gafs_inactive, gafs_fid
30  *
31  *
32  * Variables: Afs_vnodeops
33  *
34  */
35 #include "../afs/sysincludes.h" /* Standard vendor system headers */
36 #include "../afs/afsincludes.h" /* Afs-based standard headers */
37 #include "../afs/afs_stats.h"  /* statistics */
38 #include "../afs/nfsclient.h"  
39
40
41 #include <sys/mman.h>
42 #include <vm/hat.h>
43 #include <vm/as.h>
44 #include <vm/page.h>
45 #include <vm/pvn.h>
46 #include <vm/seg.h>
47 #include <vm/seg_map.h>
48 #include <vm/seg_vn.h>
49 #include <vm/rm.h>
50 #if     defined(AFS_SUN5_ENV) 
51 #include <sys/modctl.h>
52 #include <sys/syscall.h>
53 #else
54 #include <vm/swap.h>
55 #endif
56 #include <sys/debug.h>
57 #if     defined(AFS_SUN5_ENV)
58 #include <sys/fs_subr.h>
59 #endif
60
61 #if     defined(AFS_SUN5_ENV)
62 /* 
63  * XXX Temporary fix for problems with Solaris rw_tryupgrade() lock.
64  * It isn't very persistent in getting the upgrade when others are
65  * waiting for it and returns 0.  So the UpgradeSToW() macro that the
66  * rw_tryupgrade used to map to wasn't good enough and we need to use
67  * the following code instead.  Obviously this isn't the proper place
68  * for it but it's only called from here for now
69  * 
70  */
71 #ifndef AFS_SUN54_ENV
72 AFS_TRYUP(lock)
73      afs_rwlock_t *lock;
74 {
75     if (!rw_tryupgrade(lock)) {
76         rw_exit(lock);
77         rw_enter(lock, RW_WRITER);
78     }
79 }
80 #endif
81 #endif
82
83
84 /* Translate a faultcode_t as returned by some of the vm routines
85  * into a suitable errno value.
86  */
87 static int
88 afs_fc2errno(faultcode_t fc)
89 {
90     switch (FC_CODE(fc)) {
91     case 0:
92         return 0;
93
94     case FC_OBJERR:
95         return FC_ERRNO(fc);
96
97     default:
98         return EIO;
99     }
100 }
101
102
103 extern struct as kas;   /* kernel addr space */
104 extern unsigned char *afs_indexFlags;          
105 extern afs_lock_t afs_xdcache;          
106
107 /* Additional vnodeops for SunOS 4.0.x */
108 int afs_nfsrdwr(), afs_getpage(), afs_putpage(), afs_map();
109 int afs_dump(), afs_cmp(), afs_realvp(), afs_GetOnePage();
110
111 int afs_pvn_vptrunc;
112
113 #ifdef  AFS_SUN5_ENV
114
115 int afs_addmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
116     register struct vnode *avp;
117     offset_t offset;
118     struct as *asp;
119     caddr_t addr;
120     int length, prot, maxprot, flags;
121     struct AFS_UCRED *credp;
122 {
123     /* XXX What should we do here?? XXX */
124     return (0);
125 }
126
127 int afs_delmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
128     register struct vnode *avp;
129     offset_t offset;
130     struct as *asp;
131     caddr_t addr;
132     int length, prot, maxprot, flags;
133     struct AFS_UCRED *credp;
134 {
135     /* XXX What should we do here?? XXX */
136     return (0);
137 }
138
139 int afs_vmread(avp, auio, ioflag, acred)
140     register struct vnode *avp;
141     struct uio *auio;
142     int ioflag;
143     struct AFS_UCRED *acred;
144 {
145     register int code;
146
147     if (!RW_READ_HELD(&(VTOAFS(avp))->rwlock))
148         osi_Panic("afs_vmread: !rwlock");
149     AFS_GLOCK();
150     code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_READ, ioflag, acred);
151     AFS_GUNLOCK();
152     return code;
153 }
154
155
156 int afs_vmwrite(avp, auio, ioflag, acred)
157     register struct vnode *avp;
158     struct uio *auio;
159     int ioflag;
160     struct AFS_UCRED *acred;
161 {
162     register int code;
163
164     if (!RW_WRITE_HELD(&(VTOAFS(avp))->rwlock))
165         osi_Panic("afs_vmwrite: !rwlock");
166     AFS_GLOCK();
167     code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_WRITE, ioflag, acred);
168     AFS_GUNLOCK();
169     return code;
170 }
171
172 #endif  /* AFS_SUN5_ENV */
173
174 int afs_getpage(vp, off, len, protp, pl, plsz, seg, addr, rw, acred)
175 struct vnode *vp;
176 u_int len;
177 u_int *protp;
178 struct page *pl[];
179 u_int plsz;
180 struct seg *seg;
181 #ifdef  AFS_SUN5_ENV
182 offset_t off;
183 caddr_t addr;
184 #else
185 u_int off;
186 addr_t addr;
187 #endif
188 enum seg_rw rw;
189 struct AFS_UCRED *acred;
190 {
191     register afs_int32 code = 0;
192     AFS_STATCNT(afs_getpage);
193
194 #ifdef  AFS_SUN5_ENV
195     if (vp->v_flag & VNOMAP)    /* File doesn't allow mapping */
196         return (ENOSYS);
197 #endif
198
199     AFS_GLOCK();
200
201 #if     defined(AFS_SUN56_ENV)
202     if (len <= PAGESIZE)
203         code = afs_GetOnePage(vp, off, len, protp, pl, plsz,
204                               seg, addr, rw, acred);
205 #else
206 #ifdef  AFS_SUN5_ENV
207     if (len <= PAGESIZE)
208         code = afs_GetOnePage(vp, (u_int)off, len, protp, pl, plsz,
209                               seg, addr, rw, acred);
210 #else
211     if (len == PAGESIZE)
212         code = afs_GetOnePage(vp, off, protp, pl, plsz,
213                               seg, addr, rw, acred);
214 #endif
215 #endif
216     else {
217         struct vcache *vcp = VTOAFS(vp);
218 #ifdef  AFS_SUN5_ENV
219         ObtainWriteLock(&vcp->vlock, 548);
220         vcp->multiPage++;
221         ReleaseWriteLock(&vcp->vlock);
222 #endif
223         afs_BozonLock(&vcp->pvnLock, vcp);
224 #if     defined(AFS_SUN56_ENV)
225         code = pvn_getpages(afs_GetOnePage, vp, off, 
226                             len, protp, pl, plsz, seg, addr, rw, acred);
227 #else
228         code = pvn_getpages(afs_GetOnePage, vp, (u_int)off, 
229                             len, protp, pl, plsz, seg, addr, rw, acred);
230 #endif
231         afs_BozonUnlock(&vcp->pvnLock, vcp);
232 #ifdef  AFS_SUN5_ENV
233         ObtainWriteLock(&vcp->vlock, 549);
234         vcp->multiPage--;
235         ReleaseWriteLock(&vcp->vlock);
236 #endif
237     }
238     AFS_GUNLOCK();
239     return code;
240 }
241
242 /* Return all the pages from [off..off+len) in file */
243 #ifdef  AFS_SUN5_ENV
244 int afs_GetOnePage(vp, off, alen, protp, pl, plsz, seg, addr, rw, acred)
245 u_int alen;
246 #else
247 int afs_GetOnePage(vp, off, protp, pl, plsz, seg, addr, rw, acred)
248 #endif
249 struct vnode *vp;
250 #if     defined(AFS_SUN56_ENV)
251 u_offset_t off;
252 #else
253 u_int off;
254 #endif
255 u_int *protp;
256 struct page *pl[];
257 u_int plsz;
258 struct seg *seg;
259 #ifdef  AFS_SUN5_ENV
260 caddr_t addr;
261 #else
262 addr_t addr;
263 #endif
264 enum seg_rw rw;
265 struct AFS_UCRED *acred;
266 {
267     register struct page *page;
268     register afs_int32 code = 0;
269     u_int len;
270     struct buf *buf;
271     afs_int32 tlen;
272     register struct vcache *avc;
273     register struct dcache *tdc;
274     int i, s, pexists;
275     int slot;
276     afs_size_t offset, nlen;
277     struct vrequest treq;
278     afs_int32 mapForRead = 0, Code=0;
279 #if     defined(AFS_SUN56_ENV)
280     u_offset_t  toffset;
281 #else
282     afs_int32       toffset;
283 #endif
284
285     if (!acred) 
286 #ifdef  AFS_SUN5_ENV
287         osi_Panic("GetOnePage: !acred");
288 #else
289         acred = u.u_cred;               /* better than nothing */
290 #endif
291
292     avc = VTOAFS(vp);   /* cast to afs vnode */
293
294 #ifdef  AFS_SUN5_ENV
295     if (avc->credp /*&& AFS_NFSXLATORREQ(acred)*/ && AFS_NFSXLATORREQ(avc->credp)) {
296         acred = avc->credp;
297     }
298 #endif
299     if (code = afs_InitReq(&treq, acred)) return code;
300
301     if (!pl) {
302         /* This is a read-ahead request, e.g. due to madvise.  */
303 #ifdef  AFS_SUN5_ENV
304         int plen = alen;
305 #else
306         int plen = PAGESIZE;
307 #endif
308         ObtainReadLock(&avc->lock);
309
310         while (plen > 0 && !afs_BBusy()) {
311             /* Obtain a dcache entry at off.  2 means don't fetch data. */
312             tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 2);
313             if (!tdc) break;
314
315             /* Write-lock the dcache entry, if we don't succeed, just go on */
316             if (0 != NBObtainWriteLock(&tdc->lock, 642)) {
317                 afs_PutDCache(tdc);
318                 goto next_prefetch;
319             }
320
321             /* If we aren't already fetching this dcache entry, queue it */
322             if (!(tdc->mflags & DFFetchReq)) {
323                 struct brequest *bp;
324
325                 tdc->mflags |= DFFetchReq;
326                 bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
327                                 (afs_size_t) off, (afs_size_t) 1, tdc);
328                 if (!bp) {
329                     /* Unable to start background fetch; might as well stop */
330                     tdc->mflags &= ~DFFetchReq;
331                     ReleaseWriteLock(&tdc->lock);
332                     afs_PutDCache(tdc);
333                     break;
334                 }
335                 ReleaseWriteLock(&tdc->lock);
336             } else {
337                 ReleaseWriteLock(&tdc->lock);
338                 afs_PutDCache(tdc);
339             }
340
341 next_prefetch:
342             /* Adjust our offset and remaining length values */
343             off += nlen;
344             plen -= nlen;
345
346             /* If we aren't making progress for some reason, bail out */
347             if (nlen <= 0) break;
348         }
349
350         ReleaseReadLock(&avc->lock);
351         return 0;
352     }
353
354     len = PAGESIZE;
355     pl[0] = NULL;                       /* Make sure it's empty */
356
357     /* first, obtain the proper lock for the VM system */
358
359     /* if this is a read request, map the page in read-only.  This will
360      * allow us to swap out the dcache entry if there are only read-only
361      * pages created for the chunk, which helps a *lot* when dealing
362      * with small caches.  Otherwise, we have to invalidate the vm
363      * pages for the range covered by a chunk when we swap out the
364      * chunk.
365      */
366     if (rw == S_READ || rw == S_EXEC) 
367         mapForRead = 1;
368
369     if (protp) *protp = PROT_ALL;
370 #ifndef AFS_SUN5_ENV
371     if (AFS_NFSXLATORREQ(acred)) {
372         if (rw == S_READ) {
373             if (!afs_AccessOK(avc, PRSFS_READ, &treq,
374                               CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ)) {
375                 return EACCES;
376             }
377         }
378     }
379 #endif
380
381 retry:
382 #ifdef  AFS_SUN5_ENV
383     if (rw == S_WRITE || rw == S_CREATE)
384         tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 5);
385     else
386         tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 1);
387     if (!tdc) return EINVAL;
388 #endif
389     code = afs_VerifyVCache(avc, &treq);
390     if (code) {
391 #ifdef  AFS_SUN5_ENV
392         afs_PutDCache(tdc);
393 #endif  
394         return afs_CheckCode(code, &treq, 44); /* failed to get it */
395     }
396
397     afs_BozonLock(&avc->pvnLock, avc);
398     ObtainReadLock(&avc->lock);
399
400     afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, (afs_int32) vp,
401                 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off), 
402                 ICL_TYPE_LONG, len,
403                 ICL_TYPE_LONG, (int) rw);
404
405     tlen = len;
406     slot = 0;
407     toffset = off;
408 #ifdef  AFS_SUN5_ENV
409     /* Check to see if we're in the middle of a VM purge, and if we are, release
410      * the locks and try again when the VM purge is done. */
411     ObtainWriteLock(&avc->vlock, 550);
412     if (avc->activeV) {
413         ReleaseReadLock(&avc->lock); 
414         ReleaseWriteLock(&avc->vlock); 
415         afs_BozonUnlock(&avc->pvnLock, avc);
416         afs_PutDCache(tdc);
417         /* Check activeV again, it may have been turned off
418          * while we were waiting for a lock in afs_PutDCache */
419         ObtainWriteLock(&avc->vlock, 574);
420         if (avc->activeV) {
421             avc->vstates |= VRevokeWait;
422             ReleaseWriteLock(&avc->vlock);
423             afs_osi_Sleep(&avc->vstates);
424         } else {
425             ReleaseWriteLock(&avc->vlock);
426         }
427         goto retry;
428     }
429     ReleaseWriteLock(&avc->vlock); 
430 #endif
431
432     /* We're about to do stuff with our dcache entry..  Lock it. */
433     ObtainReadLock(&tdc->lock);
434
435     /* Check to see whether the cache entry is still valid */
436     if (!(avc->states & CStatd)
437         || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
438         ReleaseReadLock(&tdc->lock);
439         ReleaseReadLock(&avc->lock); 
440         afs_BozonUnlock(&avc->pvnLock, avc);
441         afs_PutDCache(tdc);
442         goto retry;
443     }
444
445     AFS_GUNLOCK();
446     while (1) { /* loop over all pages */
447         /* now, try to find the page in memory (it may already be intransit or laying
448            around the free list */
449         page = page_lookup( vp, toffset, (rw == S_CREATE ? SE_EXCL : SE_SHARED) );
450         if (page) 
451             goto nextpage;
452
453         /* if we make it here, we can't find the page in memory.  Do a real disk read
454            from the cache to get the data */
455         Code |= 0x200;          /* XXX */
456 #ifdef  AFS_SUN5_ENV
457 #if     defined(AFS_SUN54_ENV)
458         /* use PG_EXCL because we know the page does not exist already.  If it 
459          * actually does exist, we have somehow raced between lookup and create.
460          * As of 4/98, that shouldn't be possible, but we'll be defensive here
461          * in case someone tries to relax all the serialization of read and write
462          * operations with harmless things like stat. */
463 #if    defined(AFS_SUN58_ENV)
464         page = page_create_va(vp, toffset, PAGESIZE, PG_WAIT|PG_EXCL, seg, addr);
465 #else
466         page = page_create_va(vp, toffset, PAGESIZE, PG_WAIT|PG_EXCL, seg->s_as, addr);
467 #endif
468 #else
469         page = page_create(vp, toffset, PAGESIZE, PG_WAIT);
470 #endif
471         if (!page) {
472             continue;
473         }
474         if (alen < PAGESIZE)
475             pagezero(page, alen, PAGESIZE-alen); 
476 #else
477         page = rm_allocpage(seg, addr, PAGESIZE, 1);    /* can't fail */
478         if (!page) osi_Panic("afs_getpage alloc page");
479         /* we get a circularly-linked list of pages back, but we expect only
480            one, since that's what we asked for */
481         if (page->p_next != page) osi_Panic("afs_getpage list");
482         /* page enter returns a locked page; we'll drop the lock as a side-effect
483            of the pvn_done done by afs_ustrategy.  If we decide not to call
484            strategy, we must be sure to call pvn_fail, at least, to release the
485            page locks and otherwise reset the pages.  The page, while locked, is
486            not held, for what it is worth */
487         page->p_intrans = 1;    /* set appropriate flags */
488         page->p_pagein = 1;
489         /* next call shouldn't fail, since we have pvnLock set */
490         if (page_enter(page, vp, toffset)) osi_Panic("afs_getpage enter race");
491 #endif  /* AFS_SUN5_ENV */
492
493 #ifdef  AFS_SUN5_ENV
494         if (rw == S_CREATE) {
495             /* XXX Don't read from AFS in write only cases XXX */
496             page_io_unlock(page);
497         } else 
498 #else
499         if (0) {
500             /* XXX Don't read from AFS in write only cases XXX */
501             page->p_intrans = page->p_pagein = 0;
502             page_unlock(page);  /* XXX */
503         } else 
504 #endif
505             {
506 #ifndef AFS_SUN5_ENV
507             PAGE_HOLD(page);
508 #endif
509             /* now it is time to start I/O operation */
510             buf = pageio_setup(page, PAGESIZE, vp, B_READ);     /* allocate a buf structure */
511 #if     defined(AFS_SUN5_ENV)
512             buf->b_edev = 0;
513 #endif
514             buf->b_dev = 0;
515             buf->b_blkno = btodb(toffset);
516             bp_mapin(buf);              /* map it in to our address space */
517
518 #if     defined(AFS_SUN5_ENV)
519             AFS_GLOCK();
520             /* afs_ustrategy will want to lock the dcache entry */
521             ReleaseReadLock(&tdc->lock);
522             code = afs_ustrategy(buf, acred);   /* do the I/O */
523             ObtainReadLock(&tdc->lock);
524             AFS_GUNLOCK();
525 #else
526             ReleaseReadLock(&tdc->lock);
527             ReleaseReadLock(&avc->lock);
528             code = afs_ustrategy(buf);  /* do the I/O */
529             ObtainReadLock(&avc->lock);
530             ObtainReadLock(&tdc->lock);
531 #endif
532
533 #ifdef  AFS_SUN5_ENV
534             /* Before freeing unmap the buffer */
535             bp_mapout(buf);
536             pageio_done(buf);
537 #endif
538             if (code) {
539 #ifndef AFS_SUN5_ENV
540                 PAGE_RELE(page);
541 #endif
542                 goto bad;
543             }
544 #ifdef  AFS_SUN5_ENV
545             page_io_unlock(page);
546 #endif
547         }
548
549         /* come here when we have another page (already held) to enter */
550       nextpage:
551         /* put page in array and continue */
552 #ifdef  AFS_SUN5_ENV
553         /* The p_selock must be downgraded to a shared lock after the page is read */
554 #if     defined(AFS_SUN56_ENV)
555         if ((rw != S_CREATE) && !(PAGE_SHARED(page))) 
556 #else
557         if ((rw != S_CREATE) && !(se_shared_assert(&page->p_selock))) 
558 #endif
559         {
560             page_downgrade(page);
561         }
562 #endif
563         pl[slot++] = page;
564 #ifdef  AFS_SUN5_ENV
565         code = page_iolock_assert(page);
566 #endif
567         code = 0;
568         toffset += PAGESIZE;
569         addr += PAGESIZE;
570         tlen -= PAGESIZE;
571         if (tlen <= 0) break;   /* done all the pages */
572     } /* while (1) ... */
573
574     AFS_GLOCK();
575     pl[slot] = (struct page *) 0;
576     ReleaseReadLock(&tdc->lock);
577
578     /* Prefetch next chunk if we're at a chunk boundary */
579     if (AFS_CHUNKOFFSET(off) == 0) {
580         if (!(tdc->mflags & DFNextStarted))
581             afs_PrefetchChunk(avc, tdc, acred, &treq);
582     }
583
584     ReleaseReadLock(&avc->lock);
585 #ifdef  AFS_SUN5_ENV
586     ObtainWriteLock(&afs_xdcache,246);
587     if (!mapForRead) {
588         /* track that we have dirty (or dirty-able) pages for this chunk. */
589         afs_indexFlags[tdc->index] |= IFDirtyPages;
590     }
591     afs_indexFlags[tdc->index] |= IFAnyPages;
592     ReleaseWriteLock(&afs_xdcache);
593 #endif
594     afs_BozonUnlock(&avc->pvnLock, avc);
595 #ifdef  AFS_SUN5_ENV
596     afs_PutDCache(tdc);
597 #endif
598     afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, (int)page, 
599                ICL_TYPE_LONG, Code);
600     return 0;
601
602   bad:
603     AFS_GLOCK();
604     afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, (int)page, 
605                ICL_TYPE_LONG, Code);
606     /* release all pages, drop locks, return code */
607 #ifdef  AFS_SUN5_ENV
608     if (page) 
609         pvn_read_done(page, B_ERROR);
610 #else
611     for(i=0; i<slot; i++)
612         PAGE_RELE(pl[i]);
613 #endif
614     ReleaseReadLock(&avc->lock);
615     afs_BozonUnlock(&avc->pvnLock, avc);
616 #ifdef  AFS_SUN5_ENV
617     ReleaseReadLock(&tdc->lock);
618     afs_PutDCache(tdc);
619 #endif
620     return code;
621 }
622
623 #ifdef  AFS_SUN5_ENV
624 int afs_putpage(vp, off, len, flags, cred)
625     struct vnode *vp;
626     offset_t off;
627     u_int len;
628     int flags;
629     struct AFS_UCRED *cred;
630 {
631     struct vcache *avc;
632     struct page *pages;
633     afs_int32 code = 0;
634 #if    defined(AFS_SUN58_ENV)
635     size_t tlen;
636 #else
637     afs_int32 tlen;
638 #endif
639     afs_offs_t endPos;
640     afs_int32 NPages=0;
641 #if     defined(AFS_SUN56_ENV)
642     u_offset_t toff = off;
643 #else
644     int toff = (int)off;
645 #endif
646     int didWriteLock;
647
648     AFS_STATCNT(afs_putpage);
649     if (vp->v_flag & VNOMAP)            /* file doesn't allow mapping */
650         return (ENOSYS);
651
652     /*
653      * Putpage (ASYNC) is called every sec to flush out dirty vm pages 
654      */
655     AFS_GLOCK();
656     afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER, (afs_int32) vp,
657                 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
658                 ICL_TYPE_INT32, (afs_int32) len,
659                 ICL_TYPE_LONG, (int) flags);
660     avc = VTOAFS(vp);
661     afs_BozonLock(&avc->pvnLock, avc);
662     ObtainSharedLock(&avc->lock,247);
663     didWriteLock = 0;
664
665     /* Get a list of modified (or whatever) pages */
666     if (len) {
667         endPos = (afs_offs_t)off + len;         /* position we're supposed to write up to */
668         while ((afs_offs_t)toff < endPos && (afs_offs_t)toff < avc->m.Length) {
669             /* If not invalidating pages use page_lookup_nowait to avoid reclaiming
670              * them from the free list
671              */
672             AFS_GUNLOCK();
673             if (flags & (B_FREE|B_INVAL))
674                 pages = page_lookup(vp, toff, SE_EXCL);
675             else
676                 pages = page_lookup_nowait(vp, toff, SE_SHARED);
677             if (!pages || !pvn_getdirty(pages, flags)) 
678                 tlen = PAGESIZE;
679             else {
680                 if (!didWriteLock) {
681                     AFS_GLOCK();
682                     didWriteLock = 1;
683                     UpgradeSToWLock(&avc->lock, 671);
684                     AFS_GUNLOCK();
685                 }
686                 NPages++;
687                 code = afs_putapage(vp, pages, &toff, &tlen, flags, cred);
688                 if (code) {
689                     AFS_GLOCK();
690                     break;
691                 }
692             }
693             toff += tlen;
694             AFS_GLOCK();
695         }
696     } else {
697         if (!didWriteLock) {
698             UpgradeSToWLock(&avc->lock, 670);
699             didWriteLock = 1;
700         }
701
702         AFS_GUNLOCK();
703 #if     defined(AFS_SUN56_ENV) 
704         code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
705 #else
706         code = pvn_vplist_dirty(vp, (u_int)off, afs_putapage, flags, cred);
707 #endif
708         AFS_GLOCK();
709     }
710
711     if (code && !avc->vc_error) {
712         if (!didWriteLock) {
713             UpgradeSToWLock(&avc->lock, 669);
714             didWriteLock = 1;
715         }
716         avc->vc_error = code;
717     }
718
719     if (didWriteLock)
720         ReleaseWriteLock(&avc->lock);
721     else
722         ReleaseSharedLock(&avc->lock);
723     afs_BozonUnlock(&avc->pvnLock, avc);
724     afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, NPages);
725     AFS_GUNLOCK();
726     return (code);
727 }
728
729
730 int afs_putapage(struct vnode *vp, struct page *pages,
731 #if     defined(AFS_SUN56_ENV)
732                  u_offset_t *offp,
733 #else
734                  u_int *offp,
735 #endif
736 #if    defined(AFS_SUN58_ENV)
737                  size_t *lenp,
738 #else
739                  u_int *lenp,
740 #endif
741                  int flags, struct AFS_UCRED *credp)
742 {
743     struct buf *tbuf;
744     struct vcache *avc = VTOAFS(vp);
745     afs_int32 code = 0;
746     u_int tlen = PAGESIZE;
747     afs_offs_t off = (pages->p_offset/PAGESIZE)*PAGESIZE;
748
749     /*
750      * Now we've got the modified pages.  All pages are locked and held 
751      * XXX Find a kluster that fits in one block (or page). We also
752      * adjust the i/o if the file space is less than a while page. XXX
753      */
754     if (off + tlen > avc->m.Length) {
755         tlen = avc->m.Length - off;
756     }
757     /* can't call mapout with 0 length buffers (rmfree panics) */
758     if (((tlen>>24)&0xff) == 0xff) {
759         tlen = 0;
760     }
761     if ((int)tlen > 0) {
762         /*
763          * Can't call mapout with 0 length buffers since we'll get rmfree panics
764          */
765         tbuf = pageio_setup(pages, tlen, vp, B_WRITE | flags);
766         if (!tbuf) return (ENOMEM);
767
768         tbuf->b_dev = 0;
769         tbuf->b_blkno = btodb(pages->p_offset);
770         bp_mapin(tbuf);
771         AFS_GLOCK();
772         afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUTONE, ICL_TYPE_LONG, avc, 
773                 ICL_TYPE_LONG, pages,
774                 ICL_TYPE_LONG, tlen, 
775                 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off));
776         code = afs_ustrategy(tbuf, credp);      /* unlocks page */
777         AFS_GUNLOCK();
778         bp_mapout(tbuf);
779     }
780     pvn_write_done(pages, ((code) ? B_ERROR:0) | B_WRITE | flags);
781     if ((int)tlen > 0)
782         pageio_done(tbuf);
783     if (offp) *offp = off;
784     if (lenp) *lenp = tlen;
785     return code;
786 }
787
788 #else   AFS_SUN5_ENV
789
790 int afs_putpage(vp, off, len, flags, cred)
791 struct vnode *vp;
792 u_int off;
793 u_int len;
794 int flags;
795 struct AFS_UCRED *cred;
796 {
797     int wholeEnchilada; /* true if we must get all of the pages */
798     struct vcache *avc;
799     struct page *pages;
800     struct page *tpage;
801     struct buf *tbuf;
802     afs_int32 tlen;
803     afs_int32 code = 0, rcode;
804     afs_int32 poffset;
805     afs_int32 clusterStart, clusterEnd, endPos;
806
807     /* In the wholeEnchilada case, we must ensure that we get all of the pages
808        from the system, since we're doing this to shutdown the use of a vnode */
809
810     AFS_STATCNT(afs_putpage);
811     wholeEnchilada = (off == 0 && len == 0 && (flags & (B_INVAL|B_ASYNC)) == B_INVAL);
812
813     avc = VTOAFS(vp);
814     afs_BozonLock(&avc->pvnLock, avc);
815     ObtainWriteLock(&avc->lock,248);
816
817     while (1) {
818         /* in whole enchilada case, loop until call to pvn_getdirty can't find
819            any more modified pages */
820
821         /* first we try to get a list of modified (or whatever) pages */
822         if (len == 0) {
823             pages = pvn_vplist_dirty(vp, off, flags);
824         }
825         else {
826             endPos = off + len; /* position we're supposed to write up to */
827             if (endPos > avc->m.Length) endPos = avc->m.Length; /* bound by this */
828             clusterStart = off & ~(PAGESIZE-1); /* round down to nearest page */
829             clusterEnd = ((endPos-1) | (PAGESIZE-1))+1; /* round up to nearest page */
830             pages = pvn_range_dirty(vp, off, endPos, clusterStart, clusterEnd, flags);
831         }
832         
833         /* Now we've got the modified pages.  All pages are locked and held */
834         rcode = 0;              /* return code */
835         while(pages) {  /* look over all pages in the returned set */
836             tpage = pages;      /* get first page in the list */
837
838             /* write out the page */
839             poffset = tpage->p_offset;  /* where the page starts in the file */
840             /* tlen will represent the end of the range to write, for a while */
841             tlen = PAGESIZE+poffset;    /* basic place to end tpage write */
842             /* but we also don't want to write past end of off..off+len range */
843             if (len != 0 && tlen > off+len) tlen = off+len;
844             /* and we don't want to write past the end of the file */
845             if (tlen > avc->m.Length) tlen = avc->m.Length;
846             /* and we don't want to write at all if page starts after end */
847             if (poffset >= tlen) {
848                 pvn_fail(pages, B_WRITE | flags);
849                 goto done;
850             }
851             /* finally change tlen from end position to length */
852             tlen -= poffset;    /* compute bytes to write from this page */
853             page_sub(&pages, tpage);    /* remove tpage from "pages" list */
854             tbuf = pageio_setup(tpage, tlen, vp, B_WRITE | flags);
855             if (!tbuf) {
856                 pvn_fail(tpage, B_WRITE|flags);
857                 pvn_fail(pages, B_WRITE|flags);
858                 goto done;
859             }
860             tbuf->b_dev = 0;
861             tbuf->b_blkno = btodb(tpage->p_offset);
862             bp_mapin(tbuf);
863             ReleaseWriteLock(&avc->lock);       /* can't hold during strategy call */
864             code = afs_ustrategy(tbuf);         /* unlocks page */
865             ObtainWriteLock(&avc->lock,249);    /* re-obtain */
866             if (code) {
867                 /* unlocking of tpage is done by afs_ustrategy */
868                 rcode = code;
869                 if (pages)      /* may have already removed last page */
870                     pvn_fail(pages, B_WRITE|flags);
871                 goto done;
872             }
873         }       /* for (tpage=pages....) */
874
875         /* see if we've gotten all of the pages in the whole enchilada case */
876         if (!wholeEnchilada || !vp->v_pages) break;
877     }   /* while(1) obtaining all pages */
878
879     /*
880      * If low on chunks, and if writing the last byte of a chunk, try to
881      * free some.  Note that afs_DoPartialWrite calls osi_SyncVM which now
882      * calls afs_putpage, so this is recursion.  It stops there because we
883      * insist on len being non-zero.
884      */
885     if (afs_stats_cmperf.cacheCurrDirtyChunks > afs_stats_cmperf.cacheMaxDirtyChunks
886         && len != 0 && AFS_CHUNKOFFSET((off + len)) == 0)  {
887         struct vrequest treq;
888         if (!afs_InitReq(&treq, cred ? cred : u.u_cred)) {
889             rcode = afs_DoPartialWrite(avc, &treq);     /* XXX */
890         }
891     }
892     
893   done:
894
895     if (rcode && !avc->vc_error)
896         avc->vc_error = rcode;
897
898     /* when we're here, we just return code. */
899     ReleaseWriteLock(&avc->lock);
900     afs_BozonUnlock(&avc->pvnLock, avc);
901     return rcode;
902 }
903
904 #endif  /* AFS_SUN5_ENV */
905
906 int afs_nfsrdwr(avc, auio, arw, ioflag, acred)
907 register struct vcache *avc;
908 struct uio *auio;
909 enum uio_rw arw;
910 int ioflag;
911 struct AFS_UCRED *acred;
912 {
913     register afs_int32 code;
914     afs_int32 code2;
915     int counter;
916     afs_int32 mode, sflags;
917     register char *data;
918     struct dcache *dcp, *dcp_newpage;
919     afs_size_t fileBase, size;
920     afs_size_t pageBase;
921     register afs_int32 tsize;
922     register afs_int32 pageOffset, extraResid=0;
923     register afs_size_t origLength;             /* length when reading/writing started */
924     register long appendLength;         /* length when this call will finish */
925     int created;                        /* created pages instead of faulting them */
926     int lockCode;
927     int didFakeOpen, eof;
928     struct vrequest treq;
929     caddr_t raddr;
930     u_int rsize;
931
932     AFS_STATCNT(afs_nfsrdwr);
933
934     /* can't read or write other things */
935     if (vType(avc) != VREG) return EISDIR;
936
937     if (auio->uio_resid == 0)
938         return (0);
939
940     afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, (afs_int32)avc,
941                ICL_TYPE_LONG, (arw==UIO_WRITE? 1 : 0),
942                ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->uio_offset),
943                ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->uio_resid));
944
945 #ifndef AFS_64BIT_CLIENT
946     if ( AfsLargeFileUio(auio) )        /* file is larger than 2 GB */
947         return (EFBIG);
948 #endif
949     
950 #ifdef  AFS_SUN5_ENV
951     if (!acred) osi_Panic("rdwr: !acred");
952 #else
953     if (!acred) acred = u.u_cred;
954 #endif
955     if (code = afs_InitReq(&treq, acred)) return code;
956
957     /* It's not really possible to know if a write cause a growth in the
958      * cache size, we we wait for a cache drain for any write.
959      */
960     afs_MaybeWakeupTruncateDaemon();
961     while ((arw == UIO_WRITE) &&
962            (afs_blocksUsed > (CM_WAITFORDRAINPCT*afs_cacheBlocks)/100)) {
963         if (afs_blocksUsed - afs_blocksDiscarded >
964             (CM_WAITFORDRAINPCT*afs_cacheBlocks)/100) {
965             afs_WaitForCacheDrain = 1;
966             afs_osi_Sleep(&afs_WaitForCacheDrain);
967         }
968         afs_MaybeFreeDiscardedDCache();
969         afs_MaybeWakeupTruncateDaemon();
970     }
971     code = afs_VerifyVCache(avc, &treq);
972     if (code) return afs_CheckCode(code, &treq, 45);
973
974     afs_BozonLock(&avc->pvnLock, avc);
975     osi_FlushPages(avc, acred); /* hold bozon lock, but not basic vnode lock */
976
977     ObtainWriteLock(&avc->lock,250);
978
979     /* adjust parameters when appending files */
980     if ((ioflag & IO_APPEND) && arw == UIO_WRITE)
981     {
982 #if     defined(AFS_SUN56_ENV)
983         auio->uio_loffset = 0;
984 #endif
985         auio->uio_offset = avc->m.Length;       /* write at EOF position */
986     }
987     if (auio->uio_offset < 0 || (auio->uio_offset + auio->uio_resid) < 0) {
988         ReleaseWriteLock(&avc->lock);   
989         afs_BozonUnlock(&avc->pvnLock, avc);
990         return EINVAL;
991     }
992
993 #ifndef AFS_64BIT_CLIENT
994                                         /* file is larger than 2GB */
995     if ( AfsLargeFileSize(auio->uio_offset, auio->uio_resid) ) {
996         ReleaseWriteLock(&avc->lock);   
997         afs_BozonUnlock(&avc->pvnLock, avc);
998         return EFBIG;
999     }
1000 #endif
1001
1002     didFakeOpen=0;      /* keep track of open so we can do close */
1003     if (arw == UIO_WRITE) {
1004         /* do ulimit processing; shrink resid or fail */
1005 #if     defined(AFS_SUN56_ENV)
1006         if (auio->uio_loffset + auio->afsio_resid > auio->uio_llimit) {
1007             if (auio->uio_llimit >= auio->uio_llimit) {
1008                 ReleaseWriteLock(&avc->lock);
1009                 afs_BozonUnlock(&avc->pvnLock, avc);
1010                 return EFBIG;
1011             } else {
1012                 /* track # of bytes we should write, but won't because of
1013                  * ulimit; we must add this into the final resid value
1014                  * so caller knows we punted some data.
1015                  */
1016                 extraResid = auio->uio_resid;
1017                 auio->uio_resid = auio->uio_llimit - auio->uio_loffset;
1018                 extraResid -= auio->uio_resid;
1019             }
1020         }
1021 #else
1022 #ifdef  AFS_SUN52_ENV   
1023         if (auio->afsio_offset + auio->afsio_resid > auio->uio_limit) {
1024             if (auio->afsio_offset >= auio->uio_limit) {
1025                 ReleaseWriteLock(&avc->lock);   
1026                 afs_BozonUnlock(&avc->pvnLock, avc);
1027                 return EFBIG;
1028             } else {
1029                 /* track # of bytes we should write, but won't because of
1030                  * ulimit; we must add this into the final resid value
1031                  * so caller knows we punted some data.
1032                  */
1033                 extraResid = auio->uio_resid;
1034                 auio->uio_resid = auio->uio_limit - auio->afsio_offset;
1035                 extraResid -= auio->uio_resid;
1036             }
1037         }
1038 #endif
1039 #endif /* SUN56 */
1040         mode = S_WRITE;         /* segment map-in mode */
1041         afs_FakeOpen(avc);      /* do this for writes, so data gets put back
1042                                    when we want it to be put back */
1043         didFakeOpen = 1;        /* we'll be doing a fake open */
1044         /* before starting any I/O, we must ensure that the file is big enough
1045            to hold the results (since afs_putpage will be called to force the I/O */
1046         size = auio->afsio_resid + auio->afsio_offset;  /* new file size */
1047         appendLength = size;            
1048         origLength = avc->m.Length;
1049         if (size > avc->m.Length) {
1050             afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH,
1051                 ICL_TYPE_STRING, __FILE__,
1052                 ICL_TYPE_LONG, __LINE__,
1053                 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length),
1054                 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(size));
1055             avc->m.Length = size;       /* file grew */
1056         }
1057         avc->states |= CDirty;          /* Set the dirty bit */
1058         avc->m.Date = osi_Time();       /* Set file date (for ranlib) */
1059     } else {
1060         mode = S_READ;                  /* map-in read-only */
1061         origLength = avc->m.Length;
1062     }
1063
1064     if (acred && AFS_NFSXLATORREQ(acred)) {
1065         if (arw == UIO_READ) {
1066             if (!afs_AccessOK(avc, PRSFS_READ, &treq,
1067                               CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ)) {
1068                 ReleaseWriteLock(&avc->lock);   
1069                 afs_BozonUnlock(&avc->pvnLock, avc);
1070                 return EACCES;
1071             }
1072         }
1073 #ifdef  AFS_SUN5_ENV
1074         crhold(acred);
1075         if (avc->credp) {
1076             crfree(avc->credp);
1077         }
1078         avc->credp = acred;
1079 #endif
1080     }
1081     counter = 0; /* don't call afs_DoPartialWrite first time through. */
1082     while (1) {
1083         /* compute the amount of data to move into this block,
1084            based on auio->afsio_resid.  Note that we copy data in units of
1085            MAXBSIZE, not PAGESIZE.  This is because segmap_getmap panics if you
1086            call it with an offset based on blocks smaller than MAXBSIZE
1087            (implying that it should be named BSIZE, since it is clearly both a
1088            max and a min). */
1089         size = auio->afsio_resid;               /* transfer size */
1090         fileBase = auio->afsio_offset;          /* start file position for xfr */
1091         pageBase = fileBase & ~(MAXBSIZE-1);    /* file position of the page */
1092         pageOffset = fileBase & (MAXBSIZE-1);   /* xfr start's offset within page */
1093         tsize = MAXBSIZE-pageOffset;            /* how much more fits in this page */
1094         /* we'll read tsize bytes, but first must make sure tsize isn't too big */
1095         if (tsize > size) tsize = size; /* don't read past end of request */
1096         eof = 0;        /* flag telling us if we hit the EOF on the read */
1097         if (arw == UIO_READ) {          /* we're doing a read operation */
1098             /* don't read past EOF */
1099             if (fileBase + tsize > origLength) {
1100                 tsize = origLength - fileBase;
1101                 eof = 1;                /* we did hit the EOF */
1102                 if (tsize < 0) tsize = 0;       /* better safe than sorry */
1103             }
1104             sflags = 0;
1105         }
1106         else {
1107 #ifdef  AFS_SUN5_ENV
1108             /* Purge dirty chunks of file if there are too many dirty
1109              * chunks. Inside the write loop, we only do this at a chunk
1110              * boundary. Clean up partial chunk if necessary at end of loop.
1111              */
1112             if (counter > 0 && code == 0 && AFS_CHUNKOFFSET(fileBase) == 0)
1113                 {
1114                     code = afs_DoPartialWrite(avc, &treq);
1115                     if (code)
1116                         break;
1117                 }
1118 #endif  /* AFS_SUN5_ENV */
1119             /* write case, we ask segmap_release to call putpage.  Really, we
1120                don't have to do this on every page mapin, but for now we're
1121                lazy, and don't modify the rest of AFS to scan for modified
1122                pages on a close or other "synchronize with file server"
1123                operation.  This makes things a little cleaner, but probably
1124                hurts performance. */
1125             sflags = SM_WRITE;
1126         }
1127         if (tsize <= 0) {
1128             code = 0;
1129             break;      /* nothing to transfer, we're done */
1130         }
1131 #ifdef  AFS_SUN5_ENV
1132         if (arw == UIO_WRITE)
1133             avc->states |= CDirty; /* may have been cleared by DoPartialWrite*/
1134
1135         /* Before dropping lock, hold the chunk (create it if necessary).  This
1136          * serves two purposes:  (1) Ensure Cache Truncate Daemon doesn't try
1137          * to purge the chunk's pages while we have them locked.  This would
1138          * cause deadlock because we might be waiting for the CTD to free up
1139          * a chunk.  (2)  If we're writing past the original EOF, and we're
1140          * at the base of the chunk, then make sure it exists online
1141          * before we do the uiomove, since the segmap_release will
1142          * write out to the chunk, causing it to get fetched if it hasn't
1143          * been created yet.  The code that would otherwise notice that
1144          * we're fetching a chunk past EOF won't work, since we've
1145          * already adjusted the file size above.
1146          */
1147         ObtainWriteLock(&avc->vlock, 551);
1148         while (avc->vstates & VPageCleaning) {
1149             ReleaseWriteLock(&avc->vlock);
1150             ReleaseWriteLock(&avc->lock);
1151             afs_osi_Sleep(&avc->vstates);
1152             ObtainWriteLock(&avc->lock, 334);
1153             ObtainWriteLock(&avc->vlock, 552);
1154         }
1155         ReleaseWriteLock(&avc->vlock);
1156         {
1157             afs_size_t toff, tlen;
1158             dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
1159             if (!dcp) {
1160                 code = ENOENT;  
1161                 break;
1162             }
1163         }
1164 #endif
1165         ReleaseWriteLock(&avc->lock);   /* uiomove may page fault */
1166         AFS_GUNLOCK();
1167 #if     defined(AFS_SUN56_ENV)
1168         data = segmap_getmap(segkmap,AFSTOV(avc),(u_offset_t)pageBase);
1169 #else
1170         data = segmap_getmap(segkmap, AFSTOV(avc), pageBase);
1171 #endif
1172 #ifndef AFS_SUN5_ENV
1173         code = afs_fc2errno(as_fault(&kas, data+pageOffset, tsize,
1174                                      F_SOFTLOCK, mode));
1175         if (code == 0) {
1176             AFS_UIOMOVE(data+pageOffset, tsize, arw, auio, code);
1177             as_fault(&kas, data+pageOffset, tsize, F_SOFTUNLOCK, mode);
1178             code2 = segmap_release(segkmap, data, sflags);
1179             if (!code)
1180                 code = code2;
1181         }
1182         else {
1183             (void) segmap_release(segkmap, data, 0);
1184         }
1185 #else
1186 #if defined(AFS_SUN56_ENV)
1187         raddr = (caddr_t) (((uintptr_t)data +pageOffset) & PAGEMASK);
1188 #else
1189         raddr = (caddr_t) (((u_int)data +pageOffset) & PAGEMASK);
1190 #endif
1191         rsize = (((u_int)data+pageOffset+tsize+PAGEOFFSET) & PAGEMASK)-(u_int)raddr;
1192         if (code == 0) {
1193             /* if we're doing a write, and we're starting at the rounded
1194              * down page base, and we're writing enough data to cover all
1195              * created pages, then we must be writing all of the pages
1196              * in this MAXBSIZE window that we're creating.
1197              */
1198             created = 0;
1199             if (arw == UIO_WRITE
1200                     && ((long)raddr == (long)data+pageOffset)
1201                     && tsize >= rsize) {
1202                 /* probably the dcache backing this guy is around, but if
1203                  * not, we can't do this optimization, since we're creating
1204                  * writable pages, which must be backed by a chunk.
1205                  */
1206                 AFS_GLOCK();
1207                 dcp_newpage = afs_FindDCache(avc, pageBase);
1208                 if (dcp_newpage
1209                     && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)) {
1210                     ObtainWriteLock(&avc->lock,251);
1211                     ObtainWriteLock(&avc->vlock,576);
1212                     ObtainReadLock(&dcp_newpage->lock);
1213                     if ((avc->activeV == 0)
1214                         && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)
1215                         && !(dcp_newpage->dflags & (DFFetching))) {
1216                         AFS_GUNLOCK();
1217                         segmap_pagecreate(segkmap, raddr, rsize, 1);
1218                         AFS_GLOCK();
1219                         ObtainWriteLock(&afs_xdcache,252);
1220                         /* Mark the pages as created and dirty */
1221                         afs_indexFlags[dcp_newpage->index]
1222                             |= (IFAnyPages | IFDirtyPages);
1223                         ReleaseWriteLock(&afs_xdcache);             
1224                         created = 1;
1225                     }
1226                     ReleaseReadLock(&dcp_newpage->lock);
1227                     afs_PutDCache(dcp_newpage);
1228                     ReleaseWriteLock(&avc->vlock);
1229                     ReleaseWriteLock(&avc->lock);
1230                 }
1231                 else if ( dcp_newpage )
1232                     afs_PutDCache(dcp_newpage);
1233                 AFS_GUNLOCK();
1234             }
1235             if (!created)
1236                 code = afs_fc2errno(segmap_fault(kas.a_hat, segkmap, raddr,
1237                                                  rsize, F_SOFTLOCK, mode));
1238         }
1239         if (code == 0) {
1240             AFS_UIOMOVE(data+pageOffset, tsize, arw, auio, code);
1241             segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTUNLOCK, mode);
1242         }
1243         if (code == 0) {
1244             code = segmap_release(segkmap, data, sflags);
1245         } else {
1246             (void) segmap_release(segkmap, data, 0);
1247         }
1248 #endif  /* AFS_SUN5_ENV */
1249         AFS_GLOCK();
1250         ObtainWriteLock(&avc->lock,253);
1251 #ifdef  AFS_SUN5_ENV
1252         counter++;
1253         if (dcp)        
1254             afs_PutDCache(dcp);
1255 #endif  /* AFS_SUN5_ENV */
1256         if (code) break;
1257     }
1258     if (didFakeOpen) {
1259         afs_FakeClose(avc, acred);
1260     }
1261
1262 #ifdef  AFS_SUN5_ENV
1263     if (arw == UIO_WRITE && (avc->states & CDirty)) {
1264         code2 = afs_DoPartialWrite(avc, &treq);
1265         if (!code)
1266             code = code2;
1267     }
1268 #endif  /* AFS_SUN5_ENV */
1269
1270     if (!code && avc->vc_error) {
1271         code = avc->vc_error;
1272     }
1273     ReleaseWriteLock(&avc->lock);
1274     afs_BozonUnlock(&avc->pvnLock, avc);
1275     if (!code) {
1276 #ifdef  AFS_SUN53_ENV
1277         if ((ioflag & FSYNC) && (arw == UIO_WRITE) && !AFS_NFSXLATORREQ(acred))
1278             code = afs_fsync(avc, 0, acred);
1279 #else
1280         if ((ioflag & IO_SYNC) && (arw == UIO_WRITE)
1281             && !AFS_NFSXLATORREQ(acred))
1282             code = afs_fsync(avc, acred);
1283 #endif
1284     }
1285 #ifdef  AFS_SUN52_ENV   
1286     /* 
1287      * If things worked, add in as remaining in request any bytes
1288      * we didn't write due to file size ulimit.
1289      */
1290     if (code == 0 && extraResid > 0)
1291         auio->uio_resid += extraResid;
1292 #endif
1293     return afs_CheckCode(code, &treq, 46);
1294 }
1295
1296 afs_map(vp, off, as, addr, len, prot, maxprot, flags, cred)
1297 struct vnode *vp;
1298 struct as *as;
1299 #ifdef  AFS_SUN5_ENV
1300 offset_t off;
1301 caddr_t *addr;
1302 #else
1303 u_int off;
1304 addr_t *addr;
1305 #endif
1306 u_int len;
1307 #ifdef  AFS_SUN5_ENV
1308 u_char prot, maxprot;
1309 #else
1310 u_int prot, maxprot;
1311 #endif
1312 u_int flags;
1313 struct AFS_UCRED *cred;
1314 {
1315        struct segvn_crargs crargs;
1316         register afs_int32 code;
1317         struct vrequest treq;
1318         register struct vcache *avc = VTOAFS(vp);
1319
1320         AFS_STATCNT(afs_map);
1321
1322
1323         /* check for reasonableness on segment bounds; apparently len can be < 0 */
1324         if (off < 0 || off + len < 0) {
1325             return (EINVAL);
1326         }
1327 #ifndef AFS_64BIT_CLIENT
1328         if ( AfsLargeFileSize(off, len) ) /* file is larger than 2 GB */
1329         {
1330             code = EFBIG;
1331             goto out;
1332         }
1333 #endif
1334
1335 #if     defined(AFS_SUN5_ENV)
1336         if (vp->v_flag & VNOMAP)        /* File isn't allowed to be mapped */
1337             return (ENOSYS);
1338
1339         if (vp->v_filocks)              /* if locked, disallow mapping */
1340             return (EAGAIN);
1341 #endif
1342        AFS_GLOCK();     
1343        if (code = afs_InitReq(&treq, cred)) goto out;
1344
1345         if (vp->v_type != VREG) {
1346             code = ENODEV;
1347             goto out;
1348         }
1349
1350         code = afs_VerifyVCache(avc, &treq);
1351         if (code) {
1352             goto out;
1353         }
1354         afs_BozonLock(&avc->pvnLock, avc);
1355         osi_FlushPages(avc, cred);      /* ensure old pages are gone */
1356         avc->states |= CMAPPED; /* flag cleared at afs_inactive */
1357         afs_BozonUnlock(&avc->pvnLock, avc);
1358
1359         AFS_GUNLOCK();
1360 #ifdef  AFS_SUN5_ENV
1361         as_rangelock(as);
1362 #endif
1363         if ((flags & MAP_FIXED) == 0) {
1364 #if     defined(AFS_SUN57_ENV)
1365            map_addr(addr, len, off, 1, flags); 
1366 #elif   defined(AFS_SUN56_ENV)
1367             map_addr(addr, len, off, 1);
1368 #else
1369             map_addr(addr, len, (off_t)off, 1);
1370 #endif
1371             if (*addr == NULL) {
1372 #ifdef  AFS_SUN5_ENV
1373                 as_rangeunlock(as);
1374 #endif
1375                 code = ENOMEM;
1376                 goto out1;
1377             }
1378         } else
1379             (void) as_unmap(as, *addr, len);    /* unmap old address space use */
1380         /* setup the create parameter block for the call */
1381         crargs.vp = AFSTOV(avc);
1382         crargs.offset = (u_int)off;
1383         crargs.cred = cred;
1384         crargs.type = flags&MAP_TYPE;
1385         crargs.prot = prot;
1386         crargs.maxprot = maxprot;
1387         crargs.amp = (struct anon_map *) 0;
1388 #if     defined(AFS_SUN5_ENV)
1389         crargs.flags = flags & ~MAP_TYPE;
1390 #endif
1391
1392         code = as_map(as, *addr, len, segvn_create, (char *) &crargs);
1393 #ifdef  AFS_SUN5_ENV
1394         as_rangeunlock(as);
1395 #endif
1396 out1:
1397         AFS_GLOCK();
1398         code = afs_CheckCode(code, &treq, 47);
1399         AFS_GUNLOCK();
1400         return code;
1401 out:
1402         code = afs_CheckCode(code, &treq, 48);
1403         AFS_GUNLOCK();
1404         return code;
1405 }
1406
1407 /* Sun 4.0.X-specific code.  It computes the number of bytes that need
1408     to be zeroed at the end of a page by pvn_vptrunc, given that you're
1409     trying to get vptrunc to truncate a file to alen bytes.  The result
1410     will be passed to pvn_vptrunc by the truncate code */
1411 #ifndef AFS_SUN5_ENV            /* Not good for Solaris */
1412 afs_PageLeft(alen)
1413 register afs_int32 alen; {
1414     register afs_int32 nbytes;
1415
1416     AFS_STATCNT(afs_PageLeft);
1417     nbytes = PAGESIZE - (alen & PAGEOFFSET); /* amount to zap in last page */
1418     /* now check if we'd zero the entire last page.  Don't need to do this
1419        since pvn_vptrunc will handle this case properly (it will invalidate
1420        this page) */
1421     if (nbytes == PAGESIZE) nbytes = 0;
1422     if (nbytes < 0) nbytes = 0; /* just in case */
1423     return nbytes;
1424 }
1425 #endif
1426
1427
1428 /*
1429  * For Now We use standard local kernel params for AFS system values. Change this
1430  * at some point.
1431  */
1432 #if     defined(AFS_SUN5_ENV)
1433 afs_pathconf(vp, cmd, outdatap, credp)
1434     register struct AFS_UCRED *credp;
1435 #else
1436 afs_cntl(vp, cmd, indatap, outdatap, inflag, outflag)
1437     int inflag, outflag;
1438     char *indatap;
1439 #endif
1440     struct vnode *vp;
1441     int cmd;
1442     u_long *outdatap;
1443 {
1444     AFS_STATCNT(afs_cntl);
1445     switch (cmd) {
1446       case _PC_LINK_MAX:
1447         *outdatap = MAXLINK;
1448         break;
1449       case _PC_NAME_MAX:
1450         *outdatap = MAXNAMLEN;
1451         break;
1452       case _PC_PATH_MAX:
1453         *outdatap = MAXPATHLEN;
1454         break;
1455       case _PC_CHOWN_RESTRICTED:
1456         *outdatap = 1;
1457         break;
1458       case _PC_NO_TRUNC:
1459         *outdatap = 1;
1460         break;
1461 #if     !defined(AFS_SUN5_ENV)
1462       case _PC_MAX_CANON:
1463         *outdatap = CANBSIZ;
1464         break;
1465       case _PC_VDISABLE:
1466         *outdatap = VDISABLE;
1467         break;
1468       case _PC_PIPE_BUF:
1469         return EINVAL;
1470         break;
1471 #endif
1472       default:
1473         return EINVAL;
1474     }
1475     return 0;
1476 }
1477
1478 #endif /* AFS_SUN_ENV */
1479
1480 #if     defined(AFS_SUN5_ENV)
1481
1482 afs_ioctl(vnp, com, arg, flag, credp, rvalp)
1483     struct vnode *vnp;
1484     int com, arg, flag;
1485     cred_t *credp;
1486     int *rvalp;
1487 {
1488     return (ENOTTY);
1489 }
1490
1491 void afs_rwlock(vnp, wlock)
1492     struct vnode *vnp;
1493     int wlock;
1494 {
1495     rw_enter(&(VTOAFS(vnp))->rwlock, (wlock ? RW_WRITER : RW_READER));
1496 }
1497
1498
1499 void afs_rwunlock(vnp, wlock)
1500     struct vnode *vnp;
1501     int wlock;
1502 {
1503     rw_exit(&(VTOAFS(vnp))->rwlock);
1504 }
1505
1506
1507 /* NOT SUPPORTED */
1508 afs_seek(vnp, ooff, noffp)
1509     struct vnode *vnp;
1510     offset_t ooff;
1511     offset_t *noffp;
1512 {
1513     register int code = 0;
1514
1515     if ((*noffp < 0 || *noffp > MAXOFF_T))
1516         code = EINVAL;
1517     return code;
1518 }
1519
1520 int afs_frlock(vnp, cmd, ap, flag, off,
1521 #ifdef AFS_SUN59_ENV
1522                flkcb,
1523 #endif
1524                credp)
1525     struct vnode *vnp;
1526     int cmd;
1527 #if     defined(AFS_SUN56_ENV)
1528     struct flock64 *ap;
1529 #else
1530     struct flock *ap;
1531 #endif
1532     int flag;
1533     offset_t off;
1534 #ifdef AFS_SUN59_ENV
1535     struct flk_callback *flkcb;
1536 #endif
1537     struct AFS_UCRED *credp;
1538 {
1539     register afs_int32 code = 0;
1540     /*
1541      * Implement based on afs_lockctl
1542      */
1543     AFS_GLOCK();
1544 #ifdef AFS_SUN59_ENV
1545     if (flkcb)
1546         afs_warn("Don't know how to deal with flk_callback's!\n");
1547 #endif
1548     if ((cmd == F_GETLK) || (cmd == F_O_GETLK) || (cmd == F_SETLK) || (cmd ==  F_SETLKW)) {
1549 #ifdef  AFS_SUN53_ENV
1550         ap->l_pid = ttoproc(curthread)->p_pid;
1551         ap->l_sysid = 0;
1552 #else
1553         ap->l_pid = ttoproc(curthread)->p_epid;
1554         ap->l_sysid = ttoproc(curthread)->p_sysid;
1555 #endif
1556
1557         AFS_GUNLOCK();
1558 #ifdef  AFS_SUN56_ENV
1559         code = convoff(vnp, ap, 0, off);
1560 #else
1561         code = convoff(vnp, ap, 0, (off_t)off);
1562 #endif
1563         if (code) return code;
1564         AFS_GLOCK();
1565     }
1566
1567     code = afs_lockctl(VTOAFS(vnp), ap, cmd, credp);
1568     AFS_GUNLOCK();
1569     return code;
1570 }
1571
1572
1573 int afs_space(vnp, cmd, ap, flag, off, credp)
1574     struct vnode *vnp;
1575     int cmd;
1576 #if     defined(AFS_SUN56_ENV)
1577     struct flock64 *ap;
1578 #else
1579     struct flock *ap;
1580 #endif
1581     int flag;
1582     offset_t off;
1583     struct AFS_UCRED *credp;
1584 {
1585     register afs_int32 code = EINVAL;
1586     struct vattr vattr;
1587
1588     if ((cmd == F_FREESP)
1589 #ifdef  AFS_SUN56_ENV
1590         && ((code = convoff(vnp, ap, 0, off)) == 0)) {
1591 #else
1592         && ((code = convoff(vnp, ap, 0, (off_t)off)) == 0)) {
1593 #endif
1594         AFS_GLOCK();
1595         if (!ap->l_len) {
1596             vattr.va_mask = AT_SIZE;
1597             vattr.va_size = ap->l_start;
1598             code = afs_setattr(VTOAFS(vnp), &vattr, 0, credp);
1599         } 
1600         AFS_GUNLOCK();
1601     }
1602     return (code);
1603 }
1604
1605
1606 #endif
1607
1608 int afs_dump(vp, addr, i1, i2)
1609 struct vnode *vp;
1610 caddr_t addr;
1611 int i1, i2;
1612 {
1613     AFS_STATCNT(afs_dump);
1614     afs_warn("AFS_DUMP. MUST IMPLEMENT THIS!!!\n");
1615     return EINVAL;
1616 }
1617
1618
1619 /* Nothing fancy here; just compare if vnodes are identical ones */
1620 afs_cmp(vp1, vp2) 
1621 struct vnode *vp1, *vp2;
1622 {
1623     AFS_STATCNT(afs_cmp);
1624     return(vp1 == vp2);
1625 }
1626
1627
1628 int afs_realvp(struct vnode *vp, struct vnode **vpp) {
1629     AFS_STATCNT(afs_realvp);
1630     return EINVAL;
1631 }
1632
1633
1634 int  afs_pageio(vp, pp, ui1, ui2, i1, credp)
1635 struct vnode *vp;
1636 struct page *pp;
1637 u_int ui1, ui2;
1638 int i1;
1639 struct cred *credp;
1640 {
1641     afs_warn("afs_pageio: Not implemented\n");
1642     return EINVAL;
1643 }
1644
1645 int  afs_dumpctl(vp, i
1646 #ifdef AFS_SUN59_ENV
1647                  , blkp
1648 #endif
1649                  )
1650 struct vnode *vp;
1651 int i;
1652 #ifdef AFS_SUN59_ENV
1653 int *blkp;
1654 #endif
1655 {
1656     afs_warn("afs_dumpctl: Not implemented\n");
1657     return EINVAL;
1658 }
1659
1660 #ifdef  AFS_SUN54_ENV
1661 extern void afs_dispose(vp, p, fl, dn, cr) 
1662     struct vnode *vp;
1663     struct page *p;
1664     int fl, dn;
1665     struct cred *cr;
1666 {
1667     fs_dispose(vp, p, fl, dn, cr);
1668 }
1669
1670 int  afs_setsecattr(vp, vsecattr, flag, creds)
1671 struct vnode *vp;
1672 vsecattr_t *vsecattr;
1673 int flag;
1674 struct cred *creds;
1675 {
1676     return ENOSYS;
1677 }
1678
1679 int  afs_getsecattr(vp, vsecattr, flag, creds)
1680 struct vnode *vp;
1681 vsecattr_t *vsecattr;
1682 int flag;
1683 struct cred *creds;
1684 {
1685     return fs_fab_acl(vp, vsecattr, flag, creds);
1686 }
1687 #endif
1688
1689 #ifdef  AFS_GLOBAL_SUNLOCK
1690 extern int gafs_open(), gafs_close(), afs_ioctl(), gafs_access();
1691 extern int gafs_getattr(), gafs_setattr(), gafs_lookup(), gafs_create();
1692 extern int gafs_remove(), gafs_link(), gafs_rename(), gafs_mkdir();
1693 extern int gafs_rmdir(), gafs_readdir(), gafs_fsync(), gafs_symlink();
1694 extern int gafs_fid(), gafs_readlink(), fs_setfl(), afs_pathconf();
1695 extern int afs_lockctl();
1696 extern void gafs_inactive();
1697
1698 struct vnodeops Afs_vnodeops = {
1699         gafs_open,
1700         gafs_close,
1701         afs_vmread,
1702         afs_vmwrite,
1703         afs_ioctl,
1704         fs_setfl,
1705         gafs_getattr,
1706         gafs_setattr,
1707         gafs_access,
1708         gafs_lookup,
1709         gafs_create,
1710         gafs_remove,
1711         gafs_link,
1712         gafs_rename,
1713         gafs_mkdir,
1714         gafs_rmdir,
1715         gafs_readdir,
1716         gafs_symlink,
1717         gafs_readlink,
1718         gafs_fsync,
1719         gafs_inactive,
1720         gafs_fid,
1721         afs_rwlock,
1722         afs_rwunlock,
1723         afs_seek,
1724         afs_cmp,
1725         afs_frlock,
1726         afs_space,
1727         afs_realvp,
1728         afs_getpage,    
1729         afs_putpage,
1730         afs_map,
1731         afs_addmap,
1732         afs_delmap,
1733         fs_poll,
1734         afs_dump,
1735         afs_pathconf,
1736         afs_pageio,
1737         afs_dumpctl,
1738 #ifdef  AFS_SUN54_ENV
1739         afs_dispose,
1740         afs_setsecattr,
1741         afs_getsecattr,
1742 #endif
1743 #if     defined(AFS_SUN56_ENV)
1744         fs_shrlock,
1745 #endif
1746 };
1747 struct vnodeops *afs_ops = &Afs_vnodeops;
1748
1749
1750
1751 gafs_open(avcp, aflags, acred)
1752     register struct vcache **avcp;
1753     afs_int32 aflags;
1754     struct AFS_UCRED *acred; 
1755 {
1756     register int code;
1757
1758     AFS_GLOCK();
1759     code = afs_open(avcp, aflags, acred);
1760     AFS_GUNLOCK();
1761     return (code);
1762 }
1763
1764
1765 gafs_close(avc, aflags, count, offset, acred)
1766     offset_t offset;
1767     int count;
1768     register struct vcache *avc;
1769     afs_int32 aflags;
1770     struct AFS_UCRED *acred; 
1771 {
1772     register int code;
1773
1774     AFS_GLOCK();
1775     code = afs_close(avc, aflags, count, offset, acred);
1776     AFS_GUNLOCK();
1777     return (code);
1778 }
1779
1780
1781 gafs_getattr(avc, attrs, flags, acred)
1782     int flags;
1783     register struct vcache *avc;
1784     register struct vattr *attrs;
1785     struct AFS_UCRED *acred; 
1786 {
1787     register int code;
1788
1789     AFS_GLOCK();
1790     code = afs_getattr(avc, attrs, flags, acred);
1791     AFS_GUNLOCK();
1792     return (code);
1793 }
1794
1795
1796 gafs_setattr(avc, attrs, flags, acred)
1797     int flags;
1798     register struct vcache *avc;
1799     register struct vattr *attrs;
1800     struct AFS_UCRED *acred; 
1801 {
1802     register int code;
1803
1804     AFS_GLOCK();
1805     code = afs_setattr(avc, attrs, flags, acred);
1806     AFS_GUNLOCK();
1807     return (code);
1808 }
1809
1810
1811 gafs_access(avc, amode, flags, acred)
1812     int flags;          
1813     register struct vcache *avc;
1814     register afs_int32 amode;
1815     struct AFS_UCRED *acred; 
1816 {
1817     register int code;
1818
1819     AFS_GLOCK();
1820     code = afs_access(avc, amode, flags, acred);
1821     AFS_GUNLOCK();
1822     return (code);
1823 }
1824
1825
1826 gafs_lookup(adp, aname, avcp, pnp, flags, rdir, acred)
1827     struct pathname *pnp;
1828     int flags;
1829     struct vnode *rdir;
1830     register struct vcache *adp, **avcp;
1831     char *aname;
1832     struct AFS_UCRED *acred; 
1833 {
1834     register int code;
1835
1836     AFS_GLOCK();
1837     code = afs_lookup(adp, aname, avcp, pnp, flags, rdir, acred);
1838     AFS_GUNLOCK();
1839     return (code);
1840 }
1841
1842
1843 gafs_create(adp, aname, attrs, aexcl, amode, avcp, acred)
1844     register struct vcache *adp;
1845     char *aname;
1846     struct vattr *attrs;
1847     enum vcexcl aexcl;
1848     int amode;
1849     struct vcache **avcp;
1850     struct AFS_UCRED *acred; 
1851 {
1852     register int code;
1853
1854     AFS_GLOCK();
1855     code = afs_create(adp, aname, attrs, aexcl, amode, avcp, acred);
1856     AFS_GUNLOCK();
1857     return (code);
1858 }
1859
1860 gafs_remove(adp, aname, acred)
1861     register struct vcache *adp;
1862     char *aname;
1863     struct AFS_UCRED *acred; 
1864 {
1865     register int code;
1866
1867     AFS_GLOCK();
1868     code = afs_remove(adp, aname, acred);
1869     AFS_GUNLOCK();
1870     return (code);
1871 }
1872
1873 gafs_link(adp, avc, aname, acred)
1874     register struct vcache *avc;
1875     register struct vcache *adp;
1876     char *aname;
1877     struct AFS_UCRED *acred; 
1878 {
1879     register int code;
1880
1881     AFS_GLOCK();
1882     code = afs_link(adp, avc, aname, acred);
1883     AFS_GUNLOCK();
1884     return (code);
1885 }
1886
1887 gafs_rename(aodp, aname1, andp, aname2, acred)
1888     register struct vcache *aodp, *andp;
1889     char *aname1, *aname2;
1890     struct AFS_UCRED *acred; 
1891 {
1892     register int code;
1893
1894     AFS_GLOCK();
1895     code = afs_rename(aodp, aname1, andp, aname2, acred);
1896     AFS_GUNLOCK();
1897     return (code);
1898 }
1899
1900 gafs_mkdir(adp, aname, attrs, avcp, acred)
1901     register struct vcache *adp;
1902     register struct vcache **avcp;
1903     char *aname;
1904     struct vattr *attrs;
1905     struct AFS_UCRED *acred;
1906 {
1907     register int code;
1908
1909     AFS_GLOCK();
1910     code = afs_mkdir(adp, aname, attrs, avcp, acred);
1911     AFS_GUNLOCK();
1912     return (code);
1913 }
1914
1915
1916 gafs_rmdir(adp, aname, cdirp, acred)
1917     struct vnode *cdirp;
1918     register struct vcache *adp;
1919     char *aname;
1920     struct AFS_UCRED *acred; 
1921 {
1922     register int code;
1923
1924     AFS_GLOCK();
1925     code = afs_rmdir(adp, aname, cdirp, acred);
1926     AFS_GUNLOCK();
1927     return (code);
1928 }
1929
1930
1931 gafs_readdir(avc, auio, acred, eofp)
1932     int *eofp;
1933     register struct vcache *avc;
1934     struct uio *auio;
1935     struct AFS_UCRED *acred; 
1936 {
1937     register int code;
1938
1939     AFS_GLOCK();
1940     code = afs_readdir(avc, auio, acred, eofp);
1941     AFS_GUNLOCK();
1942     return (code); 
1943 }
1944
1945 gafs_symlink(adp, aname, attrs, atargetName, acred)
1946     register struct vcache *adp;
1947     register char *atargetName;
1948     char *aname;
1949     struct vattr *attrs;
1950     struct AFS_UCRED *acred; 
1951 {
1952     register int code;
1953
1954     AFS_GLOCK();
1955     code = afs_symlink(adp, aname, attrs, atargetName, acred);
1956     AFS_GUNLOCK();
1957     return (code);
1958 }
1959
1960
1961 gafs_readlink(avc, auio, acred)
1962     register struct vcache *avc;
1963     struct uio *auio;
1964     struct AFS_UCRED *acred; 
1965 {
1966     register int code;
1967
1968     AFS_GLOCK();
1969     code = afs_readlink(avc, auio, acred);
1970     AFS_GUNLOCK();
1971     return (code);
1972 }
1973
1974 #ifdef  AFS_SUN53_ENV
1975 gafs_fsync(avc, flag, acred)
1976     int flag;
1977 #else
1978 gafs_fsync(avc, acred)
1979 #endif
1980     register struct vcache *avc;
1981     struct AFS_UCRED *acred; 
1982 {
1983     register int code;
1984
1985     AFS_GLOCK();
1986 #ifdef  AFS_SUN53_ENV
1987     code = afs_fsync(avc, flag, acred);
1988 #else
1989     code = afs_fsync(avc, acred);
1990 #endif
1991     AFS_GUNLOCK();
1992     return (code);
1993 }
1994
1995 void afs_inactive(struct vcache *avc, struct AFS_UCRED *acred)
1996 {
1997     struct vnode *vp = AFSTOV(avc);
1998     if (afs_shuttingdown) return ;
1999
2000     /*
2001      * In Solaris and HPUX s800 and HP-UX10.0 they actually call us with
2002      * v_count 1 on last reference!
2003      */
2004     mutex_enter(&vp->v_lock);
2005     if (avc->vrefCount <= 0) osi_Panic("afs_inactive : v_count <=0\n");
2006
2007     /*
2008      * If more than 1 don't unmap the vnode but do decrement the ref count
2009      */
2010     vp->v_count--;
2011     if (vp->v_count > 0) {
2012         mutex_exit(&vp->v_lock);
2013         return;
2014     }   
2015     mutex_exit(&vp->v_lock);    
2016     /*
2017      * Solaris calls VOP_OPEN on exec, but isn't very diligent about calling
2018      * VOP_CLOSE when executable exits.
2019      */
2020     if (avc->opens > 0 && !(avc->states & CCore))
2021         avc->opens = avc->execsOrWriters = 0;
2022
2023     afs_InactiveVCache(avc, acred);
2024 }
2025
2026 void gafs_inactive(avc, acred)
2027     register struct vcache *avc;
2028     struct AFS_UCRED *acred; 
2029 {
2030     AFS_GLOCK();
2031     afs_inactive(avc, acred);
2032     AFS_GUNLOCK();
2033 }
2034
2035
2036 gafs_fid(avc, fidpp)
2037 struct vcache *avc;
2038 struct fid **fidpp;
2039 {
2040     register int code;
2041
2042     AFS_GLOCK();
2043     code = afs_fid(avc, fidpp);
2044     AFS_GUNLOCK();
2045     return (code);
2046 }
2047
2048 #endif  /* AFS_GLOBAL_SUNLOCK */