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 * SOLARIS/osi_vnodeops.c
19 * Functions: AFS_TRYUP, _init, _info, _fini, afs_addmap, afs_delmap,
20 * afs_vmread, afs_vmwrite, afs_getpage, afs_GetOnePage, afs_putpage,
21 * afs_putapage, afs_nfsrdwr, afs_map, afs_PageLeft, afs_pathconf/afs_cntl,
22 * afs_ioctl, afs_rwlock, afs_rwunlock, afs_seek, afs_space, afs_dump,
23 * afs_cmp, afs_realvp, afs_pageio, afs_dumpctl, afs_dispose, afs_setsecattr,
24 * afs_getsecattr, gafs_open, gafs_close, gafs_getattr, gafs_setattr,
25 * gafs_access, gafs_lookup, gafs_create, gafs_remove, gafs_link,
26 * gafs_rename, gafs_mkdir, gafs_rmdir, gafs_readdir, gafs_symlink,
27 * gafs_readlink, gafs_fsync, afs_inactive, gafs_inactive, gafs_fid
30 * Variables: Afs_vnodeops
33 #include "afs/sysincludes.h" /* Standard vendor system headers */
34 #include "afsincludes.h" /* Afs-based standard headers */
35 #include "afs/afs_stats.h" /* statistics */
36 #include "afs/nfsclient.h"
45 #include <vm/seg_map.h>
46 #include <vm/seg_vn.h>
48 #if defined(AFS_SUN511_ENV)
49 #include <sys/vfs_opreg.h>
51 #include <sys/modctl.h>
52 #include <sys/syscall.h>
53 #include <sys/debug.h>
54 #include <sys/fs_subr.h>
56 /* Translate a faultcode_t as returned by some of the vm routines
57 * into a suitable errno value.
60 afs_fc2errno(faultcode_t fc)
62 switch (FC_CODE(fc)) {
75 extern struct as kas; /* kernel addr space */
76 extern unsigned char *afs_indexFlags;
77 extern afs_lock_t afs_xdcache;
79 /* Additional vnodeops for SunOS 4.0.x */
80 int afs_nfsrdwr(), afs_getpage(), afs_putpage(), afs_map();
81 int afs_dump(), afs_cmp(), afs_realvp(), afs_GetOnePage();
86 afs_addmap(register struct vnode *avp, offset_t offset, struct as *asp,
87 caddr_t addr, int length, int prot, int maxprot, int flags,
90 /* XXX What should we do here?? XXX */
95 afs_delmap(register struct vnode *avp, offset_t offset, struct as *asp,
96 caddr_t addr, int length, int prot, int maxprot, int flags,
99 /* XXX What should we do here?? XXX */
103 #ifdef AFS_SUN510_ENV
105 afs_vmread(register struct vnode *avp, struct uio *auio, int ioflag,
106 afs_ucred_t *acred, caller_context_t *ct)
109 afs_vmread(register struct vnode *avp, struct uio *auio, int ioflag,
115 if (!RW_READ_HELD(&(VTOAFS(avp))->rwlock))
116 osi_Panic("afs_vmread: !rwlock");
118 code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_READ, ioflag, acred);
124 #ifdef AFS_SUN510_ENV
126 afs_vmwrite(register struct vnode *avp, struct uio *auio, int ioflag,
127 afs_ucred_t *acred, caller_context_t *ct)
130 afs_vmwrite(register struct vnode *avp, struct uio *auio, int ioflag,
136 if (!RW_WRITE_HELD(&(VTOAFS(avp))->rwlock))
137 osi_Panic("afs_vmwrite: !rwlock");
139 code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_WRITE, ioflag, acred);
145 afs_getpage(struct vnode *vp, offset_t off, u_int len, u_int *protp,
146 struct page *pl[], u_int plsz, struct seg *seg, caddr_t addr,
147 enum seg_rw rw, afs_ucred_t *acred)
149 register afs_int32 code = 0;
150 AFS_STATCNT(afs_getpage);
152 if (vp->v_flag & VNOMAP) /* File doesn't allow mapping */
160 #if !defined(AFS_SUN56_ENV)
163 off, len, protp, pl, plsz, seg, addr, rw, acred);
165 struct vcache *vcp = VTOAFS(vp);
166 ObtainWriteLock(&vcp->vlock, 548);
168 ReleaseWriteLock(&vcp->vlock);
169 afs_BozonLock(&vcp->pvnLock, vcp);
171 pvn_getpages(afs_GetOnePage, vp,
172 #if !defined(AFS_SUN56_ENV)
175 off, len, protp, pl, plsz, seg, addr, rw, acred);
176 afs_BozonUnlock(&vcp->pvnLock, vcp);
177 ObtainWriteLock(&vcp->vlock, 549);
179 ReleaseWriteLock(&vcp->vlock);
185 /* Return all the pages from [off..off+len) in file */
187 #if defined(AFS_SUN56_ENV)
188 afs_GetOnePage(struct vnode *vp, u_offset_t off, u_int alen, u_int *protp,
189 struct page *pl[], u_int plsz, struct seg *seg, caddr_t addr,
190 enum seg_rw rw, afs_ucred_t *acred)
192 afs_GetOnePage(struct vnode *vp, u_int off, u_int alen, u_int *protp,
193 struct page *pl[], u_int plsz, struct seg *seg, caddr_t addr,
194 enum seg_rw rw, afs_ucred_t *acred)
197 register struct page *page;
198 register afs_int32 code = 0;
202 register struct vcache *avc;
203 register struct dcache *tdc;
206 afs_size_t offset, nlen = 0;
207 struct vrequest treq;
208 afs_int32 mapForRead = 0, Code = 0;
212 osi_Panic("GetOnePage: !acred");
214 avc = VTOAFS(vp); /* cast to afs vnode */
216 if (avc->credp /*&& AFS_NFSXLATORREQ(acred) */
217 && AFS_NFSXLATORREQ(avc->credp)) {
220 if (code = afs_InitReq(&treq, acred))
224 /* This is a read-ahead request, e.g. due to madvise. */
226 ObtainReadLock(&avc->lock);
228 while (plen > 0 && !afs_BBusy()) {
229 /* Obtain a dcache entry at off. 2 means don't fetch data. */
231 afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen,
236 /* Write-lock the dcache entry, if we don't succeed, just go on */
237 if (0 != NBObtainWriteLock(&tdc->lock, 642)) {
242 /* If we aren't already fetching this dcache entry, queue it */
243 if (!(tdc->mflags & DFFetchReq)) {
246 tdc->mflags |= DFFetchReq;
247 bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
248 (afs_size_t) off, (afs_size_t) 1, tdc,
249 (void *)0, (void *)0);
251 /* Unable to start background fetch; might as well stop */
252 tdc->mflags &= ~DFFetchReq;
253 ReleaseWriteLock(&tdc->lock);
257 ReleaseWriteLock(&tdc->lock);
259 ReleaseWriteLock(&tdc->lock);
264 /* Adjust our offset and remaining length values */
268 /* If we aren't making progress for some reason, bail out */
273 ReleaseReadLock(&avc->lock);
278 pl[0] = NULL; /* Make sure it's empty */
280 /* first, obtain the proper lock for the VM system */
282 /* if this is a read request, map the page in read-only. This will
283 * allow us to swap out the dcache entry if there are only read-only
284 * pages created for the chunk, which helps a *lot* when dealing
285 * with small caches. Otherwise, we have to invalidate the vm
286 * pages for the range covered by a chunk when we swap out the
289 if (rw == S_READ || rw == S_EXEC)
296 if (rw == S_WRITE || rw == S_CREATE)
297 tdc = afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen, 5);
299 tdc = afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen, 1);
301 return afs_CheckCode(EINVAL, &treq, 62);
302 code = afs_VerifyVCache(avc, &treq);
305 return afs_CheckCode(code, &treq, 44); /* failed to get it */
308 afs_BozonLock(&avc->pvnLock, avc);
309 ObtainReadLock(&avc->lock);
311 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, (afs_int32) vp,
312 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off), ICL_TYPE_LONG, len,
313 ICL_TYPE_LONG, (int)rw);
318 /* Check to see if we're in the middle of a VM purge, and if we are, release
319 * the locks and try again when the VM purge is done. */
320 ObtainWriteLock(&avc->vlock, 550);
322 ReleaseReadLock(&avc->lock);
323 ReleaseWriteLock(&avc->vlock);
324 afs_BozonUnlock(&avc->pvnLock, avc);
326 /* Check activeV again, it may have been turned off
327 * while we were waiting for a lock in afs_PutDCache */
328 ObtainWriteLock(&avc->vlock, 574);
330 avc->vstates |= VRevokeWait;
331 ReleaseWriteLock(&avc->vlock);
332 afs_osi_Sleep(&avc->vstates);
334 ReleaseWriteLock(&avc->vlock);
338 ReleaseWriteLock(&avc->vlock);
340 /* We're about to do stuff with our dcache entry.. Lock it. */
341 ObtainReadLock(&tdc->lock);
343 /* Check to see whether the cache entry is still valid */
344 if (!(avc->f.states & CStatd)
345 || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
346 ReleaseReadLock(&tdc->lock);
347 ReleaseReadLock(&avc->lock);
348 afs_BozonUnlock(&avc->pvnLock, avc);
354 while (1) { /* loop over all pages */
355 /* now, try to find the page in memory (it may already be intransit or laying
356 * around the free list */
358 page_lookup(vp, toffset, (rw == S_CREATE ? SE_EXCL : SE_SHARED));
362 /* if we make it here, we can't find the page in memory. Do a real disk read
363 * from the cache to get the data */
364 Code |= 0x200; /* XXX */
365 #if defined(AFS_SUN54_ENV)
366 /* use PG_EXCL because we know the page does not exist already. If it
367 * actually does exist, we have somehow raced between lookup and create.
368 * As of 4/98, that shouldn't be possible, but we'll be defensive here
369 * in case someone tries to relax all the serialization of read and write
370 * operations with harmless things like stat. */
371 #if defined(AFS_SUN58_ENV)
373 page_create_va(vp, toffset, PAGESIZE, PG_WAIT | PG_EXCL, seg,
377 page_create_va(vp, toffset, PAGESIZE, PG_WAIT | PG_EXCL,
381 page = page_create(vp, toffset, PAGESIZE, PG_WAIT);
387 pagezero(page, alen, PAGESIZE - alen);
389 if (rw == S_CREATE) {
390 /* XXX Don't read from AFS in write only cases XXX */
391 page_io_unlock(page);
394 /* now it is time to start I/O operation */
395 buf = pageio_setup(page, PAGESIZE, vp, B_READ); /* allocate a buf structure */
398 #if defined(AFS_SUN56_ENV)
399 buf->b_lblkno = lbtodb(toffset);
401 buf->b_blkno = btodb(toffset);
403 bp_mapin(buf); /* map it in to our address space */
406 /* afs_ustrategy will want to lock the dcache entry */
407 ReleaseReadLock(&tdc->lock);
408 code = afs_ustrategy(buf, acred); /* do the I/O */
409 ObtainReadLock(&tdc->lock);
412 /* Before freeing unmap the buffer */
418 page_io_unlock(page);
421 /* come here when we have another page (already held) to enter */
423 /* put page in array and continue */
424 /* The p_selock must be downgraded to a shared lock after the page is read */
425 #if defined(AFS_SUN56_ENV)
426 if ((rw != S_CREATE) && !(PAGE_SHARED(page)))
428 if ((rw != S_CREATE) && !(se_shared_assert(&page->p_selock)))
431 page_downgrade(page);
434 code = page_iolock_assert(page);
440 break; /* done all the pages */
441 } /* while (1) ... */
445 ReleaseReadLock(&tdc->lock);
447 /* Prefetch next chunk if we're at a chunk boundary */
448 if (AFS_CHUNKOFFSET(off) == 0) {
449 if (!(tdc->mflags & DFNextStarted))
450 afs_PrefetchChunk(avc, tdc, acred, &treq);
453 ReleaseReadLock(&avc->lock);
454 ObtainWriteLock(&afs_xdcache, 246);
456 /* track that we have dirty (or dirty-able) pages for this chunk. */
457 afs_indexFlags[tdc->index] |= IFDirtyPages;
459 afs_indexFlags[tdc->index] |= IFAnyPages;
460 ReleaseWriteLock(&afs_xdcache);
461 afs_BozonUnlock(&avc->pvnLock, avc);
463 afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code,
464 ICL_TYPE_LONG, (int)page, ICL_TYPE_LONG, Code);
469 afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code,
470 ICL_TYPE_LONG, (int)page, ICL_TYPE_LONG, Code);
471 /* release all pages, drop locks, return code */
473 pvn_read_done(page, B_ERROR);
474 ReleaseReadLock(&avc->lock);
475 afs_BozonUnlock(&avc->pvnLock, avc);
476 ReleaseReadLock(&tdc->lock);
482 afs_putpage(struct vnode *vp, offset_t off, u_int len, int flags,
488 #if defined(AFS_SUN58_ENV)
494 afs_int32 NPages = 0;
495 #if defined(AFS_SUN56_ENV)
496 u_offset_t toff = off;
502 AFS_STATCNT(afs_putpage);
503 if (vp->v_flag & VNOMAP) /* file doesn't allow mapping */
507 * Putpage (ASYNC) is called every sec to flush out dirty vm pages
510 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER,
511 (afs_int32) vp, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
512 ICL_TYPE_INT32, (afs_int32) len, ICL_TYPE_LONG, (int)flags);
514 afs_BozonLock(&avc->pvnLock, avc);
515 ObtainSharedLock(&avc->lock, 247);
518 /* Get a list of modified (or whatever) pages */
520 endPos = (afs_offs_t) off + len; /* position we're supposed to write up to */
521 while ((afs_offs_t) toff < endPos
522 && (afs_offs_t) toff < avc->f.m.Length) {
523 /* If not invalidating pages use page_lookup_nowait to avoid reclaiming
524 * them from the free list
527 if (flags & (B_FREE | B_INVAL))
528 pages = page_lookup(vp, toff, SE_EXCL);
530 pages = page_lookup_nowait(vp, toff, SE_SHARED);
531 if (!pages || !pvn_getdirty(pages, flags))
537 UpgradeSToWLock(&avc->lock, 671);
541 code = afs_putapage(vp, pages, &toff, &tlen, flags, cred);
552 UpgradeSToWLock(&avc->lock, 670);
557 #if defined(AFS_SUN56_ENV)
558 code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
560 code = pvn_vplist_dirty(vp, (u_int) off, afs_putapage, flags, cred);
565 if (code && !avc->vc_error) {
567 UpgradeSToWLock(&avc->lock, 669);
570 avc->vc_error = code;
574 ReleaseWriteLock(&avc->lock);
576 ReleaseSharedLock(&avc->lock);
577 afs_BozonUnlock(&avc->pvnLock, avc);
578 afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code,
579 ICL_TYPE_LONG, NPages);
586 #if defined(AFS_SUN58_ENV)
587 afs_putapage(struct vnode *vp, struct page *pages, u_offset_t * offp,
588 size_t * lenp, int flags, afs_ucred_t *credp)
589 #elif defined(AFS_SUN56_ENV)
590 afs_putapage(struct vnode *vp, struct page *pages, u_offset_t * offp,
591 u_int * lenp, int flags, afs_ucred_t *credp)
593 afs_putapage(struct vnode *vp, struct page *pages, u_int * offp,
594 u_int * lenp, int flags, afs_ucred_t *credp)
598 struct vcache *avc = VTOAFS(vp);
600 u_int tlen = PAGESIZE;
601 afs_offs_t off = (pages->p_offset / PAGESIZE) * PAGESIZE;
604 * Now we've got the modified pages. All pages are locked and held
605 * XXX Find a kluster that fits in one block (or page). We also
606 * adjust the i/o if the file space is less than a while page. XXX
608 if (off + tlen > avc->f.m.Length) {
609 tlen = avc->f.m.Length - off;
611 /* can't call mapout with 0 length buffers (rmfree panics) */
612 if (((tlen >> 24) & 0xff) == 0xff) {
617 * Can't call mapout with 0 length buffers since we'll get rmfree panics
619 tbuf = pageio_setup(pages, tlen, vp, B_WRITE | flags);
624 #if defined(AFS_SUN56_ENV)
625 tbuf->b_lblkno = lbtodb(pages->p_offset);
627 tbuf->b_blkno = btodb(pages->p_offset);
631 afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUTONE, ICL_TYPE_LONG, avc,
632 ICL_TYPE_LONG, pages, ICL_TYPE_LONG, tlen, ICL_TYPE_OFFSET,
633 ICL_HANDLE_OFFSET(off));
634 code = afs_ustrategy(tbuf, credp); /* unlocks page */
638 pvn_write_done(pages, ((code) ? B_ERROR : 0) | B_WRITE | flags);
649 afs_nfsrdwr(register struct vcache *avc, struct uio *auio, enum uio_rw arw,
650 int ioflag, afs_ucred_t *acred)
652 register afs_int32 code;
655 afs_int32 mode, sflags;
657 struct dcache *dcp, *dcp_newpage;
658 afs_size_t fileBase, size;
660 register afs_int32 tsize;
661 register afs_int32 pageOffset, extraResid = 0;
662 register afs_size_t origLength; /* length when reading/writing started */
663 register long appendLength; /* length when this call will finish */
664 int created; /* created pages instead of faulting them */
666 int didFakeOpen, eof;
667 struct vrequest treq;
671 AFS_STATCNT(afs_nfsrdwr);
673 /* can't read or write other things */
674 if (vType(avc) != VREG)
677 if (auio->uio_resid == 0)
680 afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, (afs_int32) avc,
681 ICL_TYPE_LONG, (arw == UIO_WRITE ? 1 : 0), ICL_TYPE_OFFSET,
682 ICL_HANDLE_OFFSET(auio->uio_loffset), ICL_TYPE_OFFSET,
683 ICL_HANDLE_OFFSET(auio->uio_resid));
685 #ifndef AFS_64BIT_CLIENT
686 if (AfsLargeFileUio(auio)) /* file is larger than 2 GB */
691 osi_Panic("rdwr: !acred");
693 if (code = afs_InitReq(&treq, acred))
696 /* It's not really possible to know if a write cause a growth in the
697 * cache size, we we wait for a cache drain for any write.
699 afs_MaybeWakeupTruncateDaemon();
700 while ((arw == UIO_WRITE)
701 && (afs_blocksUsed > PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks))) {
702 if (afs_blocksUsed - afs_blocksDiscarded >
703 PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
704 afs_WaitForCacheDrain = 1;
705 afs_osi_Sleep(&afs_WaitForCacheDrain);
707 afs_MaybeFreeDiscardedDCache();
708 afs_MaybeWakeupTruncateDaemon();
710 code = afs_VerifyVCache(avc, &treq);
712 return afs_CheckCode(code, &treq, 45);
714 afs_BozonLock(&avc->pvnLock, avc);
715 osi_FlushPages(avc, acred); /* hold bozon lock, but not basic vnode lock */
717 ObtainWriteLock(&avc->lock, 250);
719 /* adjust parameters when appending files */
720 if ((ioflag & IO_APPEND) && arw == UIO_WRITE) {
721 #if defined(AFS_SUN56_ENV)
722 auio->uio_loffset = avc->f.m.Length; /* write at EOF position */
724 auio->uio_offset = avc->f.m.Length; /* write at EOF position */
727 if (auio->afsio_offset < 0 || (auio->afsio_offset + auio->uio_resid) < 0) {
728 ReleaseWriteLock(&avc->lock);
729 afs_BozonUnlock(&avc->pvnLock, avc);
732 #ifndef AFS_64BIT_CLIENT
733 /* file is larger than 2GB */
734 if (AfsLargeFileSize(auio->uio_offset, auio->uio_resid)) {
735 ReleaseWriteLock(&avc->lock);
736 afs_BozonUnlock(&avc->pvnLock, avc);
741 didFakeOpen = 0; /* keep track of open so we can do close */
742 if (arw == UIO_WRITE) {
743 /* do ulimit processing; shrink resid or fail */
744 #if defined(AFS_SUN56_ENV)
745 if (auio->uio_loffset + auio->afsio_resid > auio->uio_llimit) {
746 if (auio->uio_loffset >= auio->uio_llimit) {
747 ReleaseWriteLock(&avc->lock);
748 afs_BozonUnlock(&avc->pvnLock, avc);
751 /* track # of bytes we should write, but won't because of
752 * ulimit; we must add this into the final resid value
753 * so caller knows we punted some data.
755 extraResid = auio->uio_resid;
756 auio->uio_resid = auio->uio_llimit - auio->uio_loffset;
757 extraResid -= auio->uio_resid;
762 if (auio->afsio_offset + auio->afsio_resid > auio->uio_limit) {
763 if (auio->afsio_offset >= auio->uio_limit) {
764 ReleaseWriteLock(&avc->lock);
765 afs_BozonUnlock(&avc->pvnLock, avc);
768 /* track # of bytes we should write, but won't because of
769 * ulimit; we must add this into the final resid value
770 * so caller knows we punted some data.
772 extraResid = auio->uio_resid;
773 auio->uio_resid = auio->uio_limit - auio->afsio_offset;
774 extraResid -= auio->uio_resid;
779 mode = S_WRITE; /* segment map-in mode */
780 afs_FakeOpen(avc); /* do this for writes, so data gets put back
781 * when we want it to be put back */
782 didFakeOpen = 1; /* we'll be doing a fake open */
783 /* before starting any I/O, we must ensure that the file is big enough
784 * to hold the results (since afs_putpage will be called to force the I/O */
785 size = auio->afsio_resid + auio->afsio_offset; /* new file size */
787 origLength = avc->f.m.Length;
788 if (size > avc->f.m.Length) {
789 afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
790 __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
791 ICL_HANDLE_OFFSET(avc->f.m.Length), ICL_TYPE_OFFSET,
792 ICL_HANDLE_OFFSET(size));
793 avc->f.m.Length = size; /* file grew */
795 avc->f.states |= CDirty; /* Set the dirty bit */
796 avc->f.m.Date = osi_Time(); /* Set file date (for ranlib) */
798 mode = S_READ; /* map-in read-only */
799 origLength = avc->f.m.Length;
802 if (acred && AFS_NFSXLATORREQ(acred)) {
803 if (arw == UIO_READ) {
805 (avc, PRSFS_READ, &treq,
806 CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
807 ReleaseWriteLock(&avc->lock);
808 afs_BozonUnlock(&avc->pvnLock, avc);
818 counter = 0; /* don't call afs_DoPartialWrite first time through. */
820 /* compute the amount of data to move into this block,
821 * based on auio->afsio_resid. Note that we copy data in units of
822 * MAXBSIZE, not PAGESIZE. This is because segmap_getmap panics if you
823 * call it with an offset based on blocks smaller than MAXBSIZE
824 * (implying that it should be named BSIZE, since it is clearly both a
826 size = auio->afsio_resid; /* transfer size */
827 fileBase = ((arw == UIO_READ) && (origLength < auio->uio_offset)) ?
828 origLength : auio->afsio_offset; /* start file position for xfr */
829 pageBase = fileBase & ~(MAXBSIZE - 1); /* file position of the page */
830 pageOffset = fileBase & (MAXBSIZE - 1); /* xfr start's offset within page */
831 tsize = MAXBSIZE - pageOffset; /* how much more fits in this page */
832 /* we'll read tsize bytes, but first must make sure tsize isn't too big */
834 tsize = size; /* don't read past end of request */
835 eof = 0; /* flag telling us if we hit the EOF on the read */
836 if (arw == UIO_READ) { /* we're doing a read operation */
837 /* don't read past EOF */
838 if (fileBase + tsize > origLength) {
839 tsize = origLength - fileBase;
840 eof = 1; /* we did hit the EOF */
842 tsize = 0; /* better safe than sorry */
846 /* Purge dirty chunks of file if there are too many dirty
847 * chunks. Inside the write loop, we only do this at a chunk
848 * boundary. Clean up partial chunk if necessary at end of loop.
850 if (counter > 0 && code == 0 && AFS_CHUNKOFFSET(fileBase) == 0) {
851 code = afs_DoPartialWrite(avc, &treq);
855 /* write case, we ask segmap_release to call putpage. Really, we
856 * don't have to do this on every page mapin, but for now we're
857 * lazy, and don't modify the rest of AFS to scan for modified
858 * pages on a close or other "synchronize with file server"
859 * operation. This makes things a little cleaner, but probably
860 * hurts performance. */
865 break; /* nothing to transfer, we're done */
867 if (arw == UIO_WRITE)
868 avc->f.states |= CDirty; /* may have been cleared by DoPartialWrite */
870 /* Before dropping lock, hold the chunk (create it if necessary). This
871 * serves two purposes: (1) Ensure Cache Truncate Daemon doesn't try
872 * to purge the chunk's pages while we have them locked. This would
873 * cause deadlock because we might be waiting for the CTD to free up
874 * a chunk. (2) If we're writing past the original EOF, and we're
875 * at the base of the chunk, then make sure it exists online
876 * before we do the uiomove, since the segmap_release will
877 * write out to the chunk, causing it to get fetched if it hasn't
878 * been created yet. The code that would otherwise notice that
879 * we're fetching a chunk past EOF won't work, since we've
880 * already adjusted the file size above.
882 ObtainWriteLock(&avc->vlock, 551);
883 while (avc->vstates & VPageCleaning) {
884 ReleaseWriteLock(&avc->vlock);
885 ReleaseWriteLock(&avc->lock);
886 afs_osi_Sleep(&avc->vstates);
887 ObtainWriteLock(&avc->lock, 334);
888 ObtainWriteLock(&avc->vlock, 552);
890 ReleaseWriteLock(&avc->vlock);
892 afs_size_t toff, tlen;
893 dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
899 ReleaseWriteLock(&avc->lock); /* uiomove may page fault */
901 #if defined(AFS_SUN56_ENV)
902 data = segmap_getmap(segkmap, AFSTOV(avc), (u_offset_t) pageBase);
903 raddr = (caddr_t) (((uintptr_t) data + pageOffset) & PAGEMASK);
905 data = segmap_getmap(segkmap, AFSTOV(avc), pageBase);
906 raddr = (caddr_t) (((u_int) data + pageOffset) & PAGEMASK);
909 (((u_int) data + pageOffset + tsize + PAGEOFFSET) & PAGEMASK) -
912 /* if we're doing a write, and we're starting at the rounded
913 * down page base, and we're writing enough data to cover all
914 * created pages, then we must be writing all of the pages
915 * in this MAXBSIZE window that we're creating.
918 if (arw == UIO_WRITE && ((long)raddr == (long)data + pageOffset)
920 /* probably the dcache backing this guy is around, but if
921 * not, we can't do this optimization, since we're creating
922 * writable pages, which must be backed by a chunk.
925 dcp_newpage = afs_FindDCache(avc, pageBase);
927 && hsame(avc->f.m.DataVersion, dcp_newpage->f.versionNo)) {
928 ObtainWriteLock(&avc->lock, 251);
929 ObtainWriteLock(&avc->vlock, 576);
930 ObtainReadLock(&dcp_newpage->lock);
931 if ((avc->activeV == 0)
932 && hsame(avc->f.m.DataVersion, dcp_newpage->f.versionNo)
933 && !(dcp_newpage->dflags & (DFFetching))) {
935 segmap_pagecreate(segkmap, raddr, rsize, 1);
937 ObtainWriteLock(&afs_xdcache, 252);
938 /* Mark the pages as created and dirty */
939 afs_indexFlags[dcp_newpage->index]
940 |= (IFAnyPages | IFDirtyPages);
941 ReleaseWriteLock(&afs_xdcache);
944 ReleaseReadLock(&dcp_newpage->lock);
945 afs_PutDCache(dcp_newpage);
946 ReleaseWriteLock(&avc->vlock);
947 ReleaseWriteLock(&avc->lock);
948 } else if (dcp_newpage)
949 afs_PutDCache(dcp_newpage);
954 afs_fc2errno(segmap_fault
955 (kas.a_hat, segkmap, raddr, rsize,
959 AFS_UIOMOVE(data + pageOffset, tsize, arw, auio, code);
960 segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTUNLOCK,
964 code = segmap_release(segkmap, data, sflags);
966 (void)segmap_release(segkmap, data, 0);
969 ObtainWriteLock(&avc->lock, 253);
977 afs_FakeClose(avc, acred);
979 if (arw == UIO_WRITE && (avc->f.states & CDirty)) {
980 code2 = afs_DoPartialWrite(avc, &treq);
985 if (!code && avc->vc_error) {
986 code = avc->vc_error;
988 ReleaseWriteLock(&avc->lock);
989 afs_BozonUnlock(&avc->pvnLock, avc);
992 if ((ioflag & FSYNC) && (arw == UIO_WRITE)
993 && !AFS_NFSXLATORREQ(acred))
994 code = afs_fsync(avc, 0, acred);
996 if ((ioflag & IO_SYNC) && (arw == UIO_WRITE)
997 && !AFS_NFSXLATORREQ(acred))
998 code = afs_fsync(avc, acred);
1001 #ifdef AFS_SUN52_ENV
1003 * If things worked, add in as remaining in request any bytes
1004 * we didn't write due to file size ulimit.
1006 if (code == 0 && extraResid > 0)
1007 auio->uio_resid += extraResid;
1009 return afs_CheckCode(code, &treq, 46);
1013 afs_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addr, u_int len, u_char prot, u_char maxprot, u_int flags, afs_ucred_t *cred)
1015 struct segvn_crargs crargs;
1016 register afs_int32 code;
1017 struct vrequest treq;
1018 register struct vcache *avc = VTOAFS(vp);
1020 AFS_STATCNT(afs_map);
1023 /* check for reasonableness on segment bounds; apparently len can be < 0 */
1024 if (off < 0 || off + len < 0) {
1027 #ifndef AFS_64BIT_CLIENT
1028 if (AfsLargeFileSize(off, len)) { /* file is larger than 2 GB */
1034 if (vp->v_flag & VNOMAP) /* File isn't allowed to be mapped */
1037 if (vp->v_filocks) /* if locked, disallow mapping */
1041 if (code = afs_InitReq(&treq, cred))
1044 if (vp->v_type != VREG) {
1049 code = afs_VerifyVCache(avc, &treq);
1053 afs_BozonLock(&avc->pvnLock, avc);
1054 osi_FlushPages(avc, cred); /* ensure old pages are gone */
1055 avc->f.states |= CMAPPED; /* flag cleared at afs_inactive */
1056 afs_BozonUnlock(&avc->pvnLock, avc);
1060 if ((flags & MAP_FIXED) == 0) {
1061 #if defined(AFS_SUN57_ENV)
1062 map_addr(addr, len, off, 1, flags);
1063 #elif defined(AFS_SUN56_ENV)
1064 map_addr(addr, len, off, 1);
1066 map_addr(addr, len, (off_t) off, 1);
1068 if (*addr == NULL) {
1074 (void)as_unmap(as, *addr, len); /* unmap old address space use */
1075 /* setup the create parameter block for the call */
1076 crargs.vp = AFSTOV(avc);
1077 crargs.offset = (u_int) off;
1079 crargs.type = flags & MAP_TYPE;
1081 crargs.maxprot = maxprot;
1082 crargs.amp = (struct anon_map *)0;
1083 crargs.flags = flags & ~MAP_TYPE;
1085 code = as_map(as, *addr, len, segvn_create, (char *)&crargs);
1089 code = afs_CheckCode(code, &treq, 47);
1093 code = afs_CheckCode(code, &treq, 48);
1100 * For Now We use standard local kernel params for AFS system values. Change this
1104 #ifdef AFS_SUN511_ENV
1105 afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
1106 register afs_ucred_t *credp, caller_context_t *ct)
1108 afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
1109 register afs_ucred_t *credp)
1110 #endif /* AFS_SUN511_ENV */
1112 AFS_STATCNT(afs_cntl);
1115 *outdatap = MAXLINK;
1118 *outdatap = MAXNAMLEN;
1121 *outdatap = MAXPATHLEN;
1123 case _PC_CHOWN_RESTRICTED:
1129 case _PC_FILESIZEBITS:
1130 #ifdef AFS_64BIT_CLIENT
1137 #ifdef AFS_SUN511_ENV
1138 return fs_pathconf(vp, cmd, outdatap, credp, ct);
1140 return fs_pathconf(vp, cmd, outdatap, credp);
1141 #endif /* AFS_SUN511_ENV */
1147 afs_ioctl(struct vnode *vnp, int com, int arg, int flag, cred_t *credp,
1154 afs_rwlock(struct vnode *vnp, int wlock)
1156 rw_enter(&(VTOAFS(vnp))->rwlock, (wlock ? RW_WRITER : RW_READER));
1161 afs_rwunlock(struct vnode *vnp, int wlock)
1163 rw_exit(&(VTOAFS(vnp))->rwlock);
1169 afs_seek(struct vnode *vnp, offset_t ooff, offset_t *noffp)
1171 register int code = 0;
1173 #ifndef AFS_64BIT_CLIENT
1174 # define __MAXOFF_T MAXOFF_T
1176 # define __MAXOFF_T MAXOFFSET_T
1179 if ((*noffp < 0 || *noffp > __MAXOFF_T))
1185 #ifdef AFS_SUN59_ENV
1186 afs_frlock(struct vnode *vnp, int cmd, struct flock64 *ap, int flag,
1187 offset_t off, struct flk_callback *flkcb, afs_ucred_t *credp)
1188 #elif defined(AFS_SUN56_ENV)
1189 afs_frlock(struct vnode *vnp, int cmd, struct flock64 *ap, int flag,
1190 offset_t off, afs_ucred_t *credp)
1192 afs_frlock(struct vnode *vnp, int cmd, struct flock *ap, int flag,
1193 offset_t off, afs_ucred_t *credp)
1196 register afs_int32 code = 0;
1198 * Implement based on afs_lockctl
1201 #ifdef AFS_SUN59_ENV
1203 afs_warn("Don't know how to deal with flk_callback's!\n");
1205 if ((cmd == F_GETLK) || (cmd == F_O_GETLK) || (cmd == F_SETLK)
1206 || (cmd == F_SETLKW)) {
1207 #ifdef AFS_SUN53_ENV
1208 ap->l_pid = ttoproc(curthread)->p_pid;
1211 ap->l_pid = ttoproc(curthread)->p_epid;
1212 ap->l_sysid = ttoproc(curthread)->p_sysid;
1216 #ifdef AFS_SUN56_ENV
1217 code = convoff(vnp, ap, 0, off);
1219 code = convoff(vnp, ap, 0, (off_t) off);
1226 code = afs_lockctl(VTOAFS(vnp), ap, cmd, credp);
1233 #if defined(AFS_SUN56_ENV)
1234 afs_space(struct vnode *vnp, int cmd, struct flock64 *ap, int flag,
1235 offset_t off, afs_ucred_t *credp)
1237 afs_space(struct vnode *vnp, int cmd, struct flock *ap, int flag,
1238 offset_t off, afs_ucred_t *credp)
1241 register afs_int32 code = EINVAL;
1244 if ((cmd == F_FREESP)
1245 #ifdef AFS_SUN56_ENV
1246 && ((code = convoff(vnp, ap, 0, off)) == 0)) {
1248 && ((code = convoff(vnp, ap, 0, (off_t) off)) == 0)) {
1252 vattr.va_mask = AT_SIZE;
1253 vattr.va_size = ap->l_start;
1254 code = afs_setattr(VTOAFS(vnp), &vattr, 0, credp);
1262 afs_dump(struct vnode *vp, caddr_t addr, int i1, int i2)
1264 AFS_STATCNT(afs_dump);
1265 afs_warn("AFS_DUMP. MUST IMPLEMENT THIS!!!\n");
1270 /* Nothing fancy here; just compare if vnodes are identical ones */
1272 afs_cmp(struct vnode *vp1, struct vnode *vp2)
1274 AFS_STATCNT(afs_cmp);
1275 return (vp1 == vp2);
1280 afs_realvp(struct vnode *vp, struct vnode **vpp)
1282 AFS_STATCNT(afs_realvp);
1288 afs_pageio(struct vnode *vp, struct page *pp, u_int ui1, u_int ui2, int i1,
1291 afs_warn("afs_pageio: Not implemented\n");
1296 #ifdef AFS_SUN59_ENV
1297 afs_dumpctl(struct vnode *vp, int i, int *blkp)
1299 afs_dumpctl(struct vnode *vp, int i)
1302 afs_warn("afs_dumpctl: Not implemented\n");
1306 #ifdef AFS_SUN54_ENV
1307 #ifdef AFS_SUN511_ENV
1309 afs_dispose(struct vnode *vp, struct page *p, int fl, int dn, struct cred *cr, struct caller_context_t *ct)
1311 fs_dispose(vp, p, fl, dn, cr,ct);
1315 afs_setsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *creds, struct caller_context_t *ct)
1321 afs_getsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *creds, struct caller_context_t *ct)
1323 return fs_fab_acl(vp, vsecattr, flag, creds,ct);
1327 afs_dispose(struct vnode *vp, struct page *p, int fl, int dn, struct cred *cr)
1329 fs_dispose(vp, p, fl, dn, cr);
1333 afs_setsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag,
1340 afs_getsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *creds)
1342 return fs_fab_acl(vp, vsecattr, flag, creds);
1347 #ifdef AFS_GLOBAL_SUNLOCK
1348 extern int gafs_open(register struct vcache **avcp, afs_int32 aflags,
1349 afs_ucred_t *acred);
1350 extern int gafs_close(register struct vcache *avc, afs_int32 aflags,
1351 int count, offset_t offset, afs_ucred_t *acred);
1352 extern int afs_ioctl(struct vnode *vnp, int com, int arg, int flag,
1353 cred_t *credp, int *rvalp);
1354 extern int gafs_access(register struct vcache *avc, register afs_int32 amode,
1355 int flags, afs_ucred_t *acred);
1356 extern int gafs_getattr(register struct vcache *avc,
1357 register struct vattr *attrs, int flags,
1358 afs_ucred_t *acred);
1359 extern int gafs_setattr(register struct vcache *avc,
1360 register struct vattr *attrs, int flags,
1361 afs_ucred_t *acred);
1362 extern int gafs_lookup(register struct vcache *adp, char *aname,
1363 register struct vcache **avcp, struct pathname *pnp,
1364 int flags, struct vnode *rdir, afs_ucred_t *acred);
1365 extern int gafs_remove(register struct vcache *adp, char *aname,
1366 afs_ucred_t *acred);
1367 extern int gafs_link(register struct vcache *adp, register struct vcache *avc,
1368 char *aname, afs_ucred_t *acred);
1369 extern int gafs_rename(register struct vcache *aodp, char *aname1,
1370 register struct vcache *andp, char *aname2,
1371 afs_ucred_t *acred);
1372 extern int gafs_symlink(register struct vcache *adp, char *aname,
1373 struct vattr *attrs, register char *atargetName,
1374 afs_ucred_t *acred);
1375 extern int gafs_rmdir(register struct vcache *adp, char *aname,
1376 struct vnode *cdirp, afs_ucred_t *acred);
1377 extern int gafs_mkdir(register struct vcache *adp, char *aname,
1378 struct vattr *attrs, register struct vcache **avcp,
1379 afs_ucred_t *acred);
1381 #ifdef AFS_SUN53_ENV
1382 gafs_fsync(register struct vcache *avc, int flag, afs_ucred_t *acred);
1384 gafs_fsync(register struct vcache *avc, afs_ucred_t *acred);
1386 extern int gafs_readlink(register struct vcache *avc, struct uio *auio,
1387 afs_ucred_t *acred);
1388 extern int gafs_readdir(register struct vcache *avc, struct uio *auio,
1389 afs_ucred_t *acred, int *eofp);
1390 extern void gafs_inactive(register struct vcache *avc,
1391 afs_ucred_t *acred);
1392 extern int gafs_fid(struct vcache *avc, struct fid **fidpp);
1393 extern int gafs_create(register struct vcache *adp, char *aname,
1394 struct vattr *attrs, enum vcexcl aexcl, int amode,
1395 struct vcache **avcp, afs_ucred_t *acred);
1396 #ifdef AFS_SUN511_ENV
1397 extern int afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
1398 register afs_ucred_t *credp, caller_context_t *ct);
1400 extern int afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
1401 register afs_ucred_t *credp);
1402 #endif /* AFS_SUN511_ENV */
1404 #if defined(AFS_SUN511_ENV)
1405 /* The following list must always be NULL-terminated */
1406 const fs_operation_def_t afs_vnodeops_template[] = {
1407 VOPNAME_OPEN, { .vop_open = gafs_open },
1408 VOPNAME_CLOSE, { .vop_close = gafs_close },
1409 VOPNAME_READ, { .vop_read = afs_vmread },
1410 VOPNAME_WRITE, { .vop_write = afs_vmwrite },
1411 VOPNAME_IOCTL, { .vop_ioctl = afs_ioctl },
1412 VOPNAME_SETFL, { .vop_setfl = fs_setfl },
1413 VOPNAME_GETATTR, { .vop_getattr = gafs_getattr },
1414 VOPNAME_SETATTR, { .vop_setattr = gafs_setattr },
1415 VOPNAME_ACCESS, { .vop_access = gafs_access },
1416 VOPNAME_LOOKUP, { .vop_lookup = gafs_lookup },
1417 VOPNAME_CREATE, { .vop_create = gafs_create },
1418 VOPNAME_REMOVE, { .vop_remove = gafs_remove },
1419 VOPNAME_LINK, { .vop_link = gafs_link },
1420 VOPNAME_RENAME, { .vop_rename = gafs_rename },
1421 VOPNAME_MKDIR, { .vop_mkdir = gafs_mkdir },
1422 VOPNAME_RMDIR, { .vop_rmdir = gafs_rmdir },
1423 VOPNAME_READDIR, { .vop_readdir = gafs_readdir },
1424 VOPNAME_SYMLINK, { .vop_symlink = gafs_symlink },
1425 VOPNAME_READLINK, { .vop_readlink = gafs_readlink },
1426 VOPNAME_FSYNC, { .vop_fsync = gafs_fsync },
1427 VOPNAME_INACTIVE, { .vop_inactive = gafs_inactive },
1428 VOPNAME_FID, { .vop_fid = gafs_fid },
1429 VOPNAME_RWLOCK, { .vop_rwlock = afs_rwlock },
1430 VOPNAME_RWUNLOCK, { .vop_rwunlock = afs_rwunlock },
1431 VOPNAME_SEEK, { .vop_seek = afs_seek },
1432 VOPNAME_CMP, { .vop_cmp = afs_cmp },
1433 VOPNAME_FRLOCK, { .vop_frlock = afs_frlock },
1434 VOPNAME_SPACE, { .vop_space = afs_space },
1435 VOPNAME_REALVP, { .vop_realvp = afs_realvp },
1436 VOPNAME_GETPAGE, { .vop_getpage = afs_getpage },
1437 VOPNAME_PUTPAGE, { .vop_putpage = afs_putpage },
1438 VOPNAME_MAP, { .vop_map = afs_map },
1439 VOPNAME_ADDMAP, { .vop_addmap = afs_addmap },
1440 VOPNAME_DELMAP, { .vop_delmap = afs_delmap },
1441 VOPNAME_POLL, { .vop_poll = fs_poll },
1442 VOPNAME_PATHCONF, { .vop_pathconf = afs_pathconf },
1443 VOPNAME_PAGEIO, { .vop_pageio = afs_pageio },
1444 VOPNAME_DUMP, { .vop_dump = afs_dump },
1445 VOPNAME_DUMPCTL, { .vop_dumpctl = afs_dumpctl },
1446 VOPNAME_DISPOSE, { .vop_dispose = afs_dispose },
1447 VOPNAME_GETSECATTR, { .vop_getsecattr = afs_getsecattr },
1448 VOPNAME_SETSECATTR, { .vop_setsecattr = afs_setsecattr },
1449 VOPNAME_SHRLOCK, { .vop_shrlock = fs_shrlock },
1452 vnodeops_t *afs_ops;
1453 #elif defined(AFS_SUN510_ENV)
1454 /* The following list must always be NULL-terminated */
1455 const fs_operation_def_t afs_vnodeops_template[] = {
1456 VOPNAME_OPEN, gafs_open,
1457 VOPNAME_CLOSE, gafs_close,
1458 VOPNAME_READ, afs_vmread,
1459 VOPNAME_WRITE, afs_vmwrite,
1460 VOPNAME_IOCTL, afs_ioctl,
1461 VOPNAME_SETFL, fs_setfl,
1462 VOPNAME_GETATTR, gafs_getattr,
1463 VOPNAME_SETATTR, gafs_setattr,
1464 VOPNAME_ACCESS, gafs_access,
1465 VOPNAME_LOOKUP, gafs_lookup,
1466 VOPNAME_CREATE, gafs_create,
1467 VOPNAME_REMOVE, gafs_remove,
1468 VOPNAME_LINK, gafs_link,
1469 VOPNAME_RENAME, gafs_rename,
1470 VOPNAME_MKDIR, gafs_mkdir,
1471 VOPNAME_RMDIR, gafs_rmdir,
1472 VOPNAME_READDIR, gafs_readdir,
1473 VOPNAME_SYMLINK, gafs_symlink,
1474 VOPNAME_READLINK, gafs_readlink,
1475 VOPNAME_FSYNC, gafs_fsync,
1476 VOPNAME_INACTIVE, gafs_inactive,
1477 VOPNAME_FID, gafs_fid,
1478 VOPNAME_RWLOCK, afs_rwlock,
1479 VOPNAME_RWUNLOCK, afs_rwunlock,
1480 VOPNAME_SEEK, afs_seek,
1481 VOPNAME_CMP, afs_cmp,
1482 VOPNAME_FRLOCK, afs_frlock,
1483 VOPNAME_SPACE, afs_space,
1484 VOPNAME_REALVP, afs_realvp,
1485 VOPNAME_GETPAGE, afs_getpage,
1486 VOPNAME_PUTPAGE, afs_putpage,
1487 VOPNAME_MAP, afs_map,
1488 VOPNAME_ADDMAP, afs_addmap,
1489 VOPNAME_DELMAP, afs_delmap,
1490 VOPNAME_POLL, fs_poll,
1491 VOPNAME_DUMP, afs_dump,
1492 VOPNAME_PATHCONF, afs_pathconf,
1493 VOPNAME_PAGEIO, afs_pageio,
1494 VOPNAME_DUMPCTL, afs_dumpctl,
1495 VOPNAME_DISPOSE, afs_dispose,
1496 VOPNAME_GETSECATTR, afs_getsecattr,
1497 VOPNAME_SETSECATTR, afs_setsecattr,
1498 VOPNAME_SHRLOCK, fs_shrlock,
1501 struct vnodeops *afs_ops;
1503 struct vnodeops Afs_vnodeops = {
1543 #ifdef AFS_SUN54_ENV
1548 #if defined(AFS_SUN56_ENV)
1552 struct vnodeops *afs_ops = &Afs_vnodeops;
1556 gafs_open(register struct vcache **avcp, afs_int32 aflags,
1562 code = afs_open(avcp, aflags, acred);
1568 gafs_close(register struct vcache *avc, afs_int32 aflags, int count,
1569 offset_t offset, afs_ucred_t *acred)
1574 code = afs_close(avc, aflags, count, offset, acred);
1580 gafs_getattr(register struct vcache *avc, register struct vattr *attrs,
1581 int flags, afs_ucred_t *acred)
1586 code = afs_getattr(avc, attrs, flags, acred);
1593 gafs_setattr(register struct vcache *avc, register struct vattr *attrs,
1594 int flags, afs_ucred_t *acred)
1599 code = afs_setattr(avc, attrs, flags, acred);
1606 gafs_access(register struct vcache *avc, register afs_int32 amode, int flags,
1612 code = afs_access(avc, amode, flags, acred);
1619 gafs_lookup(register struct vcache *adp, char *aname,
1620 register struct vcache **avcp, struct pathname *pnp, int flags,
1621 struct vnode *rdir, afs_ucred_t *acred)
1626 code = afs_lookup(adp, aname, avcp, pnp, flags, rdir, acred);
1633 gafs_create(register struct vcache *adp, char *aname, struct vattr *attrs,
1634 enum vcexcl aexcl, int amode, struct vcache **avcp,
1640 code = afs_create(adp, aname, attrs, aexcl, amode, avcp, acred);
1646 gafs_remove(register struct vcache *adp, char *aname, afs_ucred_t *acred)
1651 code = afs_remove(adp, aname, acred);
1657 gafs_link(register struct vcache *adp, register struct vcache *avc,
1658 char *aname, afs_ucred_t *acred)
1663 code = afs_link(adp, avc, aname, acred);
1669 gafs_rename(register struct vcache *aodp, char *aname1,
1670 register struct vcache *andp, char *aname2,
1676 code = afs_rename(aodp, aname1, andp, aname2, acred);
1677 #ifdef AFS_SUN510_ENV
1679 struct vcache *avcp = NULL;
1681 (void) afs_lookup(andp, aname2, &avcp, NULL, 0, NULL, acred);
1683 struct vnode *vp = AFSTOV(avcp), *pvp = AFSTOV(andp);
1685 mutex_enter(&vp->v_lock);
1686 if (vp->v_path != NULL) {
1687 kmem_free(vp->v_path, strlen(vp->v_path) + 1);
1690 mutex_exit(&vp->v_lock);
1691 vn_setpath(afs_globalVp, pvp, vp, aname2, strlen(aname2));
1702 gafs_mkdir(register struct vcache *adp, char *aname, struct vattr *attrs,
1703 register struct vcache **avcp, afs_ucred_t *acred)
1708 code = afs_mkdir(adp, aname, attrs, avcp, acred);
1714 gafs_rmdir(register struct vcache *adp, char *aname, struct vnode *cdirp,
1720 code = afs_rmdir(adp, aname, cdirp, acred);
1727 gafs_readdir(register struct vcache *avc, struct uio *auio,
1728 afs_ucred_t *acred, int *eofp)
1733 code = afs_readdir(avc, auio, acred, eofp);
1739 gafs_symlink(register struct vcache *adp, char *aname, struct vattr *attrs,
1740 register char *atargetName, afs_ucred_t *acred)
1745 code = afs_symlink(adp, aname, attrs, atargetName, acred);
1752 gafs_readlink(register struct vcache *avc, struct uio *auio, afs_ucred_t *acred)
1757 code = afs_readlink(avc, auio, acred);
1763 #ifdef AFS_SUN53_ENV
1764 gafs_fsync(register struct vcache *avc, int flag, afs_ucred_t *acred)
1766 gafs_fsync(register struct vcache *avc, afs_ucred_t *acred)
1772 #ifdef AFS_SUN53_ENV
1773 code = afs_fsync(avc, flag, acred);
1775 code = afs_fsync(avc, acred);
1782 afs_inactive(struct vcache *avc, afs_ucred_t *acred)
1784 struct vnode *vp = AFSTOV(avc);
1785 if (afs_shuttingdown)
1789 * In Solaris and HPUX s800 and HP-UX10.0 they actually call us with
1790 * v_count 1 on last reference!
1792 mutex_enter(&vp->v_lock);
1793 if (avc->vrefCount <= 0)
1794 osi_Panic("afs_inactive : v_count <=0\n");
1797 * If more than 1 don't unmap the vnode but do decrement the ref count
1800 if (vp->v_count > 0) {
1801 mutex_exit(&vp->v_lock);
1804 mutex_exit(&vp->v_lock);
1807 * Solaris calls VOP_OPEN on exec, but doesn't call VOP_CLOSE when
1808 * the executable exits. So we clean up the open count here.
1810 * Only do this for mvstat 0 vnodes: when using fakestat, we can't
1811 * lose the open count for volume roots (mvstat 2), even though they
1812 * will get VOP_INACTIVE'd when released by afs_PutFakeStat().
1814 if (avc->opens > 0 && avc->mvstat == 0 && !(avc->f.states & CCore))
1815 avc->opens = avc->execsOrWriters = 0;
1817 afs_InactiveVCache(avc, acred);
1819 #ifdef AFS_SUN58_ENV
1820 VFS_RELE(afs_globalVFS);
1827 gafs_inactive(register struct vcache *avc, afs_ucred_t *acred)
1830 (void)afs_inactive(avc, acred);
1836 gafs_fid(struct vcache *avc, struct fid **fidpp)
1841 code = afs_fid(avc, fidpp);
1846 #endif /* AFS_GLOBAL_SUNLOCK */