2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include "../afs/param.h"
15 #if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
17 * SOLARIS/osi_vnodeops.c
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
32 * Variables: Afs_vnodeops
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"
47 #include <vm/seg_map.h>
48 #include <vm/seg_vn.h>
50 #if defined(AFS_SUN5_ENV)
51 #include <sys/modctl.h>
52 #include <sys/syscall.h>
56 #include <sys/debug.h>
57 #if defined(AFS_SUN5_ENV)
58 #include <sys/fs_subr.h>
61 #if defined(AFS_SUN5_ENV)
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
75 if (!rw_tryupgrade(lock)) {
77 rw_enter(lock, RW_WRITER);
84 /* Translate a faultcode_t as returned by some of the vm routines
85 * into a suitable errno value.
88 afs_fc2errno(faultcode_t fc)
90 switch (FC_CODE(fc)) {
103 extern struct as kas; /* kernel addr space */
104 extern unsigned char *afs_indexFlags;
105 extern afs_lock_t afs_xdcache;
107 /* Additional vnodeops for SunOS 4.0.x */
108 int afs_nfsrdwr(), afs_getpage(), afs_putpage(), afs_map();
109 int afs_dump(), afs_cmp(), afs_realvp(), afs_GetOnePage();
115 int afs_addmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
116 register struct vnode *avp;
120 int length, prot, maxprot, flags;
121 struct AFS_UCRED *credp;
123 /* XXX What should we do here?? XXX */
127 int afs_delmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
128 register struct vnode *avp;
132 int length, prot, maxprot, flags;
133 struct AFS_UCRED *credp;
135 /* XXX What should we do here?? XXX */
139 int afs_vmread(avp, auio, ioflag, acred)
140 register struct vnode *avp;
143 struct AFS_UCRED *acred;
147 if (!RW_READ_HELD(&(VTOAFS(avp))->rwlock))
148 osi_Panic("afs_vmread: !rwlock");
150 code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_READ, ioflag, acred);
156 int afs_vmwrite(avp, auio, ioflag, acred)
157 register struct vnode *avp;
160 struct AFS_UCRED *acred;
164 if (!RW_WRITE_HELD(&(VTOAFS(avp))->rwlock))
165 osi_Panic("afs_vmwrite: !rwlock");
167 code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_WRITE, ioflag, acred);
172 #endif /* AFS_SUN5_ENV */
174 int afs_getpage(vp, off, len, protp, pl, plsz, seg, addr, rw, acred)
189 struct AFS_UCRED *acred;
191 register afs_int32 code = 0;
192 AFS_STATCNT(afs_getpage);
195 if (vp->v_flag & VNOMAP) /* File doesn't allow mapping */
201 #if defined(AFS_SUN56_ENV)
203 code = afs_GetOnePage(vp, off, len, protp, pl, plsz,
204 seg, addr, rw, acred);
208 code = afs_GetOnePage(vp, (u_int)off, len, protp, pl, plsz,
209 seg, addr, rw, acred);
212 code = afs_GetOnePage(vp, off, protp, pl, plsz,
213 seg, addr, rw, acred);
217 struct vcache *vcp = VTOAFS(vp);
219 ObtainWriteLock(&vcp->vlock, 548);
221 ReleaseWriteLock(&vcp->vlock);
223 afs_BozonLock(&vcp->pvnLock, vcp);
224 #if defined(AFS_SUN56_ENV)
225 code = pvn_getpages(afs_GetOnePage, vp, off,
226 len, protp, pl, plsz, seg, addr, rw, acred);
228 code = pvn_getpages(afs_GetOnePage, vp, (u_int)off,
229 len, protp, pl, plsz, seg, addr, rw, acred);
231 afs_BozonUnlock(&vcp->pvnLock, vcp);
233 ObtainWriteLock(&vcp->vlock, 549);
235 ReleaseWriteLock(&vcp->vlock);
242 /* Return all the pages from [off..off+len) in file */
244 int afs_GetOnePage(vp, off, alen, protp, pl, plsz, seg, addr, rw, acred)
247 int afs_GetOnePage(vp, off, protp, pl, plsz, seg, addr, rw, acred)
250 #if defined(AFS_SUN56_ENV)
265 struct AFS_UCRED *acred;
267 register struct page *page;
268 register afs_int32 code = 0;
272 register struct vcache *avc;
273 register struct dcache *tdc;
276 afs_size_t offset, nlen;
277 struct vrequest treq;
278 afs_int32 mapForRead = 0, Code=0;
279 #if defined(AFS_SUN56_ENV)
287 osi_Panic("GetOnePage: !acred");
289 acred = u.u_cred; /* better than nothing */
292 avc = VTOAFS(vp); /* cast to afs vnode */
295 if (avc->credp /*&& AFS_NFSXLATORREQ(acred)*/ && AFS_NFSXLATORREQ(avc->credp)) {
299 if (code = afs_InitReq(&treq, acred)) return code;
302 /* This is a read-ahead request, e.g. due to madvise. */
308 ObtainReadLock(&avc->lock);
310 while (plen > 0 && !afs_BBusy()) {
311 /* Obtain a dcache entry at off. 2 means don't fetch data. */
312 tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 2);
315 /* Write-lock the dcache entry, if we don't succeed, just go on */
316 if (0 != NBObtainWriteLock(&tdc->lock, 642)) {
321 /* If we aren't already fetching this dcache entry, queue it */
322 if (!(tdc->mflags & DFFetchReq)) {
325 tdc->mflags |= DFFetchReq;
326 bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
327 (afs_size_t) off, (afs_size_t) 1, tdc);
329 /* Unable to start background fetch; might as well stop */
330 tdc->mflags &= ~DFFetchReq;
331 ReleaseWriteLock(&tdc->lock);
335 ReleaseWriteLock(&tdc->lock);
337 ReleaseWriteLock(&tdc->lock);
342 /* Adjust our offset and remaining length values */
346 /* If we aren't making progress for some reason, bail out */
347 if (nlen <= 0) break;
350 ReleaseReadLock(&avc->lock);
355 pl[0] = NULL; /* Make sure it's empty */
357 /* first, obtain the proper lock for the VM system */
359 /* if this is a read request, map the page in read-only. This will
360 * allow us to swap out the dcache entry if there are only read-only
361 * pages created for the chunk, which helps a *lot* when dealing
362 * with small caches. Otherwise, we have to invalidate the vm
363 * pages for the range covered by a chunk when we swap out the
366 if (rw == S_READ || rw == S_EXEC)
369 if (protp) *protp = PROT_ALL;
371 if (AFS_NFSXLATORREQ(acred)) {
373 if (!afs_AccessOK(avc, PRSFS_READ, &treq,
374 CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ)) {
383 if (rw == S_WRITE || rw == S_CREATE)
384 tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 5);
386 tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 1);
387 if (!tdc) return EINVAL;
389 code = afs_VerifyVCache(avc, &treq);
394 return afs_CheckCode(code, &treq, 44); /* failed to get it */
397 afs_BozonLock(&avc->pvnLock, avc);
398 ObtainReadLock(&avc->lock);
400 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, (afs_int32) vp,
401 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
403 ICL_TYPE_LONG, (int) rw);
409 /* Check to see if we're in the middle of a VM purge, and if we are, release
410 * the locks and try again when the VM purge is done. */
411 ObtainWriteLock(&avc->vlock, 550);
413 ReleaseReadLock(&avc->lock);
414 ReleaseWriteLock(&avc->vlock);
415 afs_BozonUnlock(&avc->pvnLock, avc);
417 /* Check activeV again, it may have been turned off
418 * while we were waiting for a lock in afs_PutDCache */
419 ObtainWriteLock(&avc->vlock, 574);
421 avc->vstates |= VRevokeWait;
422 ReleaseWriteLock(&avc->vlock);
423 afs_osi_Sleep(&avc->vstates);
425 ReleaseWriteLock(&avc->vlock);
429 ReleaseWriteLock(&avc->vlock);
432 /* We're about to do stuff with our dcache entry.. Lock it. */
433 ObtainReadLock(&tdc->lock);
435 /* Check to see whether the cache entry is still valid */
436 if (!(avc->states & CStatd)
437 || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
438 ReleaseReadLock(&tdc->lock);
439 ReleaseReadLock(&avc->lock);
440 afs_BozonUnlock(&avc->pvnLock, avc);
446 while (1) { /* loop over all pages */
447 /* now, try to find the page in memory (it may already be intransit or laying
448 around the free list */
449 page = page_lookup( vp, toffset, (rw == S_CREATE ? SE_EXCL : SE_SHARED) );
453 /* if we make it here, we can't find the page in memory. Do a real disk read
454 from the cache to get the data */
455 Code |= 0x200; /* XXX */
457 #if defined(AFS_SUN54_ENV)
458 /* use PG_EXCL because we know the page does not exist already. If it
459 * actually does exist, we have somehow raced between lookup and create.
460 * As of 4/98, that shouldn't be possible, but we'll be defensive here
461 * in case someone tries to relax all the serialization of read and write
462 * operations with harmless things like stat. */
463 #if defined(AFS_SUN58_ENV)
464 page = page_create_va(vp, toffset, PAGESIZE, PG_WAIT|PG_EXCL, seg, addr);
466 page = page_create_va(vp, toffset, PAGESIZE, PG_WAIT|PG_EXCL, seg->s_as, addr);
469 page = page_create(vp, toffset, PAGESIZE, PG_WAIT);
475 pagezero(page, alen, PAGESIZE-alen);
477 page = rm_allocpage(seg, addr, PAGESIZE, 1); /* can't fail */
478 if (!page) osi_Panic("afs_getpage alloc page");
479 /* we get a circularly-linked list of pages back, but we expect only
480 one, since that's what we asked for */
481 if (page->p_next != page) osi_Panic("afs_getpage list");
482 /* page enter returns a locked page; we'll drop the lock as a side-effect
483 of the pvn_done done by afs_ustrategy. If we decide not to call
484 strategy, we must be sure to call pvn_fail, at least, to release the
485 page locks and otherwise reset the pages. The page, while locked, is
486 not held, for what it is worth */
487 page->p_intrans = 1; /* set appropriate flags */
489 /* next call shouldn't fail, since we have pvnLock set */
490 if (page_enter(page, vp, toffset)) osi_Panic("afs_getpage enter race");
491 #endif /* AFS_SUN5_ENV */
494 if (rw == S_CREATE) {
495 /* XXX Don't read from AFS in write only cases XXX */
496 page_io_unlock(page);
500 /* XXX Don't read from AFS in write only cases XXX */
501 page->p_intrans = page->p_pagein = 0;
502 page_unlock(page); /* XXX */
509 /* now it is time to start I/O operation */
510 buf = pageio_setup(page, PAGESIZE, vp, B_READ); /* allocate a buf structure */
511 #if defined(AFS_SUN5_ENV)
515 buf->b_blkno = btodb(toffset);
516 bp_mapin(buf); /* map it in to our address space */
518 #if defined(AFS_SUN5_ENV)
520 /* afs_ustrategy will want to lock the dcache entry */
521 ReleaseReadLock(&tdc->lock);
522 code = afs_ustrategy(buf, acred); /* do the I/O */
523 ObtainReadLock(&tdc->lock);
526 ReleaseReadLock(&tdc->lock);
527 ReleaseReadLock(&avc->lock);
528 code = afs_ustrategy(buf); /* do the I/O */
529 ObtainReadLock(&avc->lock);
530 ObtainReadLock(&tdc->lock);
534 /* Before freeing unmap the buffer */
545 page_io_unlock(page);
549 /* come here when we have another page (already held) to enter */
551 /* put page in array and continue */
553 /* The p_selock must be downgraded to a shared lock after the page is read */
554 #if defined(AFS_SUN56_ENV)
555 if ((rw != S_CREATE) && !(PAGE_SHARED(page)))
557 if ((rw != S_CREATE) && !(se_shared_assert(&page->p_selock)))
560 page_downgrade(page);
565 code = page_iolock_assert(page);
571 if (tlen <= 0) break; /* done all the pages */
572 } /* while (1) ... */
575 pl[slot] = (struct page *) 0;
576 ReleaseReadLock(&tdc->lock);
578 /* Prefetch next chunk if we're at a chunk boundary */
579 if (AFS_CHUNKOFFSET(off) == 0) {
580 if (!(tdc->mflags & DFNextStarted))
581 afs_PrefetchChunk(avc, tdc, acred, &treq);
584 ReleaseReadLock(&avc->lock);
586 ObtainWriteLock(&afs_xdcache,246);
588 /* track that we have dirty (or dirty-able) pages for this chunk. */
589 afs_indexFlags[tdc->index] |= IFDirtyPages;
591 afs_indexFlags[tdc->index] |= IFAnyPages;
592 ReleaseWriteLock(&afs_xdcache);
594 afs_BozonUnlock(&avc->pvnLock, avc);
598 afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, (int)page,
599 ICL_TYPE_LONG, Code);
604 afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, (int)page,
605 ICL_TYPE_LONG, Code);
606 /* release all pages, drop locks, return code */
609 pvn_read_done(page, B_ERROR);
611 for(i=0; i<slot; i++)
614 ReleaseReadLock(&avc->lock);
615 afs_BozonUnlock(&avc->pvnLock, avc);
617 ReleaseReadLock(&tdc->lock);
624 int afs_putpage(vp, off, len, flags, cred)
629 struct AFS_UCRED *cred;
634 #if defined(AFS_SUN58_ENV)
641 #if defined(AFS_SUN56_ENV)
642 u_offset_t toff = off;
648 AFS_STATCNT(afs_putpage);
649 if (vp->v_flag & VNOMAP) /* file doesn't allow mapping */
653 * Putpage (ASYNC) is called every sec to flush out dirty vm pages
656 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER, (afs_int32) vp,
657 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
658 ICL_TYPE_INT32, (afs_int32) len,
659 ICL_TYPE_LONG, (int) flags);
661 afs_BozonLock(&avc->pvnLock, avc);
662 ObtainSharedLock(&avc->lock,247);
665 /* Get a list of modified (or whatever) pages */
667 endPos = (afs_offs_t)off + len; /* position we're supposed to write up to */
668 while ((afs_offs_t)toff < endPos && (afs_offs_t)toff < avc->m.Length) {
669 /* If not invalidating pages use page_lookup_nowait to avoid reclaiming
670 * them from the free list
673 if (flags & (B_FREE|B_INVAL))
674 pages = page_lookup(vp, toff, SE_EXCL);
676 pages = page_lookup_nowait(vp, toff, SE_SHARED);
677 if (!pages || !pvn_getdirty(pages, flags))
683 UpgradeSToWLock(&avc->lock, 671);
687 code = afs_putapage(vp, pages, &toff, &tlen, flags, cred);
698 UpgradeSToWLock(&avc->lock, 670);
703 #if defined(AFS_SUN56_ENV)
704 code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
706 code = pvn_vplist_dirty(vp, (u_int)off, afs_putapage, flags, cred);
711 if (code && !avc->vc_error) {
713 UpgradeSToWLock(&avc->lock, 669);
716 avc->vc_error = code;
720 ReleaseWriteLock(&avc->lock);
722 ReleaseSharedLock(&avc->lock);
723 afs_BozonUnlock(&avc->pvnLock, avc);
724 afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, NPages);
730 int afs_putapage(struct vnode *vp, struct page *pages,
731 #if defined(AFS_SUN56_ENV)
736 #if defined(AFS_SUN58_ENV)
741 int flags, struct AFS_UCRED *credp)
744 struct vcache *avc = VTOAFS(vp);
746 u_int tlen = PAGESIZE;
747 afs_offs_t off = (pages->p_offset/PAGESIZE)*PAGESIZE;
750 * Now we've got the modified pages. All pages are locked and held
751 * XXX Find a kluster that fits in one block (or page). We also
752 * adjust the i/o if the file space is less than a while page. XXX
754 if (off + tlen > avc->m.Length) {
755 tlen = avc->m.Length - off;
757 /* can't call mapout with 0 length buffers (rmfree panics) */
758 if (((tlen>>24)&0xff) == 0xff) {
763 * Can't call mapout with 0 length buffers since we'll get rmfree panics
765 tbuf = pageio_setup(pages, tlen, vp, B_WRITE | flags);
766 if (!tbuf) return (ENOMEM);
769 tbuf->b_blkno = btodb(pages->p_offset);
772 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUTONE, ICL_TYPE_LONG, avc,
773 ICL_TYPE_LONG, pages,
775 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off));
776 code = afs_ustrategy(tbuf, credp); /* unlocks page */
780 pvn_write_done(pages, ((code) ? B_ERROR:0) | B_WRITE | flags);
783 if (offp) *offp = off;
784 if (lenp) *lenp = tlen;
790 int afs_putpage(vp, off, len, flags, cred)
795 struct AFS_UCRED *cred;
797 int wholeEnchilada; /* true if we must get all of the pages */
803 afs_int32 code = 0, rcode;
805 afs_int32 clusterStart, clusterEnd, endPos;
807 /* In the wholeEnchilada case, we must ensure that we get all of the pages
808 from the system, since we're doing this to shutdown the use of a vnode */
810 AFS_STATCNT(afs_putpage);
811 wholeEnchilada = (off == 0 && len == 0 && (flags & (B_INVAL|B_ASYNC)) == B_INVAL);
814 afs_BozonLock(&avc->pvnLock, avc);
815 ObtainWriteLock(&avc->lock,248);
818 /* in whole enchilada case, loop until call to pvn_getdirty can't find
819 any more modified pages */
821 /* first we try to get a list of modified (or whatever) pages */
823 pages = pvn_vplist_dirty(vp, off, flags);
826 endPos = off + len; /* position we're supposed to write up to */
827 if (endPos > avc->m.Length) endPos = avc->m.Length; /* bound by this */
828 clusterStart = off & ~(PAGESIZE-1); /* round down to nearest page */
829 clusterEnd = ((endPos-1) | (PAGESIZE-1))+1; /* round up to nearest page */
830 pages = pvn_range_dirty(vp, off, endPos, clusterStart, clusterEnd, flags);
833 /* Now we've got the modified pages. All pages are locked and held */
834 rcode = 0; /* return code */
835 while(pages) { /* look over all pages in the returned set */
836 tpage = pages; /* get first page in the list */
838 /* write out the page */
839 poffset = tpage->p_offset; /* where the page starts in the file */
840 /* tlen will represent the end of the range to write, for a while */
841 tlen = PAGESIZE+poffset; /* basic place to end tpage write */
842 /* but we also don't want to write past end of off..off+len range */
843 if (len != 0 && tlen > off+len) tlen = off+len;
844 /* and we don't want to write past the end of the file */
845 if (tlen > avc->m.Length) tlen = avc->m.Length;
846 /* and we don't want to write at all if page starts after end */
847 if (poffset >= tlen) {
848 pvn_fail(pages, B_WRITE | flags);
851 /* finally change tlen from end position to length */
852 tlen -= poffset; /* compute bytes to write from this page */
853 page_sub(&pages, tpage); /* remove tpage from "pages" list */
854 tbuf = pageio_setup(tpage, tlen, vp, B_WRITE | flags);
856 pvn_fail(tpage, B_WRITE|flags);
857 pvn_fail(pages, B_WRITE|flags);
861 tbuf->b_blkno = btodb(tpage->p_offset);
863 ReleaseWriteLock(&avc->lock); /* can't hold during strategy call */
864 code = afs_ustrategy(tbuf); /* unlocks page */
865 ObtainWriteLock(&avc->lock,249); /* re-obtain */
867 /* unlocking of tpage is done by afs_ustrategy */
869 if (pages) /* may have already removed last page */
870 pvn_fail(pages, B_WRITE|flags);
873 } /* for (tpage=pages....) */
875 /* see if we've gotten all of the pages in the whole enchilada case */
876 if (!wholeEnchilada || !vp->v_pages) break;
877 } /* while(1) obtaining all pages */
880 * If low on chunks, and if writing the last byte of a chunk, try to
881 * free some. Note that afs_DoPartialWrite calls osi_SyncVM which now
882 * calls afs_putpage, so this is recursion. It stops there because we
883 * insist on len being non-zero.
885 if (afs_stats_cmperf.cacheCurrDirtyChunks > afs_stats_cmperf.cacheMaxDirtyChunks
886 && len != 0 && AFS_CHUNKOFFSET((off + len)) == 0) {
887 struct vrequest treq;
888 if (!afs_InitReq(&treq, cred ? cred : u.u_cred)) {
889 rcode = afs_DoPartialWrite(avc, &treq); /* XXX */
895 if (rcode && !avc->vc_error)
896 avc->vc_error = rcode;
898 /* when we're here, we just return code. */
899 ReleaseWriteLock(&avc->lock);
900 afs_BozonUnlock(&avc->pvnLock, avc);
904 #endif /* AFS_SUN5_ENV */
906 int afs_nfsrdwr(avc, auio, arw, ioflag, acred)
907 register struct vcache *avc;
911 struct AFS_UCRED *acred;
913 register afs_int32 code;
916 afs_int32 mode, sflags;
918 struct dcache *dcp, *dcp_newpage;
919 afs_size_t fileBase, size;
921 register afs_int32 tsize;
922 register afs_int32 pageOffset, extraResid=0;
923 register afs_size_t origLength; /* length when reading/writing started */
924 register long appendLength; /* length when this call will finish */
925 int created; /* created pages instead of faulting them */
927 int didFakeOpen, eof;
928 struct vrequest treq;
932 AFS_STATCNT(afs_nfsrdwr);
934 /* can't read or write other things */
935 if (vType(avc) != VREG) return EISDIR;
937 if (auio->uio_resid == 0)
940 afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, (afs_int32)avc,
941 ICL_TYPE_LONG, (arw==UIO_WRITE? 1 : 0),
942 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->uio_offset),
943 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->uio_resid));
945 #ifndef AFS_64BIT_CLIENT
946 if ( AfsLargeFileUio(auio) ) /* file is larger than 2 GB */
951 if (!acred) osi_Panic("rdwr: !acred");
953 if (!acred) acred = u.u_cred;
955 if (code = afs_InitReq(&treq, acred)) return code;
957 /* It's not really possible to know if a write cause a growth in the
958 * cache size, we we wait for a cache drain for any write.
960 afs_MaybeWakeupTruncateDaemon();
961 while ((arw == UIO_WRITE) &&
962 (afs_blocksUsed > (CM_WAITFORDRAINPCT*afs_cacheBlocks)/100)) {
963 if (afs_blocksUsed - afs_blocksDiscarded >
964 (CM_WAITFORDRAINPCT*afs_cacheBlocks)/100) {
965 afs_WaitForCacheDrain = 1;
966 afs_osi_Sleep(&afs_WaitForCacheDrain);
968 afs_MaybeFreeDiscardedDCache();
969 afs_MaybeWakeupTruncateDaemon();
971 code = afs_VerifyVCache(avc, &treq);
972 if (code) return afs_CheckCode(code, &treq, 45);
974 afs_BozonLock(&avc->pvnLock, avc);
975 osi_FlushPages(avc, acred); /* hold bozon lock, but not basic vnode lock */
977 ObtainWriteLock(&avc->lock,250);
979 /* adjust parameters when appending files */
980 if ((ioflag & IO_APPEND) && arw == UIO_WRITE)
982 #if defined(AFS_SUN56_ENV)
983 auio->uio_loffset = 0;
985 auio->uio_offset = avc->m.Length; /* write at EOF position */
987 if (auio->uio_offset < 0 || (auio->uio_offset + auio->uio_resid) < 0) {
988 ReleaseWriteLock(&avc->lock);
989 afs_BozonUnlock(&avc->pvnLock, avc);
993 #ifndef AFS_64BIT_CLIENT
994 /* file is larger than 2GB */
995 if ( AfsLargeFileSize(auio->uio_offset, auio->uio_resid) ) {
996 ReleaseWriteLock(&avc->lock);
997 afs_BozonUnlock(&avc->pvnLock, avc);
1002 didFakeOpen=0; /* keep track of open so we can do close */
1003 if (arw == UIO_WRITE) {
1004 /* do ulimit processing; shrink resid or fail */
1005 #if defined(AFS_SUN56_ENV)
1006 if (auio->uio_loffset + auio->afsio_resid > auio->uio_llimit) {
1007 if (auio->uio_llimit >= auio->uio_llimit) {
1008 ReleaseWriteLock(&avc->lock);
1009 afs_BozonUnlock(&avc->pvnLock, avc);
1012 /* track # of bytes we should write, but won't because of
1013 * ulimit; we must add this into the final resid value
1014 * so caller knows we punted some data.
1016 extraResid = auio->uio_resid;
1017 auio->uio_resid = auio->uio_llimit - auio->uio_loffset;
1018 extraResid -= auio->uio_resid;
1022 #ifdef AFS_SUN52_ENV
1023 if (auio->afsio_offset + auio->afsio_resid > auio->uio_limit) {
1024 if (auio->afsio_offset >= auio->uio_limit) {
1025 ReleaseWriteLock(&avc->lock);
1026 afs_BozonUnlock(&avc->pvnLock, avc);
1029 /* track # of bytes we should write, but won't because of
1030 * ulimit; we must add this into the final resid value
1031 * so caller knows we punted some data.
1033 extraResid = auio->uio_resid;
1034 auio->uio_resid = auio->uio_limit - auio->afsio_offset;
1035 extraResid -= auio->uio_resid;
1040 mode = S_WRITE; /* segment map-in mode */
1041 afs_FakeOpen(avc); /* do this for writes, so data gets put back
1042 when we want it to be put back */
1043 didFakeOpen = 1; /* we'll be doing a fake open */
1044 /* before starting any I/O, we must ensure that the file is big enough
1045 to hold the results (since afs_putpage will be called to force the I/O */
1046 size = auio->afsio_resid + auio->afsio_offset; /* new file size */
1047 appendLength = size;
1048 origLength = avc->m.Length;
1049 if (size > avc->m.Length) {
1050 afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH,
1051 ICL_TYPE_STRING, __FILE__,
1052 ICL_TYPE_LONG, __LINE__,
1053 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length),
1054 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(size));
1055 avc->m.Length = size; /* file grew */
1057 avc->states |= CDirty; /* Set the dirty bit */
1058 avc->m.Date = osi_Time(); /* Set file date (for ranlib) */
1060 mode = S_READ; /* map-in read-only */
1061 origLength = avc->m.Length;
1064 if (acred && AFS_NFSXLATORREQ(acred)) {
1065 if (arw == UIO_READ) {
1066 if (!afs_AccessOK(avc, PRSFS_READ, &treq,
1067 CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ)) {
1068 ReleaseWriteLock(&avc->lock);
1069 afs_BozonUnlock(&avc->pvnLock, avc);
1081 counter = 0; /* don't call afs_DoPartialWrite first time through. */
1083 /* compute the amount of data to move into this block,
1084 based on auio->afsio_resid. Note that we copy data in units of
1085 MAXBSIZE, not PAGESIZE. This is because segmap_getmap panics if you
1086 call it with an offset based on blocks smaller than MAXBSIZE
1087 (implying that it should be named BSIZE, since it is clearly both a
1089 size = auio->afsio_resid; /* transfer size */
1090 fileBase = auio->afsio_offset; /* start file position for xfr */
1091 pageBase = fileBase & ~(MAXBSIZE-1); /* file position of the page */
1092 pageOffset = fileBase & (MAXBSIZE-1); /* xfr start's offset within page */
1093 tsize = MAXBSIZE-pageOffset; /* how much more fits in this page */
1094 /* we'll read tsize bytes, but first must make sure tsize isn't too big */
1095 if (tsize > size) tsize = size; /* don't read past end of request */
1096 eof = 0; /* flag telling us if we hit the EOF on the read */
1097 if (arw == UIO_READ) { /* we're doing a read operation */
1098 /* don't read past EOF */
1099 if (fileBase + tsize > origLength) {
1100 tsize = origLength - fileBase;
1101 eof = 1; /* we did hit the EOF */
1102 if (tsize < 0) tsize = 0; /* better safe than sorry */
1108 /* Purge dirty chunks of file if there are too many dirty
1109 * chunks. Inside the write loop, we only do this at a chunk
1110 * boundary. Clean up partial chunk if necessary at end of loop.
1112 if (counter > 0 && code == 0 && AFS_CHUNKOFFSET(fileBase) == 0)
1114 code = afs_DoPartialWrite(avc, &treq);
1118 #endif /* AFS_SUN5_ENV */
1119 /* write case, we ask segmap_release to call putpage. Really, we
1120 don't have to do this on every page mapin, but for now we're
1121 lazy, and don't modify the rest of AFS to scan for modified
1122 pages on a close or other "synchronize with file server"
1123 operation. This makes things a little cleaner, but probably
1124 hurts performance. */
1129 break; /* nothing to transfer, we're done */
1132 if (arw == UIO_WRITE)
1133 avc->states |= CDirty; /* may have been cleared by DoPartialWrite*/
1135 /* Before dropping lock, hold the chunk (create it if necessary). This
1136 * serves two purposes: (1) Ensure Cache Truncate Daemon doesn't try
1137 * to purge the chunk's pages while we have them locked. This would
1138 * cause deadlock because we might be waiting for the CTD to free up
1139 * a chunk. (2) If we're writing past the original EOF, and we're
1140 * at the base of the chunk, then make sure it exists online
1141 * before we do the uiomove, since the segmap_release will
1142 * write out to the chunk, causing it to get fetched if it hasn't
1143 * been created yet. The code that would otherwise notice that
1144 * we're fetching a chunk past EOF won't work, since we've
1145 * already adjusted the file size above.
1147 ObtainWriteLock(&avc->vlock, 551);
1148 while (avc->vstates & VPageCleaning) {
1149 ReleaseWriteLock(&avc->vlock);
1150 ReleaseWriteLock(&avc->lock);
1151 afs_osi_Sleep(&avc->vstates);
1152 ObtainWriteLock(&avc->lock, 334);
1153 ObtainWriteLock(&avc->vlock, 552);
1155 ReleaseWriteLock(&avc->vlock);
1157 afs_size_t toff, tlen;
1158 dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
1165 ReleaseWriteLock(&avc->lock); /* uiomove may page fault */
1167 #if defined(AFS_SUN56_ENV)
1168 data = segmap_getmap(segkmap,AFSTOV(avc),(u_offset_t)pageBase);
1170 data = segmap_getmap(segkmap, AFSTOV(avc), pageBase);
1172 #ifndef AFS_SUN5_ENV
1173 code = afs_fc2errno(as_fault(&kas, data+pageOffset, tsize,
1176 AFS_UIOMOVE(data+pageOffset, tsize, arw, auio, code);
1177 as_fault(&kas, data+pageOffset, tsize, F_SOFTUNLOCK, mode);
1178 code2 = segmap_release(segkmap, data, sflags);
1183 (void) segmap_release(segkmap, data, 0);
1186 #if defined(AFS_SUN56_ENV)
1187 raddr = (caddr_t) (((uintptr_t)data +pageOffset) & PAGEMASK);
1189 raddr = (caddr_t) (((u_int)data +pageOffset) & PAGEMASK);
1191 rsize = (((u_int)data+pageOffset+tsize+PAGEOFFSET) & PAGEMASK)-(u_int)raddr;
1193 /* if we're doing a write, and we're starting at the rounded
1194 * down page base, and we're writing enough data to cover all
1195 * created pages, then we must be writing all of the pages
1196 * in this MAXBSIZE window that we're creating.
1199 if (arw == UIO_WRITE
1200 && ((long)raddr == (long)data+pageOffset)
1201 && tsize >= rsize) {
1202 /* probably the dcache backing this guy is around, but if
1203 * not, we can't do this optimization, since we're creating
1204 * writable pages, which must be backed by a chunk.
1207 dcp_newpage = afs_FindDCache(avc, pageBase);
1209 && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)) {
1210 ObtainWriteLock(&avc->lock,251);
1211 ObtainWriteLock(&avc->vlock,576);
1212 ObtainReadLock(&dcp_newpage->lock);
1213 if ((avc->activeV == 0)
1214 && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)
1215 && !(dcp_newpage->dflags & (DFFetching))) {
1217 segmap_pagecreate(segkmap, raddr, rsize, 1);
1219 ObtainWriteLock(&afs_xdcache,252);
1220 /* Mark the pages as created and dirty */
1221 afs_indexFlags[dcp_newpage->index]
1222 |= (IFAnyPages | IFDirtyPages);
1223 ReleaseWriteLock(&afs_xdcache);
1226 ReleaseReadLock(&dcp_newpage->lock);
1227 afs_PutDCache(dcp_newpage);
1228 ReleaseWriteLock(&avc->vlock);
1229 ReleaseWriteLock(&avc->lock);
1231 else if ( dcp_newpage )
1232 afs_PutDCache(dcp_newpage);
1236 code = afs_fc2errno(segmap_fault(kas.a_hat, segkmap, raddr,
1237 rsize, F_SOFTLOCK, mode));
1240 AFS_UIOMOVE(data+pageOffset, tsize, arw, auio, code);
1241 segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTUNLOCK, mode);
1244 code = segmap_release(segkmap, data, sflags);
1246 (void) segmap_release(segkmap, data, 0);
1248 #endif /* AFS_SUN5_ENV */
1250 ObtainWriteLock(&avc->lock,253);
1255 #endif /* AFS_SUN5_ENV */
1259 afs_FakeClose(avc, acred);
1263 if (arw == UIO_WRITE && (avc->states & CDirty)) {
1264 code2 = afs_DoPartialWrite(avc, &treq);
1268 #endif /* AFS_SUN5_ENV */
1270 if (!code && avc->vc_error) {
1271 code = avc->vc_error;
1273 ReleaseWriteLock(&avc->lock);
1274 afs_BozonUnlock(&avc->pvnLock, avc);
1276 #ifdef AFS_SUN53_ENV
1277 if ((ioflag & FSYNC) && (arw == UIO_WRITE) && !AFS_NFSXLATORREQ(acred))
1278 code = afs_fsync(avc, 0, acred);
1280 if ((ioflag & IO_SYNC) && (arw == UIO_WRITE)
1281 && !AFS_NFSXLATORREQ(acred))
1282 code = afs_fsync(avc, acred);
1285 #ifdef AFS_SUN52_ENV
1287 * If things worked, add in as remaining in request any bytes
1288 * we didn't write due to file size ulimit.
1290 if (code == 0 && extraResid > 0)
1291 auio->uio_resid += extraResid;
1293 return afs_CheckCode(code, &treq, 46);
1296 afs_map(vp, off, as, addr, len, prot, maxprot, flags, cred)
1308 u_char prot, maxprot;
1310 u_int prot, maxprot;
1313 struct AFS_UCRED *cred;
1315 struct segvn_crargs crargs;
1316 register afs_int32 code;
1317 struct vrequest treq;
1318 register struct vcache *avc = VTOAFS(vp);
1320 AFS_STATCNT(afs_map);
1323 /* check for reasonableness on segment bounds; apparently len can be < 0 */
1324 if (off < 0 || off + len < 0) {
1327 #ifndef AFS_64BIT_CLIENT
1328 if ( AfsLargeFileSize(off, len) ) /* file is larger than 2 GB */
1335 #if defined(AFS_SUN5_ENV)
1336 if (vp->v_flag & VNOMAP) /* File isn't allowed to be mapped */
1339 if (vp->v_filocks) /* if locked, disallow mapping */
1343 if (code = afs_InitReq(&treq, cred)) goto out;
1345 if (vp->v_type != VREG) {
1350 code = afs_VerifyVCache(avc, &treq);
1354 afs_BozonLock(&avc->pvnLock, avc);
1355 osi_FlushPages(avc, cred); /* ensure old pages are gone */
1356 avc->states |= CMAPPED; /* flag cleared at afs_inactive */
1357 afs_BozonUnlock(&avc->pvnLock, avc);
1363 if ((flags & MAP_FIXED) == 0) {
1364 #if defined(AFS_SUN57_ENV)
1365 map_addr(addr, len, off, 1, flags);
1366 #elif defined(AFS_SUN56_ENV)
1367 map_addr(addr, len, off, 1);
1369 map_addr(addr, len, (off_t)off, 1);
1371 if (*addr == NULL) {
1379 (void) as_unmap(as, *addr, len); /* unmap old address space use */
1380 /* setup the create parameter block for the call */
1381 crargs.vp = AFSTOV(avc);
1382 crargs.offset = (u_int)off;
1384 crargs.type = flags&MAP_TYPE;
1386 crargs.maxprot = maxprot;
1387 crargs.amp = (struct anon_map *) 0;
1388 #if defined(AFS_SUN5_ENV)
1389 crargs.flags = flags & ~MAP_TYPE;
1392 code = as_map(as, *addr, len, segvn_create, (char *) &crargs);
1398 code = afs_CheckCode(code, &treq, 47);
1402 code = afs_CheckCode(code, &treq, 48);
1407 /* Sun 4.0.X-specific code. It computes the number of bytes that need
1408 to be zeroed at the end of a page by pvn_vptrunc, given that you're
1409 trying to get vptrunc to truncate a file to alen bytes. The result
1410 will be passed to pvn_vptrunc by the truncate code */
1411 #ifndef AFS_SUN5_ENV /* Not good for Solaris */
1413 register afs_int32 alen; {
1414 register afs_int32 nbytes;
1416 AFS_STATCNT(afs_PageLeft);
1417 nbytes = PAGESIZE - (alen & PAGEOFFSET); /* amount to zap in last page */
1418 /* now check if we'd zero the entire last page. Don't need to do this
1419 since pvn_vptrunc will handle this case properly (it will invalidate
1421 if (nbytes == PAGESIZE) nbytes = 0;
1422 if (nbytes < 0) nbytes = 0; /* just in case */
1429 * For Now We use standard local kernel params for AFS system values. Change this
1432 #if defined(AFS_SUN5_ENV)
1433 afs_pathconf(vp, cmd, outdatap, credp)
1434 register struct AFS_UCRED *credp;
1436 afs_cntl(vp, cmd, indatap, outdatap, inflag, outflag)
1437 int inflag, outflag;
1444 AFS_STATCNT(afs_cntl);
1447 *outdatap = MAXLINK;
1450 *outdatap = MAXNAMLEN;
1453 *outdatap = MAXPATHLEN;
1455 case _PC_CHOWN_RESTRICTED:
1461 #if !defined(AFS_SUN5_ENV)
1463 *outdatap = CANBSIZ;
1466 *outdatap = VDISABLE;
1478 #endif /* AFS_SUN_ENV */
1480 #if defined(AFS_SUN5_ENV)
1482 afs_ioctl(vnp, com, arg, flag, credp, rvalp)
1491 void afs_rwlock(vnp, wlock)
1495 rw_enter(&(VTOAFS(vnp))->rwlock, (wlock ? RW_WRITER : RW_READER));
1499 void afs_rwunlock(vnp, wlock)
1503 rw_exit(&(VTOAFS(vnp))->rwlock);
1508 afs_seek(vnp, ooff, noffp)
1513 register int code = 0;
1515 if ((*noffp < 0 || *noffp > MAXOFF_T))
1520 int afs_frlock(vnp, cmd, ap, flag, off,
1521 #ifdef AFS_SUN59_ENV
1527 #if defined(AFS_SUN56_ENV)
1534 #ifdef AFS_SUN59_ENV
1535 struct flk_callback *flkcb;
1537 struct AFS_UCRED *credp;
1539 register afs_int32 code = 0;
1541 * Implement based on afs_lockctl
1544 #ifdef AFS_SUN59_ENV
1546 afs_warn("Don't know how to deal with flk_callback's!\n");
1548 if ((cmd == F_GETLK) || (cmd == F_O_GETLK) || (cmd == F_SETLK) || (cmd == F_SETLKW)) {
1549 #ifdef AFS_SUN53_ENV
1550 ap->l_pid = ttoproc(curthread)->p_pid;
1553 ap->l_pid = ttoproc(curthread)->p_epid;
1554 ap->l_sysid = ttoproc(curthread)->p_sysid;
1558 #ifdef AFS_SUN56_ENV
1559 code = convoff(vnp, ap, 0, off);
1561 code = convoff(vnp, ap, 0, (off_t)off);
1563 if (code) return code;
1567 code = afs_lockctl(VTOAFS(vnp), ap, cmd, credp);
1573 int afs_space(vnp, cmd, ap, flag, off, credp)
1576 #if defined(AFS_SUN56_ENV)
1583 struct AFS_UCRED *credp;
1585 register afs_int32 code = EINVAL;
1588 if ((cmd == F_FREESP)
1589 #ifdef AFS_SUN56_ENV
1590 && ((code = convoff(vnp, ap, 0, off)) == 0)) {
1592 && ((code = convoff(vnp, ap, 0, (off_t)off)) == 0)) {
1596 vattr.va_mask = AT_SIZE;
1597 vattr.va_size = ap->l_start;
1598 code = afs_setattr(VTOAFS(vnp), &vattr, 0, credp);
1608 int afs_dump(vp, addr, i1, i2)
1613 AFS_STATCNT(afs_dump);
1614 afs_warn("AFS_DUMP. MUST IMPLEMENT THIS!!!\n");
1619 /* Nothing fancy here; just compare if vnodes are identical ones */
1621 struct vnode *vp1, *vp2;
1623 AFS_STATCNT(afs_cmp);
1628 int afs_realvp(struct vnode *vp, struct vnode **vpp) {
1629 AFS_STATCNT(afs_realvp);
1634 int afs_pageio(vp, pp, ui1, ui2, i1, credp)
1641 afs_warn("afs_pageio: Not implemented\n");
1645 int afs_dumpctl(vp, i
1646 #ifdef AFS_SUN59_ENV
1652 #ifdef AFS_SUN59_ENV
1656 afs_warn("afs_dumpctl: Not implemented\n");
1660 #ifdef AFS_SUN54_ENV
1661 extern void afs_dispose(vp, p, fl, dn, cr)
1667 fs_dispose(vp, p, fl, dn, cr);
1670 int afs_setsecattr(vp, vsecattr, flag, creds)
1672 vsecattr_t *vsecattr;
1679 int afs_getsecattr(vp, vsecattr, flag, creds)
1681 vsecattr_t *vsecattr;
1685 return fs_fab_acl(vp, vsecattr, flag, creds);
1689 #ifdef AFS_GLOBAL_SUNLOCK
1690 extern int gafs_open(), gafs_close(), afs_ioctl(), gafs_access();
1691 extern int gafs_getattr(), gafs_setattr(), gafs_lookup(), gafs_create();
1692 extern int gafs_remove(), gafs_link(), gafs_rename(), gafs_mkdir();
1693 extern int gafs_rmdir(), gafs_readdir(), gafs_fsync(), gafs_symlink();
1694 extern int gafs_fid(), gafs_readlink(), fs_setfl(), afs_pathconf();
1695 extern int afs_lockctl();
1696 extern void gafs_inactive();
1698 struct vnodeops Afs_vnodeops = {
1738 #ifdef AFS_SUN54_ENV
1743 #if defined(AFS_SUN56_ENV)
1747 struct vnodeops *afs_ops = &Afs_vnodeops;
1751 gafs_open(avcp, aflags, acred)
1752 register struct vcache **avcp;
1754 struct AFS_UCRED *acred;
1759 code = afs_open(avcp, aflags, acred);
1765 gafs_close(avc, aflags, count, offset, acred)
1768 register struct vcache *avc;
1770 struct AFS_UCRED *acred;
1775 code = afs_close(avc, aflags, count, offset, acred);
1781 gafs_getattr(avc, attrs, flags, acred)
1783 register struct vcache *avc;
1784 register struct vattr *attrs;
1785 struct AFS_UCRED *acred;
1790 code = afs_getattr(avc, attrs, flags, acred);
1796 gafs_setattr(avc, attrs, flags, acred)
1798 register struct vcache *avc;
1799 register struct vattr *attrs;
1800 struct AFS_UCRED *acred;
1805 code = afs_setattr(avc, attrs, flags, acred);
1811 gafs_access(avc, amode, flags, acred)
1813 register struct vcache *avc;
1814 register afs_int32 amode;
1815 struct AFS_UCRED *acred;
1820 code = afs_access(avc, amode, flags, acred);
1826 gafs_lookup(adp, aname, avcp, pnp, flags, rdir, acred)
1827 struct pathname *pnp;
1830 register struct vcache *adp, **avcp;
1832 struct AFS_UCRED *acred;
1837 code = afs_lookup(adp, aname, avcp, pnp, flags, rdir, acred);
1843 gafs_create(adp, aname, attrs, aexcl, amode, avcp, acred)
1844 register struct vcache *adp;
1846 struct vattr *attrs;
1849 struct vcache **avcp;
1850 struct AFS_UCRED *acred;
1855 code = afs_create(adp, aname, attrs, aexcl, amode, avcp, acred);
1860 gafs_remove(adp, aname, acred)
1861 register struct vcache *adp;
1863 struct AFS_UCRED *acred;
1868 code = afs_remove(adp, aname, acred);
1873 gafs_link(adp, avc, aname, acred)
1874 register struct vcache *avc;
1875 register struct vcache *adp;
1877 struct AFS_UCRED *acred;
1882 code = afs_link(adp, avc, aname, acred);
1887 gafs_rename(aodp, aname1, andp, aname2, acred)
1888 register struct vcache *aodp, *andp;
1889 char *aname1, *aname2;
1890 struct AFS_UCRED *acred;
1895 code = afs_rename(aodp, aname1, andp, aname2, acred);
1900 gafs_mkdir(adp, aname, attrs, avcp, acred)
1901 register struct vcache *adp;
1902 register struct vcache **avcp;
1904 struct vattr *attrs;
1905 struct AFS_UCRED *acred;
1910 code = afs_mkdir(adp, aname, attrs, avcp, acred);
1916 gafs_rmdir(adp, aname, cdirp, acred)
1917 struct vnode *cdirp;
1918 register struct vcache *adp;
1920 struct AFS_UCRED *acred;
1925 code = afs_rmdir(adp, aname, cdirp, acred);
1931 gafs_readdir(avc, auio, acred, eofp)
1933 register struct vcache *avc;
1935 struct AFS_UCRED *acred;
1940 code = afs_readdir(avc, auio, acred, eofp);
1945 gafs_symlink(adp, aname, attrs, atargetName, acred)
1946 register struct vcache *adp;
1947 register char *atargetName;
1949 struct vattr *attrs;
1950 struct AFS_UCRED *acred;
1955 code = afs_symlink(adp, aname, attrs, atargetName, acred);
1961 gafs_readlink(avc, auio, acred)
1962 register struct vcache *avc;
1964 struct AFS_UCRED *acred;
1969 code = afs_readlink(avc, auio, acred);
1974 #ifdef AFS_SUN53_ENV
1975 gafs_fsync(avc, flag, acred)
1978 gafs_fsync(avc, acred)
1980 register struct vcache *avc;
1981 struct AFS_UCRED *acred;
1986 #ifdef AFS_SUN53_ENV
1987 code = afs_fsync(avc, flag, acred);
1989 code = afs_fsync(avc, acred);
1995 void afs_inactive(struct vcache *avc, struct AFS_UCRED *acred)
1997 struct vnode *vp = AFSTOV(avc);
1998 if (afs_shuttingdown) return ;
2001 * In Solaris and HPUX s800 and HP-UX10.0 they actually call us with
2002 * v_count 1 on last reference!
2004 mutex_enter(&vp->v_lock);
2005 if (avc->vrefCount <= 0) osi_Panic("afs_inactive : v_count <=0\n");
2008 * If more than 1 don't unmap the vnode but do decrement the ref count
2011 if (vp->v_count > 0) {
2012 mutex_exit(&vp->v_lock);
2015 mutex_exit(&vp->v_lock);
2017 * Solaris calls VOP_OPEN on exec, but isn't very diligent about calling
2018 * VOP_CLOSE when executable exits.
2020 if (avc->opens > 0 && !(avc->states & CCore))
2021 avc->opens = avc->execsOrWriters = 0;
2023 afs_InactiveVCache(avc, acred);
2026 void gafs_inactive(avc, acred)
2027 register struct vcache *avc;
2028 struct AFS_UCRED *acred;
2031 afs_inactive(avc, acred);
2036 gafs_fid(avc, fidpp)
2043 code = afs_fid(avc, fidpp);
2048 #endif /* AFS_GLOBAL_SUNLOCK */