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