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 #include "afs/sysincludes.h" /* Standard vendor system headers */
17 #include "afsincludes.h" /* Afs-based standard headers */
18 #include "afs/afs_stats.h" /* statistics */
19 #include "sys/flock.h" /* for IGN_PID */
21 extern struct vnodeops Afs_vnodeops;
23 /* Try to discard pages, in order to recycle a vcache entry.
25 * We also make some sanity checks: ref count, open count, held locks.
27 * We also do some non-VM-related chores, such as releasing the cred pointer
28 * (for AIX and Solaris) and releasing the gnode (for AIX).
30 * Locking: afs_xvcache lock is held. If it is dropped and re-acquired,
31 * *slept should be set to warn the caller.
33 * Formerly, afs_xvcache was dropped and re-acquired for Solaris, but now it
34 * is not dropped and re-acquired for any platform. It may be that *slept is
35 * therefore obsolescent.
38 osi_VM_FlushVCache(struct vcache *avc, int *slept)
41 vnode_t *vp = &avc->v;
43 if (avc->vrefCount != 0)
50 * Just in case someone is still referring to the vnode we give up
51 * trying to get rid of this guy.
53 if (CheckLock(&avc->lock) || LockWaiters(&avc->lock))
59 * we just need to avoid the race
60 * in vn_rele between the ref count going to 0 and VOP_INACTIVE
62 * Note that although we checked vcount above, we didn't have the lock
64 if (vp->v_count > 0 || (vp->v_flag & VINACT)) {
71 * Since we store on last close and on VOP_INACTIVE
72 * there should be NO dirty pages
73 * Note that we hold the xvcache lock the entire time.
76 PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
79 /* afs_chkpgoob will drop and re-acquire the global lock. */
81 osi_Assert(!VN_GET_PGCNT(vp));
82 osi_Assert(!AFS_VN_MAPPED(vp));
83 osi_Assert(!AFS_VN_DIRTY(&avc->v));
85 #if defined(AFS_SGI65_ENV)
87 cleanlocks(vp, IGN_PID, 0);
88 mutex_destroy(&vp->v_filocksem);
89 #else /* AFS_SGI65_ENV */
90 if (vp->v_filocksem) {
93 cleanlocks(vp, &curprocp->p_flid);
95 cleanlocks(vp, IGN_PID, 0);
97 osi_Assert(vp->v_filocks == NULL);
98 mutex_destroy(vp->v_filocksem);
99 kmem_free(vp->v_filocksem, sizeof *vp->v_filocksem);
100 vp->v_filocksem = NULL;
102 #endif /* AFS_SGI65_ENV */
105 osi_Panic("flushVcache: vm race");
108 vnode_pcache_reclaim(vp); /* this can sleep */
109 vnode_pcache_free(vp);
110 if (vp->v_op != &Afs_vnodeops) {
111 VOP_RECLAIM(vp, FSYNC_WAIT, code);
116 ktrace_free(vp->v_trace);
117 #endif /* VNODE_TRACING */
118 vn_bhv_remove(VN_BHV_HEAD(vp), &(avc->vc_bhv_desc));
119 vn_bhv_head_destroy(&(vp->v_bh));
120 destroy_bitlock(&vp->v_pcacheflag);
121 mutex_destroy(&vp->v_buf_lock);
123 bhv_remove(VN_BHV_HEAD(vp), &(avc->vc_bhv_desc));
124 bhv_head_destroy(&(vp->v_bh));
126 vp->v_flag = 0; /* debug */
127 #if defined(DEBUG) && defined(VNODE_INIT_BITLOCK)
128 destroy_bitlock(&vp->v_flag);
131 AFS_VN_DESTROY_BUF_LOCK(vp);
133 #endif /* AFS_SGI64_ENV */
138 /* Try to invalidate pages, for "fs flush" or "fs flushv"; or
139 * try to free pages, when deleting a file.
141 * Locking: the vcache entry's lock is held. It may be dropped and
144 * Since we drop and re-obtain the lock, we can't guarantee that there won't
145 * be some pages around when we return, newly created by concurrent activity.
148 osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
150 ReleaseWriteLock(&avc->lock);
152 /* current remapf restriction - cannot have VOP_RWLOCK */
153 osi_Assert(OSI_GET_LOCKID() != avc->vc_rwlockid);
154 if (((vnode_t *) avc)->v_type == VREG && AFS_VN_MAPPED(((vnode_t *) avc)))
155 remapf(((vnode_t *) avc), 0, 0);
156 PTOSSVP(AFSTOV(avc), (off_t) 0, (off_t) MAXLONG);
158 ObtainWriteLock(&avc->lock, 62);
161 /* Flush and invalidate pages, for fsync() with INVAL flag
163 * Locking: only the global lock is held.
166 osi_VM_FSyncInval(struct vcache *avc)
169 PFLUSHINVALVP((vnode_t *) avc, (off_t) 0, (off_t) avc->f.m.Length);
173 /* Try to store pages to cache, in order to store a file back to the server.
175 * Locking: the vcache entry's lock is held. It will usually be dropped and
179 osi_VM_StoreAllSegments(struct vcache *avc)
182 osi_Assert(valusema(&avc->vc_rwlock) <= 0);
183 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
184 osi_Assert(avc->vrefCount > 0);
185 ReleaseWriteLock(&avc->lock);
186 /* We may call back into AFS via:
187 * pflushvp->chunkpush->do_pdflush->mp_afs_bmap
191 /* Write out dirty pages list to avoid B_DELWRI buffers. */
192 while (VN_GET_DPAGES((vnode_t *) avc)) {
193 pdflush(AFSTOV(avc), 0);
196 PFLUSHVP(AFSTOV(avc), (off_t) avc->f.m.Length, (off_t) 0, error);
200 * If this fails (due to quota overage, etc.)
201 * what can we do?? we need to sure that
202 * that the VM cache is cleared of dirty pages
203 * We note that pinvalfree ignores write errors & otherwise
204 * does what we want (we don't use this normally since
205 * it also unhashes pages ..)
207 PINVALFREE((vnode_t *) avc, avc->f.m.Length);
209 ObtainWriteLock(&avc->lock, 121);
210 if (error && avc->f.m.LinkCount)
212 "AFS:Failed to push back pages for vnode 0x%x error %d (from afs_StoreOnLastReference)",
216 /* Purge VM for a file when its callback is revoked.
218 * Locking: No lock is held, not even the global lock.
221 osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
223 vnode_t *vp = (vnode_t *) avc;
225 remapf(vp, /*avc->f.m.Length */ 0, 0);
227 /* Used to grab locks and recheck avc->f.m.DataVersion and
228 * avc->execsOrWriters here, but we have to drop locks before calling
229 * ptossvp() anyway, so why bother.
233 * ptossvp tosses all pages associated with this vnode
234 * All in-use pages are marked BAD
236 PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
239 /* Purge pages beyond end-of-file, when truncating a file.
241 * Locking: no lock is held, not even the global lock.
242 * activeV is raised. This is supposed to block pageins, but at present
243 * it only works on Solaris.
246 osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
248 PTOSSVP(&avc->v, (off_t) alen, (off_t) MAXLONG);