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