| 1 | /* |
| 2 | * Copyright 2000, International Business Machines Corporation and others. |
| 3 | * All Rights Reserved. |
| 4 | * |
| 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 |
| 8 | */ |
| 9 | |
| 10 | |
| 11 | /* osi_vm.c implements: |
| 12 | * |
| 13 | * osi_VM_FlushVCache(avc) |
| 14 | * osi_ubc_flush_dirty_and_wait(vp, flags) |
| 15 | * osi_VM_StoreAllSegments(avc) |
| 16 | * osi_VM_TryToSmush(avc, acred, sync) |
| 17 | * osi_VM_FlushPages(avc, credp) |
| 18 | * osi_VM_Truncate(avc, alen, acred) |
| 19 | */ |
| 20 | |
| 21 | #include <afsconfig.h> |
| 22 | #include "afs/param.h" |
| 23 | |
| 24 | #include "afs/sysincludes.h" /* Standard vendor system headers */ |
| 25 | #include "afs/afsincludes.h" /* Afs-based standard headers */ |
| 26 | #include "afs/afs_stats.h" /* statistics */ |
| 27 | |
| 28 | /* Try to discard pages, in order to recycle a vcache entry. |
| 29 | * |
| 30 | * We also make some sanity checks: ref count, open count, held locks. |
| 31 | * |
| 32 | * We also do some non-VM-related chores, such as releasing the cred pointer |
| 33 | * (for AIX and Solaris) and releasing the gnode (for AIX). |
| 34 | * |
| 35 | * Locking: afs_xvcache lock is held. It must not be dropped. |
| 36 | * |
| 37 | * OSF/1 Locking: VN_LOCK has been called. |
| 38 | */ |
| 39 | int |
| 40 | osi_VM_FlushVCache(struct vcache *avc) |
| 41 | { |
| 42 | struct vnode *vp = AFSTOV(avc); |
| 43 | |
| 44 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 45 | printf("%s enter\n", __func__); |
| 46 | } |
| 47 | |
| 48 | if (vp == NULL) { |
| 49 | printf("%s NULL vp\n", __func__); |
| 50 | return 0; |
| 51 | } |
| 52 | |
| 53 | AFS_GUNLOCK(); |
| 54 | cache_purge(vp); |
| 55 | vflushbuf(vp, 1); |
| 56 | AFS_GLOCK(); |
| 57 | |
| 58 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 59 | printf("%s exit\n", __func__); |
| 60 | } |
| 61 | |
| 62 | return 0; |
| 63 | } |
| 64 | |
| 65 | /* Try to store pages to cache, in order to store a file back to the server. |
| 66 | * |
| 67 | * Locking: the vcache entry's lock is held. It will usually be dropped and |
| 68 | * re-obtained. |
| 69 | */ |
| 70 | void |
| 71 | osi_VM_StoreAllSegments(struct vcache *avc) |
| 72 | { |
| 73 | struct vnode *vp; |
| 74 | |
| 75 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 76 | printf("%s enter\n", __func__); |
| 77 | } |
| 78 | |
| 79 | ReleaseWriteLock(&avc->lock); |
| 80 | AFS_GUNLOCK(); |
| 81 | vp = AFSTOV(avc); |
| 82 | mutex_enter(&vp->v_interlock); |
| 83 | VOP_PUTPAGES(vp, 0, 0, PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO); |
| 84 | AFS_GLOCK(); |
| 85 | ObtainWriteLock(&avc->lock, 94); |
| 86 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 87 | printf("%s exit\n", __func__); |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | /* Try to invalidate pages, for "fs flush" or "fs flushv"; or |
| 92 | * try to free pages, when deleting a file. |
| 93 | * |
| 94 | * Locking: the vcache entry's lock is held. It may be dropped and |
| 95 | * re-obtained. |
| 96 | * |
| 97 | * Since we drop and re-obtain the lock, we can't guarantee that there won't |
| 98 | * be some pages around when we return, newly created by concurrent activity. |
| 99 | */ |
| 100 | void |
| 101 | osi_VM_TryToSmush(struct vcache *avc, afs_ucred_t *acred, int sync) |
| 102 | { |
| 103 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 104 | printf("%s enter\n", __func__); |
| 105 | } |
| 106 | |
| 107 | ReleaseWriteLock(&avc->lock); |
| 108 | osi_VM_FlushVCache(avc); |
| 109 | ObtainWriteLock(&avc->lock, 59); |
| 110 | |
| 111 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 112 | printf("%s exit\n", __func__); |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | /* Purge VM for a file when its callback is revoked. |
| 117 | * |
| 118 | * Locking: No lock is held, not even the global lock. |
| 119 | */ |
| 120 | void |
| 121 | osi_VM_FlushPages(struct vcache *avc, afs_ucred_t *credp) |
| 122 | { |
| 123 | struct vnode *vp = AFSTOV(avc); |
| 124 | |
| 125 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 126 | printf("%s enter\n", __func__); |
| 127 | } |
| 128 | |
| 129 | if (!vp) { |
| 130 | printf("%s NULL vp\n", __func__); |
| 131 | return; |
| 132 | } |
| 133 | |
| 134 | cache_purge(vp); |
| 135 | vinvalbuf(vp, 0, credp, curlwp, false, 1); |
| 136 | |
| 137 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 138 | printf("%s exit\n", __func__); |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | /* Purge pages beyond end-of-file, when truncating a file. |
| 143 | * |
| 144 | * Locking: no lock is held, not even the global lock. |
| 145 | * activeV is raised. This is supposed to block pageins, but at present |
| 146 | * it only works on Solaris. |
| 147 | */ |
| 148 | void |
| 149 | osi_VM_Truncate(struct vcache *avc, voff_t alen, afs_ucred_t *acred) |
| 150 | { |
| 151 | struct vnode *vp = AFSTOV(avc); |
| 152 | |
| 153 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 154 | printf("%s enter\n", __func__); |
| 155 | } |
| 156 | |
| 157 | vtruncbuf(vp, alen, false, 0); |
| 158 | |
| 159 | if ((afs_debug & AFSDEB_VNLAYER) != 0) { |
| 160 | printf("%s exit\n", __func__); |
| 161 | } |
| 162 | } |