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"
16 #if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
18 * SOLARIS/osi_vnodeops.c
22 * Functions: AFS_TRYUP, _init, _info, _fini, afs_addmap, afs_delmap,
23 * afs_vmread, afs_vmwrite, afs_getpage, afs_GetOnePage, afs_putpage,
24 * afs_putapage, afs_nfsrdwr, afs_map, afs_PageLeft, afs_pathconf/afs_cntl,
25 * afs_ioctl, afs_rwlock, afs_rwunlock, afs_seek, afs_space, afs_dump,
26 * afs_cmp, afs_realvp, afs_pageio, afs_dumpctl, afs_dispose, afs_setsecattr,
27 * afs_getsecattr, gafs_open, gafs_close, gafs_getattr, gafs_setattr,
28 * gafs_access, gafs_lookup, gafs_create, gafs_remove, gafs_link,
29 * gafs_rename, gafs_mkdir, gafs_rmdir, gafs_readdir, gafs_symlink,
30 * gafs_readlink, gafs_fsync, afs_inactive, gafs_inactive, gafs_fid
33 * Variables: Afs_vnodeops
36 #include "afs/sysincludes.h" /* Standard vendor system headers */
37 #include "afsincludes.h" /* Afs-based standard headers */
38 #include "afs/afs_stats.h" /* statistics */
39 #include "afs/nfsclient.h"
48 #include <vm/seg_map.h>
49 #include <vm/seg_vn.h>
51 #if defined(AFS_SUN5_ENV)
52 #include <sys/modctl.h>
53 #include <sys/syscall.h>
57 #include <sys/debug.h>
58 #if defined(AFS_SUN5_ENV)
59 #include <sys/fs_subr.h>
62 #if defined(AFS_SUN5_ENV)
64 * XXX Temporary fix for problems with Solaris rw_tryupgrade() lock.
65 * It isn't very persistent in getting the upgrade when others are
66 * waiting for it and returns 0. So the UpgradeSToW() macro that the
67 * rw_tryupgrade used to map to wasn't good enough and we need to use
68 * the following code instead. Obviously this isn't the proper place
69 * for it but it's only called from here for now
76 if (!rw_tryupgrade(lock)) {
78 rw_enter(lock, RW_WRITER);
85 /* Translate a faultcode_t as returned by some of the vm routines
86 * into a suitable errno value.
89 afs_fc2errno(faultcode_t fc)
91 switch (FC_CODE(fc)) {
104 extern struct as kas; /* kernel addr space */
105 extern unsigned char *afs_indexFlags;
106 extern afs_lock_t afs_xdcache;
108 /* Additional vnodeops for SunOS 4.0.x */
109 int afs_nfsrdwr(), afs_getpage(), afs_putpage(), afs_map();
110 int afs_dump(), afs_cmp(), afs_realvp(), afs_GetOnePage();
117 afs_addmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
118 register struct vnode *avp;
122 int length, prot, maxprot, flags;
123 struct AFS_UCRED *credp;
125 /* XXX What should we do here?? XXX */
130 afs_delmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
131 register struct vnode *avp;
135 int length, prot, maxprot, flags;
136 struct AFS_UCRED *credp;
138 /* XXX What should we do here?? XXX */
142 #ifdef AFS_SUN510_ENV
144 afs_vmread(avp, auio, ioflag, acred, ct)
145 register struct vnode *avp;
148 struct AFS_UCRED *acred;
149 caller_context_t *ct;
152 afs_vmread(avp, auio, ioflag, acred)
153 register struct vnode *avp;
156 struct AFS_UCRED *acred;
161 if (!RW_READ_HELD(&(VTOAFS(avp))->rwlock))
162 osi_Panic("afs_vmread: !rwlock");
164 code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_READ, ioflag, acred);
170 #ifdef AFS_SUN510_ENV
172 afs_vmwrite(avp, auio, ioflag, acred, ct)
173 register struct vnode *avp;
176 struct AFS_UCRED *acred;
177 caller_context_t *ct;
180 afs_vmwrite(avp, auio, ioflag, acred)
181 register struct vnode *avp;
184 struct AFS_UCRED *acred;
189 if (!RW_WRITE_HELD(&(VTOAFS(avp))->rwlock))
190 osi_Panic("afs_vmwrite: !rwlock");
192 code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_WRITE, ioflag, acred);
197 #endif /* AFS_SUN5_ENV */
200 afs_getpage(vp, off, len, protp, pl, plsz, seg, addr, rw, acred)
215 struct AFS_UCRED *acred;
217 register afs_int32 code = 0;
218 AFS_STATCNT(afs_getpage);
221 if (vp->v_flag & VNOMAP) /* File doesn't allow mapping */
227 #if defined(AFS_SUN56_ENV)
230 afs_GetOnePage(vp, off, len, protp, pl, plsz, seg, addr, rw,
236 afs_GetOnePage(vp, (u_int) off, len, protp, pl, plsz, seg, addr,
240 code = afs_GetOnePage(vp, off, protp, pl, plsz, seg, addr, rw, acred);
244 struct vcache *vcp = VTOAFS(vp);
246 ObtainWriteLock(&vcp->vlock, 548);
248 ReleaseWriteLock(&vcp->vlock);
250 afs_BozonLock(&vcp->pvnLock, vcp);
251 #if defined(AFS_SUN56_ENV)
253 pvn_getpages(afs_GetOnePage, vp, off, len, protp, pl, plsz, seg,
257 pvn_getpages(afs_GetOnePage, vp, (u_int) off, len, protp, pl,
258 plsz, seg, addr, rw, acred);
260 afs_BozonUnlock(&vcp->pvnLock, vcp);
262 ObtainWriteLock(&vcp->vlock, 549);
264 ReleaseWriteLock(&vcp->vlock);
271 /* Return all the pages from [off..off+len) in file */
274 afs_GetOnePage(vp, off, alen, protp, pl, plsz, seg, addr, rw, acred)
278 afs_GetOnePage(vp, off, protp, pl, plsz, seg, addr, rw, acred)
281 #if defined(AFS_SUN56_ENV)
296 struct AFS_UCRED *acred;
298 register struct page *page;
299 register afs_int32 code = 0;
303 register struct vcache *avc;
304 register struct dcache *tdc;
307 afs_size_t offset, nlen;
308 struct vrequest treq;
309 afs_int32 mapForRead = 0, Code = 0;
310 #if defined(AFS_SUN56_ENV)
318 osi_Panic("GetOnePage: !acred");
320 acred = u.u_cred; /* better than nothing */
323 avc = VTOAFS(vp); /* cast to afs vnode */
326 if (avc->credp /*&& AFS_NFSXLATORREQ(acred) */
327 && AFS_NFSXLATORREQ(avc->credp)) {
331 if (code = afs_InitReq(&treq, acred))
335 /* This is a read-ahead request, e.g. due to madvise. */
341 ObtainReadLock(&avc->lock);
343 while (plen > 0 && !afs_BBusy()) {
344 /* Obtain a dcache entry at off. 2 means don't fetch data. */
346 afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen,
351 /* Write-lock the dcache entry, if we don't succeed, just go on */
352 if (0 != NBObtainWriteLock(&tdc->lock, 642)) {
357 /* If we aren't already fetching this dcache entry, queue it */
358 if (!(tdc->mflags & DFFetchReq)) {
361 tdc->mflags |= DFFetchReq;
362 bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
363 (afs_size_t) off, (afs_size_t) 1, tdc);
365 /* Unable to start background fetch; might as well stop */
366 tdc->mflags &= ~DFFetchReq;
367 ReleaseWriteLock(&tdc->lock);
371 ReleaseWriteLock(&tdc->lock);
373 ReleaseWriteLock(&tdc->lock);
378 /* Adjust our offset and remaining length values */
382 /* If we aren't making progress for some reason, bail out */
387 ReleaseReadLock(&avc->lock);
392 pl[0] = NULL; /* Make sure it's empty */
394 /* first, obtain the proper lock for the VM system */
396 /* if this is a read request, map the page in read-only. This will
397 * allow us to swap out the dcache entry if there are only read-only
398 * pages created for the chunk, which helps a *lot* when dealing
399 * with small caches. Otherwise, we have to invalidate the vm
400 * pages for the range covered by a chunk when we swap out the
403 if (rw == S_READ || rw == S_EXEC)
409 if (AFS_NFSXLATORREQ(acred)) {
412 (avc, PRSFS_READ, &treq,
413 CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
422 if (rw == S_WRITE || rw == S_CREATE)
423 tdc = afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen, 5);
425 tdc = afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen, 1);
429 code = afs_VerifyVCache(avc, &treq);
434 return afs_CheckCode(code, &treq, 44); /* failed to get it */
437 afs_BozonLock(&avc->pvnLock, avc);
438 ObtainReadLock(&avc->lock);
440 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, (afs_int32) vp,
441 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off), ICL_TYPE_LONG, len,
442 ICL_TYPE_LONG, (int)rw);
448 /* Check to see if we're in the middle of a VM purge, and if we are, release
449 * the locks and try again when the VM purge is done. */
450 ObtainWriteLock(&avc->vlock, 550);
452 ReleaseReadLock(&avc->lock);
453 ReleaseWriteLock(&avc->vlock);
454 afs_BozonUnlock(&avc->pvnLock, avc);
456 /* Check activeV again, it may have been turned off
457 * while we were waiting for a lock in afs_PutDCache */
458 ObtainWriteLock(&avc->vlock, 574);
460 avc->vstates |= VRevokeWait;
461 ReleaseWriteLock(&avc->vlock);
462 afs_osi_Sleep(&avc->vstates);
464 ReleaseWriteLock(&avc->vlock);
468 ReleaseWriteLock(&avc->vlock);
471 /* We're about to do stuff with our dcache entry.. Lock it. */
472 ObtainReadLock(&tdc->lock);
474 /* Check to see whether the cache entry is still valid */
475 if (!(avc->states & CStatd)
476 || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
477 ReleaseReadLock(&tdc->lock);
478 ReleaseReadLock(&avc->lock);
479 afs_BozonUnlock(&avc->pvnLock, avc);
485 while (1) { /* loop over all pages */
486 /* now, try to find the page in memory (it may already be intransit or laying
487 * around the free list */
489 page_lookup(vp, toffset, (rw == S_CREATE ? SE_EXCL : SE_SHARED));
493 /* if we make it here, we can't find the page in memory. Do a real disk read
494 * from the cache to get the data */
495 Code |= 0x200; /* XXX */
497 #if defined(AFS_SUN54_ENV)
498 /* use PG_EXCL because we know the page does not exist already. If it
499 * actually does exist, we have somehow raced between lookup and create.
500 * As of 4/98, that shouldn't be possible, but we'll be defensive here
501 * in case someone tries to relax all the serialization of read and write
502 * operations with harmless things like stat. */
503 #if defined(AFS_SUN58_ENV)
505 page_create_va(vp, toffset, PAGESIZE, PG_WAIT | PG_EXCL, seg,
509 page_create_va(vp, toffset, PAGESIZE, PG_WAIT | PG_EXCL,
513 page = page_create(vp, toffset, PAGESIZE, PG_WAIT);
519 pagezero(page, alen, PAGESIZE - alen);
521 page = rm_allocpage(seg, addr, PAGESIZE, 1); /* can't fail */
523 osi_Panic("afs_getpage alloc page");
524 /* we get a circularly-linked list of pages back, but we expect only
525 * one, since that's what we asked for */
526 if (page->p_next != page)
527 osi_Panic("afs_getpage list");
528 /* page enter returns a locked page; we'll drop the lock as a side-effect
529 * of the pvn_done done by afs_ustrategy. If we decide not to call
530 * strategy, we must be sure to call pvn_fail, at least, to release the
531 * page locks and otherwise reset the pages. The page, while locked, is
532 * not held, for what it is worth */
533 page->p_intrans = 1; /* set appropriate flags */
535 /* next call shouldn't fail, since we have pvnLock set */
536 if (page_enter(page, vp, toffset))
537 osi_Panic("afs_getpage enter race");
538 #endif /* AFS_SUN5_ENV */
541 if (rw == S_CREATE) {
542 /* XXX Don't read from AFS in write only cases XXX */
543 page_io_unlock(page);
547 /* XXX Don't read from AFS in write only cases XXX */
548 page->p_intrans = page->p_pagein = 0;
549 page_unlock(page); /* XXX */
556 /* now it is time to start I/O operation */
557 buf = pageio_setup(page, PAGESIZE, vp, B_READ); /* allocate a buf structure */
558 #if defined(AFS_SUN5_ENV)
562 buf->b_blkno = btodb(toffset);
563 bp_mapin(buf); /* map it in to our address space */
565 #if defined(AFS_SUN5_ENV)
567 /* afs_ustrategy will want to lock the dcache entry */
568 ReleaseReadLock(&tdc->lock);
569 code = afs_ustrategy(buf, acred); /* do the I/O */
570 ObtainReadLock(&tdc->lock);
573 ReleaseReadLock(&tdc->lock);
574 ReleaseReadLock(&avc->lock);
575 code = afs_ustrategy(buf); /* do the I/O */
576 ObtainReadLock(&avc->lock);
577 ObtainReadLock(&tdc->lock);
581 /* Before freeing unmap the buffer */
592 page_io_unlock(page);
596 /* come here when we have another page (already held) to enter */
598 /* put page in array and continue */
600 /* The p_selock must be downgraded to a shared lock after the page is read */
601 #if defined(AFS_SUN56_ENV)
602 if ((rw != S_CREATE) && !(PAGE_SHARED(page)))
604 if ((rw != S_CREATE) && !(se_shared_assert(&page->p_selock)))
607 page_downgrade(page);
612 code = page_iolock_assert(page);
619 break; /* done all the pages */
620 } /* while (1) ... */
624 ReleaseReadLock(&tdc->lock);
626 /* Prefetch next chunk if we're at a chunk boundary */
627 if (AFS_CHUNKOFFSET(off) == 0) {
628 if (!(tdc->mflags & DFNextStarted))
629 afs_PrefetchChunk(avc, tdc, acred, &treq);
632 ReleaseReadLock(&avc->lock);
634 ObtainWriteLock(&afs_xdcache, 246);
636 /* track that we have dirty (or dirty-able) pages for this chunk. */
637 afs_indexFlags[tdc->index] |= IFDirtyPages;
639 afs_indexFlags[tdc->index] |= IFAnyPages;
640 ReleaseWriteLock(&afs_xdcache);
642 afs_BozonUnlock(&avc->pvnLock, avc);
646 afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code,
647 ICL_TYPE_LONG, (int)page, ICL_TYPE_LONG, Code);
652 afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code,
653 ICL_TYPE_LONG, (int)page, ICL_TYPE_LONG, Code);
654 /* release all pages, drop locks, return code */
657 pvn_read_done(page, B_ERROR);
659 for (i = 0; i < slot; i++)
662 ReleaseReadLock(&avc->lock);
663 afs_BozonUnlock(&avc->pvnLock, avc);
665 ReleaseReadLock(&tdc->lock);
673 afs_putpage(vp, off, len, flags, cred)
678 struct AFS_UCRED *cred;
683 #if defined(AFS_SUN58_ENV)
689 afs_int32 NPages = 0;
690 #if defined(AFS_SUN56_ENV)
691 u_offset_t toff = off;
697 AFS_STATCNT(afs_putpage);
698 if (vp->v_flag & VNOMAP) /* file doesn't allow mapping */
702 * Putpage (ASYNC) is called every sec to flush out dirty vm pages
705 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER,
706 (afs_int32) vp, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
707 ICL_TYPE_INT32, (afs_int32) len, ICL_TYPE_LONG, (int)flags);
709 afs_BozonLock(&avc->pvnLock, avc);
710 ObtainSharedLock(&avc->lock, 247);
713 /* Get a list of modified (or whatever) pages */
715 endPos = (afs_offs_t) off + len; /* position we're supposed to write up to */
716 while ((afs_offs_t) toff < endPos
717 && (afs_offs_t) toff < avc->m.Length) {
718 /* If not invalidating pages use page_lookup_nowait to avoid reclaiming
719 * them from the free list
722 if (flags & (B_FREE | B_INVAL))
723 pages = page_lookup(vp, toff, SE_EXCL);
725 pages = page_lookup_nowait(vp, toff, SE_SHARED);
726 if (!pages || !pvn_getdirty(pages, flags))
732 UpgradeSToWLock(&avc->lock, 671);
736 code = afs_putapage(vp, pages, &toff, &tlen, flags, cred);
747 UpgradeSToWLock(&avc->lock, 670);
752 #if defined(AFS_SUN56_ENV)
753 code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
755 code = pvn_vplist_dirty(vp, (u_int) off, afs_putapage, flags, cred);
760 if (code && !avc->vc_error) {
762 UpgradeSToWLock(&avc->lock, 669);
765 avc->vc_error = code;
769 ReleaseWriteLock(&avc->lock);
771 ReleaseSharedLock(&avc->lock);
772 afs_BozonUnlock(&avc->pvnLock, avc);
773 afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code,
774 ICL_TYPE_LONG, NPages);
781 afs_putapage(struct vnode *vp, struct page *pages,
782 #if defined(AFS_SUN56_ENV)
787 #if defined(AFS_SUN58_ENV)
792 int flags, struct AFS_UCRED *credp)
795 struct vcache *avc = VTOAFS(vp);
797 u_int tlen = PAGESIZE;
798 afs_offs_t off = (pages->p_offset / PAGESIZE) * PAGESIZE;
801 * Now we've got the modified pages. All pages are locked and held
802 * XXX Find a kluster that fits in one block (or page). We also
803 * adjust the i/o if the file space is less than a while page. XXX
805 if (off + tlen > avc->m.Length) {
806 tlen = avc->m.Length - off;
808 /* can't call mapout with 0 length buffers (rmfree panics) */
809 if (((tlen >> 24) & 0xff) == 0xff) {
814 * Can't call mapout with 0 length buffers since we'll get rmfree panics
816 tbuf = pageio_setup(pages, tlen, vp, B_WRITE | flags);
821 tbuf->b_blkno = btodb(pages->p_offset);
824 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUTONE, ICL_TYPE_LONG, avc,
825 ICL_TYPE_LONG, pages, ICL_TYPE_LONG, tlen, ICL_TYPE_OFFSET,
826 ICL_HANDLE_OFFSET(off));
827 code = afs_ustrategy(tbuf, credp); /* unlocks page */
831 pvn_write_done(pages, ((code) ? B_ERROR : 0) | B_WRITE | flags);
841 #else /* AFS_SUN5_ENV */
844 afs_putpage(vp, off, len, flags, cred)
849 struct AFS_UCRED *cred;
851 int wholeEnchilada; /* true if we must get all of the pages */
857 afs_int32 code = 0, rcode;
859 afs_int32 clusterStart, clusterEnd, endPos;
861 /* In the wholeEnchilada case, we must ensure that we get all of the pages
862 * from the system, since we're doing this to shutdown the use of a vnode */
864 AFS_STATCNT(afs_putpage);
865 wholeEnchilada = (off == 0 && len == 0
866 && (flags & (B_INVAL | B_ASYNC)) == B_INVAL);
869 afs_BozonLock(&avc->pvnLock, avc);
870 ObtainWriteLock(&avc->lock, 248);
873 /* in whole enchilada case, loop until call to pvn_getdirty can't find
874 * any more modified pages */
876 /* first we try to get a list of modified (or whatever) pages */
878 pages = pvn_vplist_dirty(vp, off, flags);
880 endPos = off + len; /* position we're supposed to write up to */
881 if (endPos > avc->m.Length)
882 endPos = avc->m.Length; /* bound by this */
883 clusterStart = off & ~(PAGESIZE - 1); /* round down to nearest page */
884 clusterEnd = ((endPos - 1) | (PAGESIZE - 1)) + 1; /* round up to nearest page */
886 pvn_range_dirty(vp, off, endPos, clusterStart, clusterEnd,
890 /* Now we've got the modified pages. All pages are locked and held */
891 rcode = 0; /* return code */
892 while (pages) { /* look over all pages in the returned set */
893 tpage = pages; /* get first page in the list */
895 /* write out the page */
896 poffset = tpage->p_offset; /* where the page starts in the file */
897 /* tlen will represent the end of the range to write, for a while */
898 tlen = PAGESIZE + poffset; /* basic place to end tpage write */
899 /* but we also don't want to write past end of off..off+len range */
900 if (len != 0 && tlen > off + len)
902 /* and we don't want to write past the end of the file */
903 if (tlen > avc->m.Length)
904 tlen = avc->m.Length;
905 /* and we don't want to write at all if page starts after end */
906 if (poffset >= tlen) {
907 pvn_fail(pages, B_WRITE | flags);
910 /* finally change tlen from end position to length */
911 tlen -= poffset; /* compute bytes to write from this page */
912 page_sub(&pages, tpage); /* remove tpage from "pages" list */
913 tbuf = pageio_setup(tpage, tlen, vp, B_WRITE | flags);
915 pvn_fail(tpage, B_WRITE | flags);
916 pvn_fail(pages, B_WRITE | flags);
920 tbuf->b_blkno = btodb(tpage->p_offset);
922 ReleaseWriteLock(&avc->lock); /* can't hold during strategy call */
923 code = afs_ustrategy(tbuf); /* unlocks page */
924 ObtainWriteLock(&avc->lock, 249); /* re-obtain */
926 /* unlocking of tpage is done by afs_ustrategy */
928 if (pages) /* may have already removed last page */
929 pvn_fail(pages, B_WRITE | flags);
932 } /* for (tpage=pages....) */
934 /* see if we've gotten all of the pages in the whole enchilada case */
935 if (!wholeEnchilada || !vp->v_pages)
937 } /* while(1) obtaining all pages */
940 * If low on chunks, and if writing the last byte of a chunk, try to
941 * free some. Note that afs_DoPartialWrite calls osi_SyncVM which now
942 * calls afs_putpage, so this is recursion. It stops there because we
943 * insist on len being non-zero.
945 if (afs_stats_cmperf.cacheCurrDirtyChunks >
946 afs_stats_cmperf.cacheMaxDirtyChunks && len != 0
947 && AFS_CHUNKOFFSET((off + len)) == 0) {
948 struct vrequest treq;
949 if (!afs_InitReq(&treq, cred ? cred : u.u_cred)) {
950 rcode = afs_DoPartialWrite(avc, &treq); /* XXX */
956 if (rcode && !avc->vc_error)
957 avc->vc_error = rcode;
959 /* when we're here, we just return code. */
960 ReleaseWriteLock(&avc->lock);
961 afs_BozonUnlock(&avc->pvnLock, avc);
965 #endif /* AFS_SUN5_ENV */
968 afs_nfsrdwr(avc, auio, arw, ioflag, acred)
969 register struct vcache *avc;
973 struct AFS_UCRED *acred;
975 register afs_int32 code;
978 afs_int32 mode, sflags;
980 struct dcache *dcp, *dcp_newpage;
981 afs_size_t fileBase, size;
983 register afs_int32 tsize;
984 register afs_int32 pageOffset, extraResid = 0;
985 register afs_size_t origLength; /* length when reading/writing started */
986 register long appendLength; /* length when this call will finish */
987 int created; /* created pages instead of faulting them */
989 int didFakeOpen, eof;
990 struct vrequest treq;
994 AFS_STATCNT(afs_nfsrdwr);
996 /* can't read or write other things */
997 if (vType(avc) != VREG)
1000 if (auio->uio_resid == 0)
1003 afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, (afs_int32) avc,
1004 ICL_TYPE_LONG, (arw == UIO_WRITE ? 1 : 0), ICL_TYPE_OFFSET,
1005 ICL_HANDLE_OFFSET(auio->uio_offset), ICL_TYPE_OFFSET,
1006 ICL_HANDLE_OFFSET(auio->uio_resid));
1008 #ifndef AFS_64BIT_CLIENT
1009 if (AfsLargeFileUio(auio)) /* file is larger than 2 GB */
1015 osi_Panic("rdwr: !acred");
1020 if (code = afs_InitReq(&treq, acred))
1023 /* It's not really possible to know if a write cause a growth in the
1024 * cache size, we we wait for a cache drain for any write.
1026 afs_MaybeWakeupTruncateDaemon();
1027 while ((arw == UIO_WRITE)
1028 && (afs_blocksUsed > (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100)) {
1029 if (afs_blocksUsed - afs_blocksDiscarded >
1030 (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
1031 afs_WaitForCacheDrain = 1;
1032 afs_osi_Sleep(&afs_WaitForCacheDrain);
1034 afs_MaybeFreeDiscardedDCache();
1035 afs_MaybeWakeupTruncateDaemon();
1037 code = afs_VerifyVCache(avc, &treq);
1039 return afs_CheckCode(code, &treq, 45);
1041 afs_BozonLock(&avc->pvnLock, avc);
1042 osi_FlushPages(avc, acred); /* hold bozon lock, but not basic vnode lock */
1044 ObtainWriteLock(&avc->lock, 250);
1046 /* adjust parameters when appending files */
1047 if ((ioflag & IO_APPEND) && arw == UIO_WRITE) {
1048 #if defined(AFS_SUN56_ENV)
1049 auio->uio_loffset = 0;
1051 auio->uio_offset = avc->m.Length; /* write at EOF position */
1053 if (auio->uio_offset < 0 || (auio->uio_offset + auio->uio_resid) < 0) {
1054 ReleaseWriteLock(&avc->lock);
1055 afs_BozonUnlock(&avc->pvnLock, avc);
1058 #ifndef AFS_64BIT_CLIENT
1059 /* file is larger than 2GB */
1060 if (AfsLargeFileSize(auio->uio_offset, auio->uio_resid)) {
1061 ReleaseWriteLock(&avc->lock);
1062 afs_BozonUnlock(&avc->pvnLock, avc);
1067 didFakeOpen = 0; /* keep track of open so we can do close */
1068 if (arw == UIO_WRITE) {
1069 /* do ulimit processing; shrink resid or fail */
1070 #if defined(AFS_SUN56_ENV)
1071 if (auio->uio_loffset + auio->afsio_resid > auio->uio_llimit) {
1072 if (auio->uio_loffset >= auio->uio_llimit) {
1073 ReleaseWriteLock(&avc->lock);
1074 afs_BozonUnlock(&avc->pvnLock, avc);
1077 /* track # of bytes we should write, but won't because of
1078 * ulimit; we must add this into the final resid value
1079 * so caller knows we punted some data.
1081 extraResid = auio->uio_resid;
1082 auio->uio_resid = auio->uio_llimit - auio->uio_loffset;
1083 extraResid -= auio->uio_resid;
1087 #ifdef AFS_SUN52_ENV
1088 if (auio->afsio_offset + auio->afsio_resid > auio->uio_limit) {
1089 if (auio->afsio_offset >= auio->uio_limit) {
1090 ReleaseWriteLock(&avc->lock);
1091 afs_BozonUnlock(&avc->pvnLock, avc);
1094 /* track # of bytes we should write, but won't because of
1095 * ulimit; we must add this into the final resid value
1096 * so caller knows we punted some data.
1098 extraResid = auio->uio_resid;
1099 auio->uio_resid = auio->uio_limit - auio->afsio_offset;
1100 extraResid -= auio->uio_resid;
1105 mode = S_WRITE; /* segment map-in mode */
1106 afs_FakeOpen(avc); /* do this for writes, so data gets put back
1107 * when we want it to be put back */
1108 didFakeOpen = 1; /* we'll be doing a fake open */
1109 /* before starting any I/O, we must ensure that the file is big enough
1110 * to hold the results (since afs_putpage will be called to force the I/O */
1111 size = auio->afsio_resid + auio->afsio_offset; /* new file size */
1112 appendLength = size;
1113 origLength = avc->m.Length;
1114 if (size > avc->m.Length) {
1115 afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
1116 __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
1117 ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_OFFSET,
1118 ICL_HANDLE_OFFSET(size));
1119 avc->m.Length = size; /* file grew */
1121 avc->states |= CDirty; /* Set the dirty bit */
1122 avc->m.Date = osi_Time(); /* Set file date (for ranlib) */
1124 mode = S_READ; /* map-in read-only */
1125 origLength = avc->m.Length;
1128 if (acred && AFS_NFSXLATORREQ(acred)) {
1129 if (arw == UIO_READ) {
1131 (avc, PRSFS_READ, &treq,
1132 CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
1133 ReleaseWriteLock(&avc->lock);
1134 afs_BozonUnlock(&avc->pvnLock, avc);
1146 counter = 0; /* don't call afs_DoPartialWrite first time through. */
1148 /* compute the amount of data to move into this block,
1149 * based on auio->afsio_resid. Note that we copy data in units of
1150 * MAXBSIZE, not PAGESIZE. This is because segmap_getmap panics if you
1151 * call it with an offset based on blocks smaller than MAXBSIZE
1152 * (implying that it should be named BSIZE, since it is clearly both a
1153 * max and a min). */
1154 size = auio->afsio_resid; /* transfer size */
1155 fileBase = auio->afsio_offset; /* start file position for xfr */
1156 pageBase = fileBase & ~(MAXBSIZE - 1); /* file position of the page */
1157 pageOffset = fileBase & (MAXBSIZE - 1); /* xfr start's offset within page */
1158 tsize = MAXBSIZE - pageOffset; /* how much more fits in this page */
1159 /* we'll read tsize bytes, but first must make sure tsize isn't too big */
1161 tsize = size; /* don't read past end of request */
1162 eof = 0; /* flag telling us if we hit the EOF on the read */
1163 if (arw == UIO_READ) { /* we're doing a read operation */
1164 /* don't read past EOF */
1165 if (fileBase + tsize > origLength) {
1166 tsize = origLength - fileBase;
1167 eof = 1; /* we did hit the EOF */
1169 tsize = 0; /* better safe than sorry */
1174 /* Purge dirty chunks of file if there are too many dirty
1175 * chunks. Inside the write loop, we only do this at a chunk
1176 * boundary. Clean up partial chunk if necessary at end of loop.
1178 if (counter > 0 && code == 0 && AFS_CHUNKOFFSET(fileBase) == 0) {
1179 code = afs_DoPartialWrite(avc, &treq);
1183 #endif /* AFS_SUN5_ENV */
1184 /* write case, we ask segmap_release to call putpage. Really, we
1185 * don't have to do this on every page mapin, but for now we're
1186 * lazy, and don't modify the rest of AFS to scan for modified
1187 * pages on a close or other "synchronize with file server"
1188 * operation. This makes things a little cleaner, but probably
1189 * hurts performance. */
1194 break; /* nothing to transfer, we're done */
1197 if (arw == UIO_WRITE)
1198 avc->states |= CDirty; /* may have been cleared by DoPartialWrite */
1200 /* Before dropping lock, hold the chunk (create it if necessary). This
1201 * serves two purposes: (1) Ensure Cache Truncate Daemon doesn't try
1202 * to purge the chunk's pages while we have them locked. This would
1203 * cause deadlock because we might be waiting for the CTD to free up
1204 * a chunk. (2) If we're writing past the original EOF, and we're
1205 * at the base of the chunk, then make sure it exists online
1206 * before we do the uiomove, since the segmap_release will
1207 * write out to the chunk, causing it to get fetched if it hasn't
1208 * been created yet. The code that would otherwise notice that
1209 * we're fetching a chunk past EOF won't work, since we've
1210 * already adjusted the file size above.
1212 ObtainWriteLock(&avc->vlock, 551);
1213 while (avc->vstates & VPageCleaning) {
1214 ReleaseWriteLock(&avc->vlock);
1215 ReleaseWriteLock(&avc->lock);
1216 afs_osi_Sleep(&avc->vstates);
1217 ObtainWriteLock(&avc->lock, 334);
1218 ObtainWriteLock(&avc->vlock, 552);
1220 ReleaseWriteLock(&avc->vlock);
1222 afs_size_t toff, tlen;
1223 dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
1230 ReleaseWriteLock(&avc->lock); /* uiomove may page fault */
1232 #if defined(AFS_SUN56_ENV)
1233 data = segmap_getmap(segkmap, AFSTOV(avc), (u_offset_t) pageBase);
1235 data = segmap_getmap(segkmap, AFSTOV(avc), pageBase);
1237 #ifndef AFS_SUN5_ENV
1239 afs_fc2errno(as_fault
1240 (&kas, data + pageOffset, tsize, F_SOFTLOCK, mode));
1242 AFS_UIOMOVE(data + pageOffset, tsize, arw, auio, code);
1243 as_fault(&kas, data + pageOffset, tsize, F_SOFTUNLOCK, mode);
1244 code2 = segmap_release(segkmap, data, sflags);
1248 (void)segmap_release(segkmap, data, 0);
1251 #if defined(AFS_SUN56_ENV)
1252 raddr = (caddr_t) (((uintptr_t) data + pageOffset) & PAGEMASK);
1254 raddr = (caddr_t) (((u_int) data + pageOffset) & PAGEMASK);
1257 (((u_int) data + pageOffset + tsize + PAGEOFFSET) & PAGEMASK) -
1260 /* if we're doing a write, and we're starting at the rounded
1261 * down page base, and we're writing enough data to cover all
1262 * created pages, then we must be writing all of the pages
1263 * in this MAXBSIZE window that we're creating.
1266 if (arw == UIO_WRITE && ((long)raddr == (long)data + pageOffset)
1267 && tsize >= rsize) {
1268 /* probably the dcache backing this guy is around, but if
1269 * not, we can't do this optimization, since we're creating
1270 * writable pages, which must be backed by a chunk.
1273 dcp_newpage = afs_FindDCache(avc, pageBase);
1275 && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)) {
1276 ObtainWriteLock(&avc->lock, 251);
1277 ObtainWriteLock(&avc->vlock, 576);
1278 ObtainReadLock(&dcp_newpage->lock);
1279 if ((avc->activeV == 0)
1280 && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)
1281 && !(dcp_newpage->dflags & (DFFetching))) {
1283 segmap_pagecreate(segkmap, raddr, rsize, 1);
1285 ObtainWriteLock(&afs_xdcache, 252);
1286 /* Mark the pages as created and dirty */
1287 afs_indexFlags[dcp_newpage->index]
1288 |= (IFAnyPages | IFDirtyPages);
1289 ReleaseWriteLock(&afs_xdcache);
1292 ReleaseReadLock(&dcp_newpage->lock);
1293 afs_PutDCache(dcp_newpage);
1294 ReleaseWriteLock(&avc->vlock);
1295 ReleaseWriteLock(&avc->lock);
1296 } else if (dcp_newpage)
1297 afs_PutDCache(dcp_newpage);
1302 afs_fc2errno(segmap_fault
1303 (kas.a_hat, segkmap, raddr, rsize,
1307 AFS_UIOMOVE(data + pageOffset, tsize, arw, auio, code);
1308 segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTUNLOCK,
1312 code = segmap_release(segkmap, data, sflags);
1314 (void)segmap_release(segkmap, data, 0);
1316 #endif /* AFS_SUN5_ENV */
1318 ObtainWriteLock(&avc->lock, 253);
1323 #endif /* AFS_SUN5_ENV */
1328 afs_FakeClose(avc, acred);
1331 if (arw == UIO_WRITE && (avc->states & CDirty)) {
1332 code2 = afs_DoPartialWrite(avc, &treq);
1336 #endif /* AFS_SUN5_ENV */
1338 if (!code && avc->vc_error) {
1339 code = avc->vc_error;
1341 ReleaseWriteLock(&avc->lock);
1342 afs_BozonUnlock(&avc->pvnLock, avc);
1344 #ifdef AFS_SUN53_ENV
1345 if ((ioflag & FSYNC) && (arw == UIO_WRITE)
1346 && !AFS_NFSXLATORREQ(acred))
1347 code = afs_fsync(avc, 0, acred);
1349 if ((ioflag & IO_SYNC) && (arw == UIO_WRITE)
1350 && !AFS_NFSXLATORREQ(acred))
1351 code = afs_fsync(avc, acred);
1354 #ifdef AFS_SUN52_ENV
1356 * If things worked, add in as remaining in request any bytes
1357 * we didn't write due to file size ulimit.
1359 if (code == 0 && extraResid > 0)
1360 auio->uio_resid += extraResid;
1362 return afs_CheckCode(code, &treq, 46);
1365 afs_map(vp, off, as, addr, len, prot, maxprot, flags, cred)
1377 u_char prot, maxprot;
1379 u_int prot, maxprot;
1382 struct AFS_UCRED *cred;
1384 struct segvn_crargs crargs;
1385 register afs_int32 code;
1386 struct vrequest treq;
1387 register struct vcache *avc = VTOAFS(vp);
1389 AFS_STATCNT(afs_map);
1392 /* check for reasonableness on segment bounds; apparently len can be < 0 */
1393 if (off < 0 || off + len < 0) {
1396 #ifndef AFS_64BIT_CLIENT
1397 if (AfsLargeFileSize(off, len)) { /* file is larger than 2 GB */
1403 #if defined(AFS_SUN5_ENV)
1404 if (vp->v_flag & VNOMAP) /* File isn't allowed to be mapped */
1407 if (vp->v_filocks) /* if locked, disallow mapping */
1411 if (code = afs_InitReq(&treq, cred))
1414 if (vp->v_type != VREG) {
1419 code = afs_VerifyVCache(avc, &treq);
1423 afs_BozonLock(&avc->pvnLock, avc);
1424 osi_FlushPages(avc, cred); /* ensure old pages are gone */
1425 avc->states |= CMAPPED; /* flag cleared at afs_inactive */
1426 afs_BozonUnlock(&avc->pvnLock, avc);
1432 if ((flags & MAP_FIXED) == 0) {
1433 #if defined(AFS_SUN57_ENV)
1434 map_addr(addr, len, off, 1, flags);
1435 #elif defined(AFS_SUN56_ENV)
1436 map_addr(addr, len, off, 1);
1438 map_addr(addr, len, (off_t) off, 1);
1440 if (*addr == NULL) {
1448 (void)as_unmap(as, *addr, len); /* unmap old address space use */
1449 /* setup the create parameter block for the call */
1450 crargs.vp = AFSTOV(avc);
1451 crargs.offset = (u_int) off;
1453 crargs.type = flags & MAP_TYPE;
1455 crargs.maxprot = maxprot;
1456 crargs.amp = (struct anon_map *)0;
1457 #if defined(AFS_SUN5_ENV)
1458 crargs.flags = flags & ~MAP_TYPE;
1461 code = as_map(as, *addr, len, segvn_create, (char *)&crargs);
1467 code = afs_CheckCode(code, &treq, 47);
1471 code = afs_CheckCode(code, &treq, 48);
1476 /* Sun 4.0.X-specific code. It computes the number of bytes that need
1477 to be zeroed at the end of a page by pvn_vptrunc, given that you're
1478 trying to get vptrunc to truncate a file to alen bytes. The result
1479 will be passed to pvn_vptrunc by the truncate code */
1480 #ifndef AFS_SUN5_ENV /* Not good for Solaris */
1482 register afs_int32 alen;
1484 register afs_int32 nbytes;
1486 AFS_STATCNT(afs_PageLeft);
1487 nbytes = PAGESIZE - (alen & PAGEOFFSET); /* amount to zap in last page */
1488 /* now check if we'd zero the entire last page. Don't need to do this
1489 * since pvn_vptrunc will handle this case properly (it will invalidate
1491 if (nbytes == PAGESIZE)
1494 nbytes = 0; /* just in case */
1501 * For Now We use standard local kernel params for AFS system values. Change this
1504 #if defined(AFS_SUN5_ENV)
1505 afs_pathconf(vp, cmd, outdatap, credp)
1506 register struct AFS_UCRED *credp;
1508 afs_cntl(vp, cmd, indatap, outdatap, inflag, outflag)
1509 int inflag, outflag;
1516 AFS_STATCNT(afs_cntl);
1519 *outdatap = MAXLINK;
1522 *outdatap = MAXNAMLEN;
1525 *outdatap = MAXPATHLEN;
1527 case _PC_CHOWN_RESTRICTED:
1533 #if !defined(AFS_SUN5_ENV)
1535 *outdatap = CANBSIZ;
1538 *outdatap = VDISABLE;
1550 #endif /* AFS_SUN_ENV */
1552 #if defined(AFS_SUN5_ENV)
1554 afs_ioctl(vnp, com, arg, flag, credp, rvalp)
1564 afs_rwlock(vnp, wlock)
1568 rw_enter(&(VTOAFS(vnp))->rwlock, (wlock ? RW_WRITER : RW_READER));
1573 afs_rwunlock(vnp, wlock)
1577 rw_exit(&(VTOAFS(vnp))->rwlock);
1582 afs_seek(vnp, ooff, noffp)
1587 register int code = 0;
1589 if ((*noffp < 0 || *noffp > MAXOFF_T))
1595 afs_frlock(vnp, cmd, ap, flag, off,
1596 #ifdef AFS_SUN59_ENV
1602 #if defined(AFS_SUN56_ENV)
1609 #ifdef AFS_SUN59_ENV
1610 struct flk_callback *flkcb;
1612 struct AFS_UCRED *credp;
1614 register afs_int32 code = 0;
1616 * Implement based on afs_lockctl
1619 #ifdef AFS_SUN59_ENV
1621 afs_warn("Don't know how to deal with flk_callback's!\n");
1623 if ((cmd == F_GETLK) || (cmd == F_O_GETLK) || (cmd == F_SETLK)
1624 || (cmd == F_SETLKW)) {
1625 #ifdef AFS_SUN53_ENV
1626 ap->l_pid = ttoproc(curthread)->p_pid;
1629 ap->l_pid = ttoproc(curthread)->p_epid;
1630 ap->l_sysid = ttoproc(curthread)->p_sysid;
1634 #ifdef AFS_SUN56_ENV
1635 code = convoff(vnp, ap, 0, off);
1637 code = convoff(vnp, ap, 0, (off_t) off);
1644 code = afs_lockctl(VTOAFS(vnp), ap, cmd, credp);
1651 afs_space(vnp, cmd, ap, flag, off, credp)
1654 #if defined(AFS_SUN56_ENV)
1661 struct AFS_UCRED *credp;
1663 register afs_int32 code = EINVAL;
1666 if ((cmd == F_FREESP)
1667 #ifdef AFS_SUN56_ENV
1668 && ((code = convoff(vnp, ap, 0, off)) == 0)) {
1670 && ((code = convoff(vnp, ap, 0, (off_t) off)) == 0)) {
1674 vattr.va_mask = AT_SIZE;
1675 vattr.va_size = ap->l_start;
1676 code = afs_setattr(VTOAFS(vnp), &vattr, 0, credp);
1687 afs_dump(vp, addr, i1, i2)
1692 AFS_STATCNT(afs_dump);
1693 afs_warn("AFS_DUMP. MUST IMPLEMENT THIS!!!\n");
1698 /* Nothing fancy here; just compare if vnodes are identical ones */
1700 struct vnode *vp1, *vp2;
1702 AFS_STATCNT(afs_cmp);
1703 return (vp1 == vp2);
1708 afs_realvp(struct vnode *vp, struct vnode **vpp)
1710 AFS_STATCNT(afs_realvp);
1716 afs_pageio(vp, pp, ui1, ui2, i1, credp)
1723 afs_warn("afs_pageio: Not implemented\n");
1729 #ifdef AFS_SUN59_ENV
1735 #ifdef AFS_SUN59_ENV
1739 afs_warn("afs_dumpctl: Not implemented\n");
1743 #ifdef AFS_SUN54_ENV
1745 afs_dispose(vp, p, fl, dn, cr)
1751 fs_dispose(vp, p, fl, dn, cr);
1755 afs_setsecattr(vp, vsecattr, flag, creds)
1757 vsecattr_t *vsecattr;
1765 afs_getsecattr(vp, vsecattr, flag, creds)
1767 vsecattr_t *vsecattr;
1771 return fs_fab_acl(vp, vsecattr, flag, creds);
1775 #ifdef AFS_GLOBAL_SUNLOCK
1776 extern int gafs_open(), gafs_close(), afs_ioctl(), gafs_access();
1777 extern int gafs_getattr(), gafs_setattr(), gafs_lookup(), gafs_create();
1778 extern int gafs_remove(), gafs_link(), gafs_rename(), gafs_mkdir();
1779 extern int gafs_rmdir(), gafs_readdir(), gafs_fsync(), gafs_symlink();
1780 extern int gafs_fid(), gafs_readlink(), fs_setfl(), afs_pathconf();
1781 extern int afs_lockctl();
1782 extern void gafs_inactive();
1784 #ifdef AFS_SUN510_ENV
1785 struct fs_operation_def afs_vnodeops_template[] = {
1786 { VOPNAME_OPEN, gafs_open },
1787 { VOPNAME_CLOSE, gafs_close },
1788 { VOPNAME_READ, afs_vmread },
1789 { VOPNAME_WRITE, afs_vmwrite },
1790 { VOPNAME_IOCTL, afs_ioctl },
1791 { VOPNAME_SETFL, fs_setfl },
1792 { VOPNAME_GETATTR, gafs_getattr },
1793 { VOPNAME_SETATTR, gafs_setattr },
1794 { VOPNAME_ACCESS, gafs_access },
1795 { VOPNAME_LOOKUP, gafs_lookup },
1796 { VOPNAME_CREATE, gafs_create },
1797 { VOPNAME_REMOVE, gafs_remove },
1798 { VOPNAME_LINK, gafs_link },
1799 { VOPNAME_RENAME, gafs_rename },
1800 { VOPNAME_MKDIR, gafs_mkdir },
1801 { VOPNAME_RMDIR, gafs_rmdir },
1802 { VOPNAME_READDIR, gafs_readdir },
1803 { VOPNAME_SYMLINK, gafs_symlink },
1804 { VOPNAME_READLINK, gafs_readlink },
1805 { VOPNAME_FSYNC, gafs_fsync },
1806 { VOPNAME_INACTIVE, gafs_inactive },
1807 { VOPNAME_FID, gafs_fid },
1808 { VOPNAME_RWLOCK, afs_rwlock },
1809 { VOPNAME_RWUNLOCK, afs_rwunlock },
1810 { VOPNAME_SEEK, afs_seek },
1811 { VOPNAME_CMP, afs_cmp },
1812 { VOPNAME_FRLOCK, afs_frlock },
1813 { VOPNAME_SPACE, afs_space },
1814 { VOPNAME_REALVP, afs_realvp },
1815 { VOPNAME_GETPAGE, afs_getpage },
1816 { VOPNAME_PUTPAGE, afs_putpage },
1817 { VOPNAME_MAP, afs_map },
1818 { VOPNAME_ADDMAP, afs_addmap },
1819 { VOPNAME_DELMAP, afs_delmap },
1820 { VOPNAME_POLL, fs_poll },
1821 { VOPNAME_DUMP, afs_dump },
1822 { VOPNAME_PATHCONF, afs_pathconf },
1823 { VOPNAME_PAGEIO, afs_pageio },
1824 { VOPNAME_DUMPCTL, afs_dumpctl },
1825 { VOPNAME_DISPOSE, afs_dispose },
1826 { VOPNAME_GETSECATTR, afs_getsecattr },
1827 { VOPNAME_SETSECATTR, afs_setsecattr },
1828 { VOPNAME_SHRLOCK, fs_shrlock },
1831 struct vnodeops *afs_ops;
1833 struct vnodeops Afs_vnodeops = {
1873 #ifdef AFS_SUN54_ENV
1878 #if defined(AFS_SUN56_ENV)
1882 struct vnodeops *afs_ops = &Afs_vnodeops;
1887 gafs_open(avcp, aflags, acred)
1888 register struct vcache **avcp;
1890 struct AFS_UCRED *acred;
1895 code = afs_open(avcp, aflags, acred);
1901 gafs_close(avc, aflags, count, offset, acred)
1904 register struct vcache *avc;
1906 struct AFS_UCRED *acred;
1911 code = afs_close(avc, aflags, count, offset, acred);
1917 gafs_getattr(avc, attrs, flags, acred)
1919 register struct vcache *avc;
1920 register struct vattr *attrs;
1921 struct AFS_UCRED *acred;
1926 code = afs_getattr(avc, attrs, flags, acred);
1932 gafs_setattr(avc, attrs, flags, acred)
1934 register struct vcache *avc;
1935 register struct vattr *attrs;
1936 struct AFS_UCRED *acred;
1941 code = afs_setattr(avc, attrs, flags, acred);
1947 gafs_access(avc, amode, flags, acred)
1949 register struct vcache *avc;
1950 register afs_int32 amode;
1951 struct AFS_UCRED *acred;
1956 code = afs_access(avc, amode, flags, acred);
1962 gafs_lookup(adp, aname, avcp, pnp, flags, rdir, acred)
1963 struct pathname *pnp;
1966 register struct vcache *adp, **avcp;
1968 struct AFS_UCRED *acred;
1973 code = afs_lookup(adp, aname, avcp, pnp, flags, rdir, acred);
1979 gafs_create(adp, aname, attrs, aexcl, amode, avcp, acred)
1980 register struct vcache *adp;
1982 struct vattr *attrs;
1985 struct vcache **avcp;
1986 struct AFS_UCRED *acred;
1991 code = afs_create(adp, aname, attrs, aexcl, amode, avcp, acred);
1996 gafs_remove(adp, aname, acred)
1997 register struct vcache *adp;
1999 struct AFS_UCRED *acred;
2004 code = afs_remove(adp, aname, acred);
2009 gafs_link(adp, avc, aname, acred)
2010 register struct vcache *avc;
2011 register struct vcache *adp;
2013 struct AFS_UCRED *acred;
2018 code = afs_link(adp, avc, aname, acred);
2023 gafs_rename(aodp, aname1, andp, aname2, acred)
2024 register struct vcache *aodp, *andp;
2025 char *aname1, *aname2;
2026 struct AFS_UCRED *acred;
2031 code = afs_rename(aodp, aname1, andp, aname2, acred);
2036 gafs_mkdir(adp, aname, attrs, avcp, acred)
2037 register struct vcache *adp;
2038 register struct vcache **avcp;
2040 struct vattr *attrs;
2041 struct AFS_UCRED *acred;
2046 code = afs_mkdir(adp, aname, attrs, avcp, acred);
2052 gafs_rmdir(adp, aname, cdirp, acred)
2053 struct vnode *cdirp;
2054 register struct vcache *adp;
2056 struct AFS_UCRED *acred;
2061 code = afs_rmdir(adp, aname, cdirp, acred);
2067 gafs_readdir(avc, auio, acred, eofp)
2069 register struct vcache *avc;
2071 struct AFS_UCRED *acred;
2076 code = afs_readdir(avc, auio, acred, eofp);
2081 gafs_symlink(adp, aname, attrs, atargetName, acred)
2082 register struct vcache *adp;
2083 register char *atargetName;
2085 struct vattr *attrs;
2086 struct AFS_UCRED *acred;
2091 code = afs_symlink(adp, aname, attrs, atargetName, acred);
2097 gafs_readlink(avc, auio, acred)
2098 register struct vcache *avc;
2100 struct AFS_UCRED *acred;
2105 code = afs_readlink(avc, auio, acred);
2110 #ifdef AFS_SUN53_ENV
2111 gafs_fsync(avc, flag, acred)
2114 gafs_fsync(avc, acred)
2116 register struct vcache *avc;
2117 struct AFS_UCRED *acred;
2122 #ifdef AFS_SUN53_ENV
2123 code = afs_fsync(avc, flag, acred);
2125 code = afs_fsync(avc, acred);
2132 afs_inactive(struct vcache *avc, struct AFS_UCRED *acred)
2134 struct vnode *vp = AFSTOV(avc);
2135 if (afs_shuttingdown)
2139 * In Solaris and HPUX s800 and HP-UX10.0 they actually call us with
2140 * v_count 1 on last reference!
2142 mutex_enter(&vp->v_lock);
2143 if (avc->vrefCount <= 0)
2144 osi_Panic("afs_inactive : v_count <=0\n");
2147 * If more than 1 don't unmap the vnode but do decrement the ref count
2150 if (vp->v_count > 0) {
2151 mutex_exit(&vp->v_lock);
2154 mutex_exit(&vp->v_lock);
2157 * Solaris calls VOP_OPEN on exec, but doesn't call VOP_CLOSE when
2158 * the executable exits. So we clean up the open count here.
2160 * Only do this for mvstat 0 vnodes: when using fakestat, we can't
2161 * lose the open count for volume roots (mvstat 2), even though they
2162 * will get VOP_INACTIVE'd when released by afs_PutFakeStat().
2164 if (avc->opens > 0 && avc->mvstat == 0 && !(avc->states & CCore))
2165 avc->opens = avc->execsOrWriters = 0;
2167 afs_InactiveVCache(avc, acred);
2171 gafs_inactive(avc, acred)
2172 register struct vcache *avc;
2173 struct AFS_UCRED *acred;
2176 afs_inactive(avc, acred);
2181 gafs_fid(avc, fidpp)
2188 code = afs_fid(avc, fidpp);
2193 #endif /* AFS_GLOBAL_SUNLOCK */