Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / DARWIN / osi_vm.c
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 #include <afsconfig.h>
11 #include "afs/param.h"
12
13
14 #include "afs/sysincludes.h" /* Standard vendor system headers */
15 #include "afsincludes.h" /* Afs-based standard headers */
16 #include "afs/afs_stats.h" /* statistics */
17 #include <sys/ubc.h>
18
19 /* Try to discard pages, in order to recycle a vcache entry.
20 *
21 * We also make some sanity checks: ref count, open count, held locks.
22 *
23 * We also do some non-VM-related chores, such as releasing the cred pointer
24 * (for AIX and Solaris) and releasing the gnode (for AIX).
25 *
26 * Locking: afs_xvcache lock is held. It must not be dropped.
27 *
28 * OSF/1 Locking: VN_LOCK has been called.
29 */
30 int
31 osi_VM_FlushVCache(struct vcache *avc)
32 {
33 struct vnode *vp = AFSTOV(avc);
34 kern_return_t kret;
35 off_t size;
36
37 if (!vp)
38 return 0;
39 AFS_GUNLOCK();
40 #if 0
41 if (!(UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp))) {
42 size=ubc_getsize(vp);
43 kret=ubc_invalidate(vp,0,size);
44 }
45 #endif
46 cache_purge(vp);
47 AFS_GLOCK();
48
49 return 0;
50 }
51
52
53 /* Try to store pages to cache, in order to store a file back to the server.
54 *
55 * Locking: the vcache entry's lock is held. It will usually be dropped and
56 * re-obtained.
57 */
58 void
59 osi_VM_StoreAllSegments(struct vcache *avc)
60 {
61 struct vnode *vp = AFSTOV(avc);
62 ReleaseWriteLock(&avc->lock);
63 AFS_GUNLOCK();
64 #ifdef AFS_DARWIN80_ENV
65 ubc_msync_range(vp, 0, ubc_getsize(vp), UBC_SYNC|UBC_PUSHDIRTY);
66 #else
67 if (UBCINFOEXISTS(vp)) {
68 ubc_pushdirty(vp);
69 }
70 #endif
71 AFS_GLOCK();
72 ObtainWriteLock(&avc->lock, 94);
73 }
74
75 /* Try to invalidate pages, for "fs flush" or "fs flushv"; or
76 * try to free pages, when deleting a file.
77 *
78 * Locking: the vcache entry's lock is held. It may be dropped and
79 * re-obtained.
80 *
81 * Since we drop and re-obtain the lock, we can't guarantee that there won't
82 * be some pages around when we return, newly created by concurrent activity.
83 */
84 void
85 osi_VM_TryToSmush(struct vcache *avc, afs_ucred_t *acred, int sync)
86 {
87 struct vnode *vp = AFSTOV(avc);
88 void *object;
89 kern_return_t kret;
90 off_t size, lastpg;
91
92 ReleaseWriteLock(&avc->lock);
93 AFS_GUNLOCK();
94 #ifdef AFS_DARWIN80_ENV
95 ubc_msync_range(vp, 0, ubc_getsize(vp), UBC_INVALIDATE);
96 #else
97 if (UBCINFOEXISTS(vp)) {
98 size = ubc_getsize(vp);
99 kret = ubc_invalidate(vp, 0, size);
100 if (kret != 1) /* should be KERN_SUCCESS */
101 printf("TryToSmush: invalidate failed (error = %d)\n", kret);
102 }
103 #endif
104 AFS_GLOCK();
105 ObtainWriteLock(&avc->lock, 59);
106 }
107
108 /* Purge VM for a file when its callback is revoked.
109 *
110 * Locking: No lock is held, not even the global lock.
111 */
112 /* XXX this seems to not be referenced anywhere. *somebody* ought to be calling
113 this, and also making sure that ubc's idea of the filesize is right more
114 often */
115 void
116 osi_VM_FlushPages(struct vcache *avc, afs_ucred_t *credp)
117 {
118 struct vnode *vp = AFSTOV(avc);
119 void *object;
120 kern_return_t kret;
121 off_t size;
122 #ifdef AFS_DARWIN80_ENV
123 size = ubc_getsize(vp);
124 ubc_msync_range(vp, 0, size, UBC_INVALIDATE);
125 /* XXX what about when not CStatd */
126 if (avc->f.states & CStatd && size != avc->f.m.Length)
127 ubc_setsize(vp, avc->f.m.Length);
128 #else
129 if (UBCINFOEXISTS(vp)) {
130 size = ubc_getsize(vp);
131 kret = ubc_invalidate(vp, 0, size);
132 if (kret != 1) /* Should be KERN_SUCCESS */
133 printf("VMFlushPages: invalidate failed (error = %d)\n", kret);
134 /* XXX what about when not CStatd */
135 if (avc->f.states & CStatd && size != avc->f.m.Length)
136 if (UBCISVALID(vp))
137 ubc_setsize(vp, avc->f.m.Length);
138 }
139 #endif
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, int alen, afs_ucred_t *acred)
150 {
151 struct vnode *vp = AFSTOV(avc);
152 #ifdef AFS_DARWIN80_ENV
153 ubc_setsize(vp, alen);
154 #else
155 if (UBCINFOEXISTS(vp) && UBCISVALID(vp)) {
156 ubc_setsize(vp, alen);
157 }
158 #endif
159 }
160
161 void
162 osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size)
163 {
164 #if 0
165 void *object;
166 struct vcache *avc = VTOAFS(vp);
167
168 offset = trunc_page(offset);
169 size = round_page(size + 1);
170 while (size) {
171 ubc_page_op(vp, (vm_offset_t) offset,
172 UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP, 0, 0);
173 size -= PAGE_SIZE;
174 offset += PAGE_SIZE;
175 }
176 #endif
177 }
178
179 int
180 osi_VM_Setup(struct vcache *avc, int force)
181 {
182 int error;
183 struct vnode *vp = AFSTOV(avc);
184
185 #ifndef AFS_DARWIN80_ENV
186 if (UBCISVALID(vp) && ((avc->f.states & CStatd) || force)) {
187 if (!UBCINFOEXISTS(vp)) {
188 osi_vnhold(avc, 0);
189 avc->f.states |= CUBCinit;
190 AFS_GUNLOCK();
191 if ((error = ubc_info_init(vp))) {
192 AFS_GLOCK();
193 avc->f.states &= ~CUBCinit;
194 AFS_RELE(vp);
195 return error;
196 }
197 AFS_GLOCK();
198 avc->f.states &= ~CUBCinit;
199 AFS_RELE(vp);
200 }
201 if (UBCINFOEXISTS(vp) && UBCISVALID(vp)) {
202 ubc_setsize(vp, avc->f.m.Length);
203 }
204 }
205 #endif
206 return 0;
207 }