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 #include "../afs/sysincludes.h" /* Standard vendor system headers */
16 #include "../afs/afsincludes.h" /* Afs-based standard headers */
17 #include "../afs/afs_stats.h" /* statistics */
20 /* Try to discard pages, in order to recycle a vcache entry.
22 * We also make some sanity checks: ref count, open count, held locks.
24 * We also do some non-VM-related chores, such as releasing the cred pointer
25 * (for AIX and Solaris) and releasing the gnode (for AIX).
27 * Locking: afs_xvcache lock is held. If it is dropped and re-acquired,
28 * *slept should be set to warn the caller.
30 * Formerly, afs_xvcache was dropped and re-acquired for Solaris, but now it
31 * is not dropped and re-acquired for any platform. It may be that *slept is
32 * therefore obsolescent.
34 * OSF/1 Locking: VN_LOCK has been called.
37 osi_VM_FlushVCache(avc, slept)
41 struct vnode *vp=(struct vnode *)avc;
42 #ifdef AFS_DARWIN14_ENV
43 if (UBCINFOEXISTS(vp))
52 /* if a lock is held, give up */
53 if (CheckLock(&avc->lock) || afs_CheckBozonLock(&avc->pvnLock))
58 #ifndef AFS_DARWIN14_ENV
59 if (UBCINFOEXISTS(vp))
74 /* Try to store pages to cache, in order to store a file back to the server.
76 * Locking: the vcache entry's lock is held. It will usually be dropped and
80 osi_VM_StoreAllSegments(avc)
83 struct vnode *vp=(struct vnode *)avc;
84 ReleaseWriteLock(&avc->lock);
86 if (UBCINFOEXISTS(vp)) {
90 ObtainWriteLock(&avc->lock,94);
93 /* Try to invalidate pages, for "fs flush" or "fs flushv"; or
94 * try to free pages, when deleting a file.
96 * Locking: the vcache entry's lock is held. It may be dropped and
99 * Since we drop and re-obtain the lock, we can't guarantee that there won't
100 * be some pages around when we return, newly created by concurrent activity.
103 osi_VM_TryToSmush(avc, acred, sync)
105 struct AFS_UCRED *acred;
108 struct vnode *vp=(struct vnode *)avc;
113 ReleaseWriteLock(&avc->lock);
115 if (UBCINFOEXISTS(vp)) {
116 size=ubc_getsize(vp);
117 kret=ubc_invalidate(vp,0,size);
118 if (kret != 1) /* should be KERN_SUCCESS */
119 printf("TryToSmush: invalidate failed (error = %d)\n", kret);
122 ObtainWriteLock(&avc->lock,59);
125 /* Purge VM for a file when its callback is revoked.
127 * Locking: No lock is held, not even the global lock.
129 /* XXX this seems to not be referenced anywhere. *somebody* ought to be calling
130 this, and also making sure that ubc's idea of the filesize is right more
133 osi_VM_FlushPages(avc, credp)
135 struct AFS_UCRED *credp;
137 struct vnode *vp=(struct vnode *)avc;
141 if (UBCINFOEXISTS(vp)) {
142 size=ubc_getsize(vp);
143 kret=ubc_invalidate(vp,0,size);
144 if (kret != 1) /* Should be KERN_SUCCESS */
145 printf("VMFlushPages: invalidate failed (error = %d)\n", kret);
146 /* XXX what about when not CStatd */
147 if (avc->states & CStatd && size != avc->m.Length)
148 ubc_setsize(vp, avc->m.Length);
152 /* Purge pages beyond end-of-file, when truncating a file.
154 * Locking: no lock is held, not even the global lock.
155 * activeV is raised. This is supposed to block pageins, but at present
156 * it only works on Solaris.
159 osi_VM_Truncate(avc, alen, acred)
162 struct AFS_UCRED *acred;
164 struct vnode *vp=(struct vnode *)avc;
165 if (UBCINFOEXISTS(vp)) {
166 ubc_setsize(vp, alen);
170 extern struct AFS_UCRED afs_osi_cred;
171 extern afs_rwlock_t afs_xvcache;
172 /* vnreclaim and vinactive are probably not aggressive enough to keep
173 enough afs vcaches free, so we try to do some of it ourselves */
174 /* XXX there's probably not nearly enough locking here */
175 void osi_VM_TryReclaim(avc, slept)
179 struct proc *p=current_proc();
180 struct vnode *vp=(struct vnode *)avc;
185 VN_HOLD(vp); /* remove from inactive list */
186 if (!simple_lock_try(&vp->v_interlock)) {
190 if (!UBCINFOEXISTS(vp) || vp->v_count != 2) {
191 simple_unlock(&vp->v_interlock);
195 #ifdef AFS_DARWIN14_ENV
196 if (vp->v_ubcinfo->ui_refcount > 1) {
197 simple_unlock(&vp->v_interlock);
202 if (vp->v_ubcinfo->ui_holdcnt) {
203 simple_unlock(&vp->v_interlock);
208 if (slept && ubc_issetflags(vp, UI_WASMAPPED)) {
209 /* We can't possibly release this in time for this NewVCache to get it */
210 simple_unlock(&vp->v_interlock);
215 vp->v_usecount--; /* we want the usecount to be 1 */
218 ReleaseWriteLock(&afs_xvcache);
221 ReleaseReadLock(&afs_xvcache);
224 if (ubc_issetflags(vp, UI_WASMAPPED)) {
225 simple_unlock(&vp->v_interlock);
226 #ifdef AFS_DARWIN14_ENV
227 ubc_release_named(vp);
231 if (ubc_issetflags(vp, UI_HASOBJREF))
232 printf("ubc_release didn't release the reference?!\n");
233 } else if (!vn_lock(vp, LK_EXCLUSIVE|LK_INTERLOCK,current_proc())) {
234 #ifdef AFS_DARWIN14_ENV
235 obj = ubc_getobject(vp,UBC_HOLDOBJECT);
237 #ifdef AFS_DARWIN13_ENV
238 obj = ubc_getobject(vp,(UBC_NOREACTIVATE|UBC_HOLDOBJECT));
240 obj = ubc_getobject(vp);
243 (void)ubc_clean(vp, 1);
244 vinvalbuf(vp, V_SAVE, &afs_osi_cred, p, 0, 0);
245 if (vp->v_usecount == 1)
248 VOP_UNLOCK(vp, 0, p);
250 if (ISSET(vp->v_flag, VTERMINATE))
251 panic("afs_vnreclaim: already teminating");
252 SET(vp->v_flag, VTERMINATE);
253 memory_object_destroy(obj, 0);
254 while (ISSET(vp->v_flag, VTERMINATE)) {
255 SET(vp->v_flag, VTERMWANT);
256 tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "afs_vnreclaim", 0);
260 if (simple_lock_try(&vp->v_interlock))
261 panic("afs_vnreclaim: slept, but did no work :(");
262 if (UBCINFOEXISTS(vp) && vp->v_count == 1) {
264 simple_unlock(&vp->v_interlock);
267 simple_unlock(&vp->v_interlock);
271 ObtainWriteLock(&afs_xvcache,175);
273 ObtainReadLock(&afs_xvcache);
276 void osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size) {
279 struct vcache *avc = (struct vcache *)vp;
281 #ifdef AFS_DARWIN14_ENV
282 offset=trunc_page(offset);
283 size=round_page(size+1);
285 ubc_page_op(vp, (vm_offset_t)offset,
286 UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP,
293 #ifdef AFS_DARWIN13_ENV
294 if (UBCINFOEXISTS(vp))
295 object = ubc_getobject(vp, UBC_NOREACTIVATE);
297 if (UBCINFOEXISTS(vp))
298 object = ubc_getobject(vp);
303 offset=trunc_page(offset);
304 size=round_page(size+1);
306 #ifdef AFS_DARWIN13_ENV
308 memory_object_page_op(object, (vm_offset_t)offset,
309 UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP,
315 /* This is all we can do, and it's not enough. sucks to be us */
316 ubc_setsize(vp, offset);
317 size=(offset + size > avc->m.Length) ? offset + size : avc->m.Length;
318 ubc_setsize(vp, size);
323 int osi_VM_Setup(struct vcache *avc) {
325 struct vnode *vp=(struct vnode *)avc;
327 if (UBCISVALID(vp) && (avc->states & CStatd)) {
328 if (!UBCINFOEXISTS(vp) && !ISSET(vp->v_flag, VTERMINATE)) {
331 if ((error=ubc_info_init(&avc->v))) {
336 #ifndef AFS_DARWIN14_ENV
337 simple_lock(&avc->v.v_interlock);
338 if (!ubc_issetflags(&avc->v, UI_HASOBJREF))
339 #ifdef AFS_DARWIN13_ENV
340 if (ubc_getobject(&avc->v, (UBC_NOREACTIVATE|UBC_HOLDOBJECT)))
341 panic("VM_Setup: null object");
343 (void)_ubc_getobject(&avc->v, 1); /* return value not used */
345 simple_unlock(&avc->v.v_interlock);
350 if (UBCINFOEXISTS(&avc->v))
351 ubc_setsize(&avc->v, avc->m.Length);