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 extern struct as kas; /* kernel addr space */
85 extern unsigned char *afs_indexFlags;
86 extern afs_lock_t afs_xdcache;
88 /* Additional vnodeops for SunOS 4.0.x */
89 int afs_nfsrdwr(), afs_getpage(), afs_putpage(), afs_map();
90 int afs_dump(), afs_cmp(), afs_realvp(), afs_GetOnePage();
96 int afs_addmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
97 register struct vnode *avp;
101 int length, prot, maxprot, flags;
102 struct AFS_UCRED *credp;
104 /* XXX What should we do here?? XXX */
108 int afs_delmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
109 register struct vnode *avp;
113 int length, prot, maxprot, flags;
114 struct AFS_UCRED *credp;
116 /* XXX What should we do here?? XXX */
120 int afs_vmread(avp, auio, ioflag, acred)
121 register struct vnode *avp;
124 struct AFS_UCRED *acred;
128 if (!RW_READ_HELD(&(VTOAFS(avp))->rwlock))
129 osi_Panic("afs_vmread: !rwlock");
131 code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_READ, ioflag, acred);
137 int afs_vmwrite(avp, auio, ioflag, acred)
138 register struct vnode *avp;
141 struct AFS_UCRED *acred;
145 if (!RW_WRITE_HELD(&(VTOAFS(avp))->rwlock))
146 osi_Panic("afs_vmwrite: !rwlock");
148 code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_WRITE, ioflag, acred);
153 #endif /* AFS_SUN5_ENV */
155 int afs_getpage(vp, off, len, protp, pl, plsz, seg, addr, rw, acred)
170 struct AFS_UCRED *acred;
172 register afs_int32 code = 0;
173 AFS_STATCNT(afs_getpage);
176 if (vp->v_flag & VNOMAP) /* File doesn't allow mapping */
182 #if defined(AFS_SUN56_ENV)
184 code = afs_GetOnePage(vp, off, len, protp, pl, plsz,
185 seg, addr, rw, acred);
189 code = afs_GetOnePage(vp, (u_int)off, len, protp, pl, plsz,
190 seg, addr, rw, acred);
193 code = afs_GetOnePage(vp, off, protp, pl, plsz,
194 seg, addr, rw, acred);
198 struct vcache *vcp = VTOAFS(vp);
200 ObtainWriteLock(&vcp->vlock, 548);
202 ReleaseWriteLock(&vcp->vlock);
204 afs_BozonLock(&vcp->pvnLock, vcp);
205 #if defined(AFS_SUN56_ENV)
206 code = pvn_getpages(afs_GetOnePage, vp, off,
207 len, protp, pl, plsz, seg, addr, rw, acred);
209 code = pvn_getpages(afs_GetOnePage, vp, (u_int)off,
210 len, protp, pl, plsz, seg, addr, rw, acred);
212 afs_BozonUnlock(&vcp->pvnLock, vcp);
214 ObtainWriteLock(&vcp->vlock, 549);
216 ReleaseWriteLock(&vcp->vlock);
223 /* Return all the pages from [off..off+len) in file */
225 int afs_GetOnePage(vp, off, alen, protp, pl, plsz, seg, addr, rw, acred)
228 int afs_GetOnePage(vp, off, protp, pl, plsz, seg, addr, rw, acred)
231 #if defined(AFS_SUN56_ENV)
246 struct AFS_UCRED *acred;
248 register struct page *page;
249 register afs_int32 code = 0;
253 register struct vcache *avc;
254 register struct dcache *tdc;
257 afs_size_t offset, nlen;
258 struct vrequest treq;
259 afs_int32 mapForRead = 0, Code=0;
260 #if defined(AFS_SUN56_ENV)
268 osi_Panic("GetOnePage: !acred");
270 acred = u.u_cred; /* better than nothing */
273 avc = VTOAFS(vp); /* cast to afs vnode */
276 if (avc->credp /*&& AFS_NFSXLATORREQ(acred)*/ && AFS_NFSXLATORREQ(avc->credp)) {
280 if (code = afs_InitReq(&treq, acred)) return code;
283 /* This is a read-ahead request, e.g. due to madvise. */
289 ObtainReadLock(&avc->lock);
291 while (plen > 0 && !afs_BBusy()) {
292 /* Obtain a dcache entry at off. 2 means don't fetch data. */
293 tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 2);
296 /* Write-lock the dcache entry, if we don't succeed, just go on */
297 if (0 != NBObtainWriteLock(&tdc->lock, 642)) {
302 /* If we aren't already fetching this dcache entry, queue it */
303 if (!(tdc->mflags & DFFetchReq)) {
306 tdc->mflags |= DFFetchReq;
307 bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
308 (afs_size_t) off, (afs_size_t) 1, tdc);
310 /* Unable to start background fetch; might as well stop */
311 tdc->mflags &= ~DFFetchReq;
312 ReleaseWriteLock(&tdc->lock);
316 ReleaseWriteLock(&tdc->lock);
318 ReleaseWriteLock(&tdc->lock);
323 /* Adjust our offset and remaining length values */
327 /* If we aren't making progress for some reason, bail out */
328 if (nlen <= 0) break;
331 ReleaseReadLock(&avc->lock);
336 pl[0] = NULL; /* Make sure it's empty */
338 /* first, obtain the proper lock for the VM system */
340 /* if this is a read request, map the page in read-only. This will
341 * allow us to swap out the dcache entry if there are only read-only
342 * pages created for the chunk, which helps a *lot* when dealing
343 * with small caches. Otherwise, we have to invalidate the vm
344 * pages for the range covered by a chunk when we swap out the
347 if (rw == S_READ || rw == S_EXEC)
350 if (protp) *protp = PROT_ALL;
352 if (AFS_NFSXLATORREQ(acred)) {
354 if (!afs_AccessOK(avc, PRSFS_READ, &treq,
355 CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ)) {
364 if (rw == S_WRITE || rw == S_CREATE)
365 tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 5);
367 tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 1);
368 if (!tdc) return EINVAL;
370 code = afs_VerifyVCache(avc, &treq);
375 return afs_CheckCode(code, &treq, 44); /* failed to get it */
378 afs_BozonLock(&avc->pvnLock, avc);
379 ObtainReadLock(&avc->lock);
381 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, (afs_int32) vp,
382 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
384 ICL_TYPE_LONG, (int) rw);
390 /* Check to see if we're in the middle of a VM purge, and if we are, release
391 * the locks and try again when the VM purge is done. */
392 ObtainWriteLock(&avc->vlock, 550);
394 ReleaseReadLock(&avc->lock);
395 ReleaseWriteLock(&avc->vlock);
396 afs_BozonUnlock(&avc->pvnLock, avc);
398 /* Check activeV again, it may have been turned off
399 * while we were waiting for a lock in afs_PutDCache */
400 ObtainWriteLock(&avc->vlock, 574);
402 avc->vstates |= VRevokeWait;
403 ReleaseWriteLock(&avc->vlock);
404 afs_osi_Sleep(&avc->vstates);
406 ReleaseWriteLock(&avc->vlock);
410 ReleaseWriteLock(&avc->vlock);
413 /* We're about to do stuff with our dcache entry.. Lock it. */
414 ObtainReadLock(&tdc->lock);
416 /* Check to see whether the cache entry is still valid */
417 if (!(avc->states & CStatd)
418 || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
419 ReleaseReadLock(&tdc->lock);
420 ReleaseReadLock(&avc->lock);
421 afs_BozonUnlock(&avc->pvnLock, avc);
427 while (1) { /* loop over all pages */
428 /* now, try to find the page in memory (it may already be intransit or laying
429 around the free list */
430 page = page_lookup( vp, toffset, (rw == S_CREATE ? SE_EXCL : SE_SHARED) );
434 /* if we make it here, we can't find the page in memory. Do a real disk read
435 from the cache to get the data */
436 Code |= 0x200; /* XXX */
438 #if defined(AFS_SUN54_ENV)
439 /* use PG_EXCL because we know the page does not exist already. If it
440 * actually does exist, we have somehow raced between lookup and create.
441 * As of 4/98, that shouldn't be possible, but we'll be defensive here
442 * in case someone tries to relax all the serialization of read and write
443 * operations with harmless things like stat. */
444 #if defined(AFS_SUN58_ENV)
445 page = page_create_va(vp, toffset, PAGESIZE, PG_WAIT|PG_EXCL, seg, addr);
447 page = page_create_va(vp, toffset, PAGESIZE, PG_WAIT|PG_EXCL, seg->s_as, addr);
450 page = page_create(vp, toffset, PAGESIZE, PG_WAIT);
456 pagezero(page, alen, PAGESIZE-alen);
458 page = rm_allocpage(seg, addr, PAGESIZE, 1); /* can't fail */
459 if (!page) osi_Panic("afs_getpage alloc page");
460 /* we get a circularly-linked list of pages back, but we expect only
461 one, since that's what we asked for */
462 if (page->p_next != page) osi_Panic("afs_getpage list");
463 /* page enter returns a locked page; we'll drop the lock as a side-effect
464 of the pvn_done done by afs_ustrategy. If we decide not to call
465 strategy, we must be sure to call pvn_fail, at least, to release the
466 page locks and otherwise reset the pages. The page, while locked, is
467 not held, for what it is worth */
468 page->p_intrans = 1; /* set appropriate flags */
470 /* next call shouldn't fail, since we have pvnLock set */
471 if (page_enter(page, vp, toffset)) osi_Panic("afs_getpage enter race");
472 #endif /* AFS_SUN5_ENV */
475 if (rw == S_CREATE) {
476 /* XXX Don't read from AFS in write only cases XXX */
477 page_io_unlock(page);
481 /* XXX Don't read from AFS in write only cases XXX */
482 page->p_intrans = page->p_pagein = 0;
483 page_unlock(page); /* XXX */
490 /* now it is time to start I/O operation */
491 buf = pageio_setup(page, PAGESIZE, vp, B_READ); /* allocate a buf structure */
492 #if defined(AFS_SUN5_ENV)
496 buf->b_blkno = btodb(toffset);
497 bp_mapin(buf); /* map it in to our address space */
499 #if defined(AFS_SUN5_ENV)
501 /* afs_ustrategy will want to lock the dcache entry */
502 ReleaseReadLock(&tdc->lock);
503 code = afs_ustrategy(buf, acred); /* do the I/O */
504 ObtainReadLock(&tdc->lock);
507 ReleaseReadLock(&tdc->lock);
508 ReleaseReadLock(&avc->lock);
509 code = afs_ustrategy(buf); /* do the I/O */
510 ObtainReadLock(&avc->lock);
511 ObtainReadLock(&tdc->lock);
515 /* Before freeing unmap the buffer */
526 page_io_unlock(page);
530 /* come here when we have another page (already held) to enter */
532 /* put page in array and continue */
534 /* The p_selock must be downgraded to a shared lock after the page is read */
535 #if defined(AFS_SUN56_ENV)
536 if ((rw != S_CREATE) && !(PAGE_SHARED(page)))
538 if ((rw != S_CREATE) && !(se_shared_assert(&page->p_selock)))
541 page_downgrade(page);
546 code = page_iolock_assert(page);
552 if (tlen <= 0) break; /* done all the pages */
553 } /* while (1) ... */
556 pl[slot] = (struct page *) 0;
557 ReleaseReadLock(&tdc->lock);
559 /* Prefetch next chunk if we're at a chunk boundary */
560 if (AFS_CHUNKOFFSET(off) == 0) {
561 if (!(tdc->mflags & DFNextStarted))
562 afs_PrefetchChunk(avc, tdc, acred, &treq);
565 ReleaseReadLock(&avc->lock);
567 ObtainWriteLock(&afs_xdcache,246);
569 /* track that we have dirty (or dirty-able) pages for this chunk. */
570 afs_indexFlags[tdc->index] |= IFDirtyPages;
572 afs_indexFlags[tdc->index] |= IFAnyPages;
573 ReleaseWriteLock(&afs_xdcache);
575 afs_BozonUnlock(&avc->pvnLock, avc);
579 afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, (int)page,
580 ICL_TYPE_LONG, Code);
585 afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, (int)page,
586 ICL_TYPE_LONG, Code);
587 /* release all pages, drop locks, return code */
590 pvn_read_done(page, B_ERROR);
592 for(i=0; i<slot; i++)
595 ReleaseReadLock(&avc->lock);
596 afs_BozonUnlock(&avc->pvnLock, avc);
598 ReleaseReadLock(&tdc->lock);
605 int afs_putpage(vp, off, len, flags, cred)
610 struct AFS_UCRED *cred;
615 #if defined(AFS_SUN58_ENV)
622 #if defined(AFS_SUN56_ENV)
623 u_offset_t toff = off;
629 AFS_STATCNT(afs_putpage);
630 if (vp->v_flag & VNOMAP) /* file doesn't allow mapping */
634 * Putpage (ASYNC) is called every sec to flush out dirty vm pages
637 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER, (afs_int32) vp,
638 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
639 ICL_TYPE_INT32, (afs_int32) len,
640 ICL_TYPE_LONG, (int) flags);
642 afs_BozonLock(&avc->pvnLock, avc);
643 ObtainSharedLock(&avc->lock,247);
646 /* Get a list of modified (or whatever) pages */
648 endPos = (afs_offs_t)off + len; /* position we're supposed to write up to */
649 while ((afs_offs_t)toff < endPos && (afs_offs_t)toff < avc->m.Length) {
650 /* If not invalidating pages use page_lookup_nowait to avoid reclaiming
651 * them from the free list
654 if (flags & (B_FREE|B_INVAL))
655 pages = page_lookup(vp, toff, SE_EXCL);
657 pages = page_lookup_nowait(vp, toff, SE_SHARED);
658 if (!pages || !pvn_getdirty(pages, flags))
664 UpgradeSToWLock(&avc->lock, 671);
668 code = afs_putapage(vp, pages, &toff, &tlen, flags, cred);
679 UpgradeSToWLock(&avc->lock, 670);
684 #if defined(AFS_SUN56_ENV)
685 code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
687 code = pvn_vplist_dirty(vp, (u_int)off, afs_putapage, flags, cred);
692 if (code && !avc->vc_error) {
694 UpgradeSToWLock(&avc->lock, 669);
697 avc->vc_error = code;
701 ReleaseWriteLock(&avc->lock);
703 ReleaseSharedLock(&avc->lock);
704 afs_BozonUnlock(&avc->pvnLock, avc);
705 afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, NPages);
711 int afs_putapage(struct vnode *vp, struct page *pages,
712 #if defined(AFS_SUN56_ENV)
717 #if defined(AFS_SUN58_ENV)
722 int flags, struct AFS_UCRED *credp)
725 struct vcache *avc = VTOAFS(vp);
727 u_int tlen = PAGESIZE;
728 afs_offs_t off = (pages->p_offset/PAGESIZE)*PAGESIZE;
731 * Now we've got the modified pages. All pages are locked and held
732 * XXX Find a kluster that fits in one block (or page). We also
733 * adjust the i/o if the file space is less than a while page. XXX
735 if (off + tlen > avc->m.Length) {
736 tlen = avc->m.Length - off;
738 /* can't call mapout with 0 length buffers (rmfree panics) */
739 if (((tlen>>24)&0xff) == 0xff) {
744 * Can't call mapout with 0 length buffers since we'll get rmfree panics
746 tbuf = pageio_setup(pages, tlen, vp, B_WRITE | flags);
747 if (!tbuf) return (ENOMEM);
750 tbuf->b_blkno = btodb(pages->p_offset);
753 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUTONE, ICL_TYPE_LONG, avc,
754 ICL_TYPE_LONG, pages,
756 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off));
757 code = afs_ustrategy(tbuf, credp); /* unlocks page */
761 pvn_write_done(pages, ((code) ? B_ERROR:0) | B_WRITE | flags);
764 if (offp) *offp = off;
765 if (lenp) *lenp = tlen;
771 int afs_putpage(vp, off, len, flags, cred)
776 struct AFS_UCRED *cred;
778 int wholeEnchilada; /* true if we must get all of the pages */
784 afs_int32 code = 0, rcode;
786 afs_int32 clusterStart, clusterEnd, endPos;
788 /* In the wholeEnchilada case, we must ensure that we get all of the pages
789 from the system, since we're doing this to shutdown the use of a vnode */
791 AFS_STATCNT(afs_putpage);
792 wholeEnchilada = (off == 0 && len == 0 && (flags & (B_INVAL|B_ASYNC)) == B_INVAL);
795 afs_BozonLock(&avc->pvnLock, avc);
796 ObtainWriteLock(&avc->lock,248);
799 /* in whole enchilada case, loop until call to pvn_getdirty can't find
800 any more modified pages */
802 /* first we try to get a list of modified (or whatever) pages */
804 pages = pvn_vplist_dirty(vp, off, flags);
807 endPos = off + len; /* position we're supposed to write up to */
808 if (endPos > avc->m.Length) endPos = avc->m.Length; /* bound by this */
809 clusterStart = off & ~(PAGESIZE-1); /* round down to nearest page */
810 clusterEnd = ((endPos-1) | (PAGESIZE-1))+1; /* round up to nearest page */
811 pages = pvn_range_dirty(vp, off, endPos, clusterStart, clusterEnd, flags);
814 /* Now we've got the modified pages. All pages are locked and held */
815 rcode = 0; /* return code */
816 while(pages) { /* look over all pages in the returned set */
817 tpage = pages; /* get first page in the list */
819 /* write out the page */
820 poffset = tpage->p_offset; /* where the page starts in the file */
821 /* tlen will represent the end of the range to write, for a while */
822 tlen = PAGESIZE+poffset; /* basic place to end tpage write */
823 /* but we also don't want to write past end of off..off+len range */
824 if (len != 0 && tlen > off+len) tlen = off+len;
825 /* and we don't want to write past the end of the file */
826 if (tlen > avc->m.Length) tlen = avc->m.Length;
827 /* and we don't want to write at all if page starts after end */
828 if (poffset >= tlen) {
829 pvn_fail(pages, B_WRITE | flags);
832 /* finally change tlen from end position to length */
833 tlen -= poffset; /* compute bytes to write from this page */
834 page_sub(&pages, tpage); /* remove tpage from "pages" list */
835 tbuf = pageio_setup(tpage, tlen, vp, B_WRITE | flags);
837 pvn_fail(tpage, B_WRITE|flags);
838 pvn_fail(pages, B_WRITE|flags);
842 tbuf->b_blkno = btodb(tpage->p_offset);
844 ReleaseWriteLock(&avc->lock); /* can't hold during strategy call */
845 code = afs_ustrategy(tbuf); /* unlocks page */
846 ObtainWriteLock(&avc->lock,249); /* re-obtain */
848 /* unlocking of tpage is done by afs_ustrategy */
850 if (pages) /* may have already removed last page */
851 pvn_fail(pages, B_WRITE|flags);
854 } /* for (tpage=pages....) */
856 /* see if we've gotten all of the pages in the whole enchilada case */
857 if (!wholeEnchilada || !vp->v_pages) break;
858 } /* while(1) obtaining all pages */
861 * If low on chunks, and if writing the last byte of a chunk, try to
862 * free some. Note that afs_DoPartialWrite calls osi_SyncVM which now
863 * calls afs_putpage, so this is recursion. It stops there because we
864 * insist on len being non-zero.
866 if (afs_stats_cmperf.cacheCurrDirtyChunks > afs_stats_cmperf.cacheMaxDirtyChunks
867 && len != 0 && AFS_CHUNKOFFSET((off + len)) == 0) {
868 struct vrequest treq;
869 if (!afs_InitReq(&treq, cred ? cred : u.u_cred)) {
870 rcode = afs_DoPartialWrite(avc, &treq); /* XXX */
876 if (rcode && !avc->vc_error)
877 avc->vc_error = rcode;
879 /* when we're here, we just return code. */
880 ReleaseWriteLock(&avc->lock);
881 afs_BozonUnlock(&avc->pvnLock, avc);
885 #endif /* AFS_SUN5_ENV */
887 int afs_nfsrdwr(avc, auio, arw, ioflag, acred)
888 register struct vcache *avc;
892 struct AFS_UCRED *acred;
894 register afs_int32 code;
897 afs_int32 mode, sflags;
899 struct dcache *dcp, *dcp_newpage;
900 afs_size_t fileBase, size;
902 register afs_int32 tsize;
903 register afs_int32 pageOffset, extraResid=0;
904 register afs_size_t origLength; /* length when reading/writing started */
905 register long appendLength; /* length when this call will finish */
906 int created; /* created pages instead of faulting them */
908 int didFakeOpen, eof;
909 struct vrequest treq;
913 AFS_STATCNT(afs_nfsrdwr);
915 /* can't read or write other things */
916 if (vType(avc) != VREG) return EISDIR;
918 if (auio->uio_resid == 0)
921 afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, (afs_int32)avc,
922 ICL_TYPE_LONG, (arw==UIO_WRITE? 1 : 0),
923 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->uio_offset),
924 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->uio_resid));
926 #ifndef AFS_64BIT_CLIENT
927 if ( AfsLargeFileUio(auio) ) /* file is larger than 2 GB */
932 if (!acred) osi_Panic("rdwr: !acred");
934 if (!acred) acred = u.u_cred;
936 if (code = afs_InitReq(&treq, acred)) return code;
938 /* It's not really possible to know if a write cause a growth in the
939 * cache size, we we wait for a cache drain for any write.
941 afs_MaybeWakeupTruncateDaemon();
942 while ((arw == UIO_WRITE) &&
943 (afs_blocksUsed > (CM_WAITFORDRAINPCT*afs_cacheBlocks)/100)) {
944 if (afs_blocksUsed - afs_blocksDiscarded >
945 (CM_WAITFORDRAINPCT*afs_cacheBlocks)/100) {
946 afs_WaitForCacheDrain = 1;
947 afs_osi_Sleep(&afs_WaitForCacheDrain);
949 afs_MaybeFreeDiscardedDCache();
950 afs_MaybeWakeupTruncateDaemon();
952 code = afs_VerifyVCache(avc, &treq);
953 if (code) return afs_CheckCode(code, &treq, 45);
955 afs_BozonLock(&avc->pvnLock, avc);
956 osi_FlushPages(avc, acred); /* hold bozon lock, but not basic vnode lock */
958 ObtainWriteLock(&avc->lock,250);
960 /* adjust parameters when appending files */
961 if ((ioflag & IO_APPEND) && arw == UIO_WRITE)
963 #if defined(AFS_SUN56_ENV)
964 auio->uio_loffset = 0;
966 auio->uio_offset = avc->m.Length; /* write at EOF position */
968 if (auio->uio_offset < 0 || (auio->uio_offset + auio->uio_resid) < 0) {
969 ReleaseWriteLock(&avc->lock);
970 afs_BozonUnlock(&avc->pvnLock, avc);
974 #ifndef AFS_64BIT_CLIENT
975 /* file is larger than 2GB */
976 if ( AfsLargeFileSize(auio->uio_offset, auio->uio_resid) ) {
977 ReleaseWriteLock(&avc->lock);
978 afs_BozonUnlock(&avc->pvnLock, avc);
983 didFakeOpen=0; /* keep track of open so we can do close */
984 if (arw == UIO_WRITE) {
985 /* do ulimit processing; shrink resid or fail */
986 #if defined(AFS_SUN56_ENV)
987 if (auio->uio_loffset + auio->afsio_resid > auio->uio_llimit) {
988 if (auio->uio_llimit >= auio->uio_llimit) {
989 ReleaseWriteLock(&avc->lock);
990 afs_BozonUnlock(&avc->pvnLock, avc);
993 /* track # of bytes we should write, but won't because of
994 * ulimit; we must add this into the final resid value
995 * so caller knows we punted some data.
997 extraResid = auio->uio_resid;
998 auio->uio_resid = auio->uio_llimit - auio->uio_loffset;
999 extraResid -= auio->uio_resid;
1003 #ifdef AFS_SUN52_ENV
1004 if (auio->afsio_offset + auio->afsio_resid > auio->uio_limit) {
1005 if (auio->afsio_offset >= auio->uio_limit) {
1006 ReleaseWriteLock(&avc->lock);
1007 afs_BozonUnlock(&avc->pvnLock, avc);
1010 /* track # of bytes we should write, but won't because of
1011 * ulimit; we must add this into the final resid value
1012 * so caller knows we punted some data.
1014 extraResid = auio->uio_resid;
1015 auio->uio_resid = auio->uio_limit - auio->afsio_offset;
1016 extraResid -= auio->uio_resid;
1021 mode = S_WRITE; /* segment map-in mode */
1022 afs_FakeOpen(avc); /* do this for writes, so data gets put back
1023 when we want it to be put back */
1024 didFakeOpen = 1; /* we'll be doing a fake open */
1025 /* before starting any I/O, we must ensure that the file is big enough
1026 to hold the results (since afs_putpage will be called to force the I/O */
1027 size = auio->afsio_resid + auio->afsio_offset; /* new file size */
1028 appendLength = size;
1029 origLength = avc->m.Length;
1030 if (size > avc->m.Length) {
1031 afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH,
1032 ICL_TYPE_STRING, __FILE__,
1033 ICL_TYPE_LONG, __LINE__,
1034 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length),
1035 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(size));
1036 avc->m.Length = size; /* file grew */
1038 avc->states |= CDirty; /* Set the dirty bit */
1039 avc->m.Date = osi_Time(); /* Set file date (for ranlib) */
1041 mode = S_READ; /* map-in read-only */
1042 origLength = avc->m.Length;
1045 if (acred && AFS_NFSXLATORREQ(acred)) {
1046 if (arw == UIO_READ) {
1047 if (!afs_AccessOK(avc, PRSFS_READ, &treq,
1048 CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ)) {
1049 ReleaseWriteLock(&avc->lock);
1050 afs_BozonUnlock(&avc->pvnLock, avc);
1062 counter = 0; /* don't call afs_DoPartialWrite first time through. */
1064 /* compute the amount of data to move into this block,
1065 based on auio->afsio_resid. Note that we copy data in units of
1066 MAXBSIZE, not PAGESIZE. This is because segmap_getmap panics if you
1067 call it with an offset based on blocks smaller than MAXBSIZE
1068 (implying that it should be named BSIZE, since it is clearly both a
1070 size = auio->afsio_resid; /* transfer size */
1071 fileBase = auio->afsio_offset; /* start file position for xfr */
1072 pageBase = fileBase & ~(MAXBSIZE-1); /* file position of the page */
1073 pageOffset = fileBase & (MAXBSIZE-1); /* xfr start's offset within page */
1074 tsize = MAXBSIZE-pageOffset; /* how much more fits in this page */
1075 /* we'll read tsize bytes, but first must make sure tsize isn't too big */
1076 if (tsize > size) tsize = size; /* don't read past end of request */
1077 eof = 0; /* flag telling us if we hit the EOF on the read */
1078 if (arw == UIO_READ) { /* we're doing a read operation */
1079 /* don't read past EOF */
1080 if (fileBase + tsize > origLength) {
1081 tsize = origLength - fileBase;
1082 eof = 1; /* we did hit the EOF */
1083 if (tsize < 0) tsize = 0; /* better safe than sorry */
1089 /* Purge dirty chunks of file if there are too many dirty
1090 * chunks. Inside the write loop, we only do this at a chunk
1091 * boundary. Clean up partial chunk if necessary at end of loop.
1093 if (counter > 0 && code == 0 && AFS_CHUNKOFFSET(fileBase) == 0)
1095 code = afs_DoPartialWrite(avc, &treq);
1099 #endif /* AFS_SUN5_ENV */
1100 /* write case, we ask segmap_release to call putpage. Really, we
1101 don't have to do this on every page mapin, but for now we're
1102 lazy, and don't modify the rest of AFS to scan for modified
1103 pages on a close or other "synchronize with file server"
1104 operation. This makes things a little cleaner, but probably
1105 hurts performance. */
1110 break; /* nothing to transfer, we're done */
1113 if (arw == UIO_WRITE)
1114 avc->states |= CDirty; /* may have been cleared by DoPartialWrite*/
1116 /* Before dropping lock, hold the chunk (create it if necessary). This
1117 * serves two purposes: (1) Ensure Cache Truncate Daemon doesn't try
1118 * to purge the chunk's pages while we have them locked. This would
1119 * cause deadlock because we might be waiting for the CTD to free up
1120 * a chunk. (2) If we're writing past the original EOF, and we're
1121 * at the base of the chunk, then make sure it exists online
1122 * before we do the uiomove, since the segmap_release will
1123 * write out to the chunk, causing it to get fetched if it hasn't
1124 * been created yet. The code that would otherwise notice that
1125 * we're fetching a chunk past EOF won't work, since we've
1126 * already adjusted the file size above.
1128 ObtainWriteLock(&avc->vlock, 551);
1129 while (avc->vstates & VPageCleaning) {
1130 ReleaseWriteLock(&avc->vlock);
1131 ReleaseWriteLock(&avc->lock);
1132 afs_osi_Sleep(&avc->vstates);
1133 ObtainWriteLock(&avc->lock, 334);
1134 ObtainWriteLock(&avc->vlock, 552);
1136 ReleaseWriteLock(&avc->vlock);
1138 afs_size_t toff, tlen;
1139 dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
1146 ReleaseWriteLock(&avc->lock); /* uiomove may page fault */
1148 #if defined(AFS_SUN56_ENV)
1149 data = segmap_getmap(segkmap,AFSTOV(avc),(u_offset_t)pageBase);
1151 data = segmap_getmap(segkmap, AFSTOV(avc), pageBase);
1153 #ifndef AFS_SUN5_ENV
1154 code = as_fault(&kas, data+pageOffset, tsize, F_SOFTLOCK, mode);
1156 AFS_UIOMOVE(data+pageOffset, tsize, arw, auio, code);
1157 as_fault(&kas, data+pageOffset, tsize, F_SOFTUNLOCK, mode);
1158 code2 = segmap_release(segkmap, data, sflags);
1163 (void) segmap_release(segkmap, data, 0);
1166 #if defined(AFS_SUN56_ENV)
1167 raddr = (caddr_t) (((uintptr_t)data +pageOffset) & PAGEMASK);
1169 raddr = (caddr_t) (((u_int)data +pageOffset) & PAGEMASK);
1171 rsize = (((u_int)data+pageOffset+tsize+PAGEOFFSET) & PAGEMASK)-(u_int)raddr;
1173 /* if we're doing a write, and we're starting at the rounded
1174 * down page base, and we're writing enough data to cover all
1175 * created pages, then we must be writing all of the pages
1176 * in this MAXBSIZE window that we're creating.
1179 if (arw == UIO_WRITE
1180 && ((long)raddr == (long)data+pageOffset)
1181 && tsize >= rsize) {
1182 /* probably the dcache backing this guy is around, but if
1183 * not, we can't do this optimization, since we're creating
1184 * writable pages, which must be backed by a chunk.
1187 dcp_newpage = afs_FindDCache(avc, pageBase);
1189 && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)) {
1190 ObtainWriteLock(&avc->lock,251);
1191 ObtainWriteLock(&avc->vlock,576);
1192 ObtainReadLock(&dcp_newpage->lock);
1193 if ((avc->activeV == 0)
1194 && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)
1195 && !(dcp_newpage->dflags & (DFFetching))) {
1197 segmap_pagecreate(segkmap, raddr, rsize, 1);
1199 ObtainWriteLock(&afs_xdcache,252);
1200 /* Mark the pages as created and dirty */
1201 afs_indexFlags[dcp_newpage->index]
1202 |= (IFAnyPages | IFDirtyPages);
1203 ReleaseWriteLock(&afs_xdcache);
1206 ReleaseReadLock(&dcp_newpage->lock);
1207 afs_PutDCache(dcp_newpage);
1208 ReleaseWriteLock(&avc->vlock);
1209 ReleaseWriteLock(&avc->lock);
1211 else if ( dcp_newpage )
1212 afs_PutDCache(dcp_newpage);
1216 code = segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTLOCK, mode);
1219 AFS_UIOMOVE(data+pageOffset, tsize, arw, auio, code);
1220 segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTUNLOCK, mode);
1223 code = segmap_release(segkmap, data, sflags);
1225 (void) segmap_release(segkmap, data, 0);
1227 #endif /* AFS_SUN5_ENV */
1229 ObtainWriteLock(&avc->lock,253);
1234 #endif /* AFS_SUN5_ENV */
1238 afs_FakeClose(avc, acred);
1242 if (arw == UIO_WRITE && (avc->states & CDirty)) {
1243 code2 = afs_DoPartialWrite(avc, &treq);
1247 #endif /* AFS_SUN5_ENV */
1249 if (!code && avc->vc_error) {
1250 code = avc->vc_error;
1252 ReleaseWriteLock(&avc->lock);
1253 afs_BozonUnlock(&avc->pvnLock, avc);
1255 #ifdef AFS_SUN53_ENV
1256 if ((ioflag & FSYNC) && (arw == UIO_WRITE) && !AFS_NFSXLATORREQ(acred))
1257 code = afs_fsync(avc, 0, acred);
1259 if ((ioflag & IO_SYNC) && (arw == UIO_WRITE)
1260 && !AFS_NFSXLATORREQ(acred))
1261 code = afs_fsync(avc, acred);
1264 #ifdef AFS_SUN52_ENV
1266 * If things worked, add in as remaining in request any bytes
1267 * we didn't write due to file size ulimit.
1269 if (code == 0 && extraResid > 0)
1270 auio->uio_resid += extraResid;
1272 return afs_CheckCode(code, &treq, 46);
1275 afs_map(vp, off, as, addr, len, prot, maxprot, flags, cred)
1287 u_char prot, maxprot;
1289 u_int prot, maxprot;
1292 struct AFS_UCRED *cred;
1294 struct segvn_crargs crargs;
1295 register afs_int32 code;
1296 struct vrequest treq;
1297 register struct vcache *avc = VTOAFS(vp);
1299 AFS_STATCNT(afs_map);
1302 /* check for reasonableness on segment bounds; apparently len can be < 0 */
1303 if (off < 0 || off + len < 0) {
1306 #ifndef AFS_64BIT_CLIENT
1307 if ( AfsLargeFileSize(off, len) ) /* file is larger than 2 GB */
1314 #if defined(AFS_SUN5_ENV)
1315 if (vp->v_flag & VNOMAP) /* File isn't allowed to be mapped */
1318 if (vp->v_filocks) /* if locked, disallow mapping */
1322 if (code = afs_InitReq(&treq, cred)) goto out;
1324 if (vp->v_type != VREG) {
1329 code = afs_VerifyVCache(avc, &treq);
1333 afs_BozonLock(&avc->pvnLock, avc);
1334 osi_FlushPages(avc, cred); /* ensure old pages are gone */
1335 avc->states |= CMAPPED; /* flag cleared at afs_inactive */
1336 afs_BozonUnlock(&avc->pvnLock, avc);
1342 if ((flags & MAP_FIXED) == 0) {
1343 #if defined(AFS_SUN57_ENV)
1344 map_addr(addr, len, off, 1, flags);
1345 #elif defined(AFS_SUN56_ENV)
1346 map_addr(addr, len, off, 1);
1348 map_addr(addr, len, (off_t)off, 1);
1350 if (*addr == NULL) {
1358 (void) as_unmap(as, *addr, len); /* unmap old address space use */
1359 /* setup the create parameter block for the call */
1360 crargs.vp = AFSTOV(avc);
1361 crargs.offset = (u_int)off;
1363 crargs.type = flags&MAP_TYPE;
1365 crargs.maxprot = maxprot;
1366 crargs.amp = (struct anon_map *) 0;
1367 #if defined(AFS_SUN5_ENV)
1368 crargs.flags = flags & ~MAP_TYPE;
1371 code = as_map(as, *addr, len, segvn_create, (char *) &crargs);
1377 code = afs_CheckCode(code, &treq, 47);
1381 code = afs_CheckCode(code, &treq, 48);
1386 /* Sun 4.0.X-specific code. It computes the number of bytes that need
1387 to be zeroed at the end of a page by pvn_vptrunc, given that you're
1388 trying to get vptrunc to truncate a file to alen bytes. The result
1389 will be passed to pvn_vptrunc by the truncate code */
1390 #ifndef AFS_SUN5_ENV /* Not good for Solaris */
1392 register afs_int32 alen; {
1393 register afs_int32 nbytes;
1395 AFS_STATCNT(afs_PageLeft);
1396 nbytes = PAGESIZE - (alen & PAGEOFFSET); /* amount to zap in last page */
1397 /* now check if we'd zero the entire last page. Don't need to do this
1398 since pvn_vptrunc will handle this case properly (it will invalidate
1400 if (nbytes == PAGESIZE) nbytes = 0;
1401 if (nbytes < 0) nbytes = 0; /* just in case */
1408 * For Now We use standard local kernel params for AFS system values. Change this
1411 #if defined(AFS_SUN5_ENV)
1412 afs_pathconf(vp, cmd, outdatap, credp)
1413 register struct AFS_UCRED *credp;
1415 afs_cntl(vp, cmd, indatap, outdatap, inflag, outflag)
1416 int inflag, outflag;
1423 AFS_STATCNT(afs_cntl);
1426 *outdatap = MAXLINK;
1429 *outdatap = MAXNAMLEN;
1432 *outdatap = MAXPATHLEN;
1434 case _PC_CHOWN_RESTRICTED:
1440 #if !defined(AFS_SUN5_ENV)
1442 *outdatap = CANBSIZ;
1445 *outdatap = VDISABLE;
1457 #endif /* AFS_SUN_ENV */
1459 #if defined(AFS_SUN5_ENV)
1461 afs_ioctl(vnp, com, arg, flag, credp, rvalp)
1470 void afs_rwlock(vnp, wlock)
1474 rw_enter(&(VTOAFS(vnp))->rwlock, (wlock ? RW_WRITER : RW_READER));
1478 void afs_rwunlock(vnp, wlock)
1482 rw_exit(&(VTOAFS(vnp))->rwlock);
1487 afs_seek(vnp, ooff, noffp)
1492 register int code = 0;
1494 if ((*noffp < 0 || *noffp > MAXOFF_T))
1499 int afs_frlock(vnp, cmd, ap, flag, off,
1500 #ifdef AFS_SUN59_ENV
1506 #if defined(AFS_SUN56_ENV)
1513 #ifdef AFS_SUN59_ENV
1514 struct flk_callback *flkcb;
1516 struct AFS_UCRED *credp;
1518 register afs_int32 code = 0;
1520 * Implement based on afs_lockctl
1523 #ifdef AFS_SUN59_ENV
1525 afs_warn("Don't know how to deal with flk_callback's!\n");
1527 if ((cmd == F_GETLK) || (cmd == F_O_GETLK) || (cmd == F_SETLK) || (cmd == F_SETLKW)) {
1528 #ifdef AFS_SUN53_ENV
1529 ap->l_pid = ttoproc(curthread)->p_pid;
1532 ap->l_pid = ttoproc(curthread)->p_epid;
1533 ap->l_sysid = ttoproc(curthread)->p_sysid;
1537 #ifdef AFS_SUN56_ENV
1538 code = convoff(vnp, ap, 0, off);
1540 code = convoff(vnp, ap, 0, (off_t)off);
1542 if (code) return code;
1546 code = afs_lockctl(VTOAFS(vnp), ap, cmd, credp);
1552 int afs_space(vnp, cmd, ap, flag, off, credp)
1555 #if defined(AFS_SUN56_ENV)
1562 struct AFS_UCRED *credp;
1564 register afs_int32 code = EINVAL;
1567 if ((cmd == F_FREESP)
1568 #ifdef AFS_SUN56_ENV
1569 && ((code = convoff(vnp, ap, 0, off)) == 0)) {
1571 && ((code = convoff(vnp, ap, 0, (off_t)off)) == 0)) {
1575 vattr.va_mask = AT_SIZE;
1576 vattr.va_size = ap->l_start;
1577 code = afs_setattr(VTOAFS(vnp), &vattr, 0, credp);
1587 int afs_dump(vp, addr, i1, i2)
1592 AFS_STATCNT(afs_dump);
1593 afs_warn("AFS_DUMP. MUST IMPLEMENT THIS!!!\n");
1598 /* Nothing fancy here; just compare if vnodes are identical ones */
1600 struct vnode *vp1, *vp2;
1602 AFS_STATCNT(afs_cmp);
1607 int afs_realvp(struct vnode *vp, struct vnode **vpp) {
1608 AFS_STATCNT(afs_realvp);
1613 int afs_pageio(vp, pp, ui1, ui2, i1, credp)
1620 afs_warn("afs_pageio: Not implemented\n");
1624 int afs_dumpctl(vp, i
1625 #ifdef AFS_SUN59_ENV
1631 #ifdef AFS_SUN59_ENV
1635 afs_warn("afs_dumpctl: Not implemented\n");
1639 #ifdef AFS_SUN54_ENV
1640 extern void afs_dispose(vp, p, fl, dn, cr)
1646 fs_dispose(vp, p, fl, dn, cr);
1649 int afs_setsecattr(vp, vsecattr, flag, creds)
1651 vsecattr_t *vsecattr;
1658 int afs_getsecattr(vp, vsecattr, flag, creds)
1660 vsecattr_t *vsecattr;
1664 return fs_fab_acl(vp, vsecattr, flag, creds);
1668 #ifdef AFS_GLOBAL_SUNLOCK
1669 extern int gafs_open(), gafs_close(), afs_ioctl(), gafs_access();
1670 extern int gafs_getattr(), gafs_setattr(), gafs_lookup(), gafs_create();
1671 extern int gafs_remove(), gafs_link(), gafs_rename(), gafs_mkdir();
1672 extern int gafs_rmdir(), gafs_readdir(), gafs_fsync(), gafs_symlink();
1673 extern int gafs_fid(), gafs_readlink(), fs_setfl(), afs_pathconf();
1674 extern int afs_lockctl();
1675 extern void gafs_inactive();
1677 struct vnodeops Afs_vnodeops = {
1717 #ifdef AFS_SUN54_ENV
1722 #if defined(AFS_SUN56_ENV)
1726 struct vnodeops *afs_ops = &Afs_vnodeops;
1730 gafs_open(avcp, aflags, acred)
1731 register struct vcache **avcp;
1733 struct AFS_UCRED *acred;
1738 code = afs_open(avcp, aflags, acred);
1744 gafs_close(avc, aflags, count, offset, acred)
1747 register struct vcache *avc;
1749 struct AFS_UCRED *acred;
1754 code = afs_close(avc, aflags, count, offset, acred);
1760 gafs_getattr(avc, attrs, flags, acred)
1762 register struct vcache *avc;
1763 register struct vattr *attrs;
1764 struct AFS_UCRED *acred;
1769 code = afs_getattr(avc, attrs, flags, acred);
1775 gafs_setattr(avc, attrs, flags, acred)
1777 register struct vcache *avc;
1778 register struct vattr *attrs;
1779 struct AFS_UCRED *acred;
1784 code = afs_setattr(avc, attrs, flags, acred);
1790 gafs_access(avc, amode, flags, acred)
1792 register struct vcache *avc;
1793 register afs_int32 amode;
1794 struct AFS_UCRED *acred;
1799 code = afs_access(avc, amode, flags, acred);
1805 gafs_lookup(adp, aname, avcp, pnp, flags, rdir, acred)
1806 struct pathname *pnp;
1809 register struct vcache *adp, **avcp;
1811 struct AFS_UCRED *acred;
1816 code = afs_lookup(adp, aname, avcp, pnp, flags, rdir, acred);
1822 gafs_create(adp, aname, attrs, aexcl, amode, avcp, acred)
1823 register struct vcache *adp;
1825 struct vattr *attrs;
1828 struct vcache **avcp;
1829 struct AFS_UCRED *acred;
1834 code = afs_create(adp, aname, attrs, aexcl, amode, avcp, acred);
1839 gafs_remove(adp, aname, acred)
1840 register struct vcache *adp;
1842 struct AFS_UCRED *acred;
1847 code = afs_remove(adp, aname, acred);
1852 gafs_link(adp, avc, aname, acred)
1853 register struct vcache *avc;
1854 register struct vcache *adp;
1856 struct AFS_UCRED *acred;
1861 code = afs_link(adp, avc, aname, acred);
1866 gafs_rename(aodp, aname1, andp, aname2, acred)
1867 register struct vcache *aodp, *andp;
1868 char *aname1, *aname2;
1869 struct AFS_UCRED *acred;
1874 code = afs_rename(aodp, aname1, andp, aname2, acred);
1879 gafs_mkdir(adp, aname, attrs, avcp, acred)
1880 register struct vcache *adp;
1881 register struct vcache **avcp;
1883 struct vattr *attrs;
1884 struct AFS_UCRED *acred;
1889 code = afs_mkdir(adp, aname, attrs, avcp, acred);
1895 gafs_rmdir(adp, aname, cdirp, acred)
1896 struct vnode *cdirp;
1897 register struct vcache *adp;
1899 struct AFS_UCRED *acred;
1904 code = afs_rmdir(adp, aname, cdirp, acred);
1910 gafs_readdir(avc, auio, acred, eofp)
1912 register struct vcache *avc;
1914 struct AFS_UCRED *acred;
1919 code = afs_readdir(avc, auio, acred, eofp);
1924 gafs_symlink(adp, aname, attrs, atargetName, acred)
1925 register struct vcache *adp;
1926 register char *atargetName;
1928 struct vattr *attrs;
1929 struct AFS_UCRED *acred;
1934 code = afs_symlink(adp, aname, attrs, atargetName, acred);
1940 gafs_readlink(avc, auio, acred)
1941 register struct vcache *avc;
1943 struct AFS_UCRED *acred;
1948 code = afs_readlink(avc, auio, acred);
1953 #ifdef AFS_SUN53_ENV
1954 gafs_fsync(avc, flag, acred)
1957 gafs_fsync(avc, acred)
1959 register struct vcache *avc;
1960 struct AFS_UCRED *acred;
1965 #ifdef AFS_SUN53_ENV
1966 code = afs_fsync(avc, flag, acred);
1968 code = afs_fsync(avc, acred);
1974 void afs_inactive(struct vcache *avc, struct AFS_UCRED *acred)
1976 struct vnode *vp = AFSTOV(avc);
1977 if (afs_shuttingdown) return ;
1980 * In Solaris and HPUX s800 and HP-UX10.0 they actually call us with
1981 * v_count 1 on last reference!
1983 mutex_enter(&vp->v_lock);
1984 if (avc->vrefCount <= 0) osi_Panic("afs_inactive : v_count <=0\n");
1987 * If more than 1 don't unmap the vnode but do decrement the ref count
1990 if (vp->v_count > 0) {
1991 mutex_exit(&vp->v_lock);
1994 mutex_exit(&vp->v_lock);
1996 * Solaris calls VOP_OPEN on exec, but isn't very diligent about calling
1997 * VOP_CLOSE when executable exits.
1999 if (avc->opens > 0 && !(avc->states & CCore))
2000 avc->opens = avc->execsOrWriters = 0;
2002 afs_InactiveVCache(avc, acred);
2005 void gafs_inactive(avc, acred)
2006 register struct vcache *avc;
2007 struct AFS_UCRED *acred;
2010 afs_inactive(avc, acred);
2015 gafs_fid(avc, fidpp)
2022 code = afs_fid(avc, fidpp);
2027 #endif /* AFS_GLOBAL_SUNLOCK */