Tue Aug 4 23:31:57 2009 UTC ()
uvm_vnp_zerorange() logically and by implementation more a part of
ubc than uvm_vnode, so move it over.


(pooka)
diff -r1.66 -r1.67 src/sys/uvm/uvm_bio.c
diff -r1.91 -r1.92 src/sys/uvm/uvm_vnode.c

cvs diff -r1.66 -r1.67 src/sys/uvm/uvm_bio.c (switch to unified diff)

--- src/sys/uvm/uvm_bio.c 2008/11/27 08:46:09 1.66
+++ src/sys/uvm/uvm_bio.c 2009/08/04 23:31:57 1.67
@@ -1,698 +1,728 @@ @@ -1,698 +1,728 @@
1/* $NetBSD: uvm_bio.c,v 1.66 2008/11/27 08:46:09 pooka Exp $ */ 1/* $NetBSD: uvm_bio.c,v 1.67 2009/08/04 23:31:57 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1998 Chuck Silvers. 4 * Copyright (c) 1998 Chuck Silvers.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products 15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission. 16 * derived from this software without specific prior written permission.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE. 28 * SUCH DAMAGE.
29 * 29 *
30 */ 30 */
31 31
32/* 32/*
33 * uvm_bio.c: buffered i/o object mapping cache 33 * uvm_bio.c: buffered i/o object mapping cache
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.66 2008/11/27 08:46:09 pooka Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.67 2009/08/04 23:31:57 pooka Exp $");
38 38
39#include "opt_uvmhist.h" 39#include "opt_uvmhist.h"
40#include "opt_ubc.h" 40#include "opt_ubc.h"
41 41
42#include <sys/param.h> 42#include <sys/param.h>
43#include <sys/systm.h> 43#include <sys/systm.h>
44#include <sys/kmem.h> 44#include <sys/kmem.h>
45#include <sys/kernel.h> 45#include <sys/kernel.h>
46#include <sys/proc.h> 46#include <sys/proc.h>
 47#include <sys/vnode.h>
47 48
48#include <uvm/uvm.h> 49#include <uvm/uvm.h>
49 50
50/* 51/*
51 * global data structures 52 * global data structures
52 */ 53 */
53 54
54/* 55/*
55 * local functions 56 * local functions
56 */ 57 */
57 58
58static int ubc_fault(struct uvm_faultinfo *, vaddr_t, struct vm_page **, 59static int ubc_fault(struct uvm_faultinfo *, vaddr_t, struct vm_page **,
59 int, int, vm_prot_t, int); 60 int, int, vm_prot_t, int);
60static struct ubc_map *ubc_find_mapping(struct uvm_object *, voff_t); 61static struct ubc_map *ubc_find_mapping(struct uvm_object *, voff_t);
61 62
62/* 63/*
63 * local data structues 64 * local data structues
64 */ 65 */
65 66
66#define UBC_HASH(uobj, offset) \ 67#define UBC_HASH(uobj, offset) \
67 (((((u_long)(uobj)) >> 8) + (((u_long)(offset)) >> PAGE_SHIFT)) & \ 68 (((((u_long)(uobj)) >> 8) + (((u_long)(offset)) >> PAGE_SHIFT)) & \
68 ubc_object.hashmask) 69 ubc_object.hashmask)
69 70
70#define UBC_QUEUE(offset) \ 71#define UBC_QUEUE(offset) \
71 (&ubc_object.inactive[(((u_long)(offset)) >> ubc_winshift) & \ 72 (&ubc_object.inactive[(((u_long)(offset)) >> ubc_winshift) & \
72 (UBC_NQUEUES - 1)]) 73 (UBC_NQUEUES - 1)])
73 74
74#define UBC_UMAP_ADDR(u) \ 75#define UBC_UMAP_ADDR(u) \
75 (vaddr_t)(ubc_object.kva + (((u) - ubc_object.umap) << ubc_winshift)) 76 (vaddr_t)(ubc_object.kva + (((u) - ubc_object.umap) << ubc_winshift))
76 77
77 78
78#define UMAP_PAGES_LOCKED 0x0001 79#define UMAP_PAGES_LOCKED 0x0001
79#define UMAP_MAPPING_CACHED 0x0002 80#define UMAP_MAPPING_CACHED 0x0002
80 81
81struct ubc_map 82struct ubc_map
82{ 83{
83 struct uvm_object * uobj; /* mapped object */ 84 struct uvm_object * uobj; /* mapped object */
84 voff_t offset; /* offset into uobj */ 85 voff_t offset; /* offset into uobj */
85 voff_t writeoff; /* write offset */ 86 voff_t writeoff; /* write offset */
86 vsize_t writelen; /* write len */ 87 vsize_t writelen; /* write len */
87 int refcount; /* refcount on mapping */ 88 int refcount; /* refcount on mapping */
88 int flags; /* extra state */ 89 int flags; /* extra state */
89 int advice; 90 int advice;
90 91
91 LIST_ENTRY(ubc_map) hash; /* hash table */ 92 LIST_ENTRY(ubc_map) hash; /* hash table */
92 TAILQ_ENTRY(ubc_map) inactive; /* inactive queue */ 93 TAILQ_ENTRY(ubc_map) inactive; /* inactive queue */
93}; 94};
94 95
95static struct ubc_object 96static struct ubc_object
96{ 97{
97 struct uvm_object uobj; /* glue for uvm_map() */ 98 struct uvm_object uobj; /* glue for uvm_map() */
98 char *kva; /* where ubc_object is mapped */ 99 char *kva; /* where ubc_object is mapped */
99 struct ubc_map *umap; /* array of ubc_map's */ 100 struct ubc_map *umap; /* array of ubc_map's */
100 101
101 LIST_HEAD(, ubc_map) *hash; /* hashtable for cached ubc_map's */ 102 LIST_HEAD(, ubc_map) *hash; /* hashtable for cached ubc_map's */
102 u_long hashmask; /* mask for hashtable */ 103 u_long hashmask; /* mask for hashtable */
103 104
104 TAILQ_HEAD(ubc_inactive_head, ubc_map) *inactive; 105 TAILQ_HEAD(ubc_inactive_head, ubc_map) *inactive;
105 /* inactive queues for ubc_map's */ 106 /* inactive queues for ubc_map's */
106 107
107} ubc_object; 108} ubc_object;
108 109
109const struct uvm_pagerops ubc_pager = { 110const struct uvm_pagerops ubc_pager = {
110 .pgo_fault = ubc_fault, 111 .pgo_fault = ubc_fault,
111 /* ... rest are NULL */ 112 /* ... rest are NULL */
112}; 113};
113 114
114int ubc_nwins = UBC_NWINS; 115int ubc_nwins = UBC_NWINS;
115int ubc_winshift = UBC_WINSHIFT; 116int ubc_winshift = UBC_WINSHIFT;
116int ubc_winsize; 117int ubc_winsize;
117#if defined(PMAP_PREFER) 118#if defined(PMAP_PREFER)
118int ubc_nqueues; 119int ubc_nqueues;
119#define UBC_NQUEUES ubc_nqueues 120#define UBC_NQUEUES ubc_nqueues
120#else 121#else
121#define UBC_NQUEUES 1 122#define UBC_NQUEUES 1
122#endif 123#endif
123 124
124#if defined(UBC_STATS) 125#if defined(UBC_STATS)
125 126
126#define UBC_EVCNT_DEFINE(name) \ 127#define UBC_EVCNT_DEFINE(name) \
127struct evcnt ubc_evcnt_##name = \ 128struct evcnt ubc_evcnt_##name = \
128EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "ubc", #name); \ 129EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "ubc", #name); \
129EVCNT_ATTACH_STATIC(ubc_evcnt_##name); 130EVCNT_ATTACH_STATIC(ubc_evcnt_##name);
130#define UBC_EVCNT_INCR(name) ubc_evcnt_##name.ev_count++ 131#define UBC_EVCNT_INCR(name) ubc_evcnt_##name.ev_count++
131 132
132#else /* defined(UBC_STATS) */ 133#else /* defined(UBC_STATS) */
133 134
134#define UBC_EVCNT_DEFINE(name) /* nothing */ 135#define UBC_EVCNT_DEFINE(name) /* nothing */
135#define UBC_EVCNT_INCR(name) /* nothing */ 136#define UBC_EVCNT_INCR(name) /* nothing */
136 137
137#endif /* defined(UBC_STATS) */ 138#endif /* defined(UBC_STATS) */
138 139
139UBC_EVCNT_DEFINE(wincachehit) 140UBC_EVCNT_DEFINE(wincachehit)
140UBC_EVCNT_DEFINE(wincachemiss) 141UBC_EVCNT_DEFINE(wincachemiss)
141UBC_EVCNT_DEFINE(faultbusy) 142UBC_EVCNT_DEFINE(faultbusy)
142 143
143/* 144/*
144 * ubc_init 145 * ubc_init
145 * 146 *
146 * init pager private data structures. 147 * init pager private data structures.
147 */ 148 */
148 149
149void 150void
150ubc_init(void) 151ubc_init(void)
151{ 152{
152 struct ubc_map *umap; 153 struct ubc_map *umap;
153 vaddr_t va; 154 vaddr_t va;
154 int i; 155 int i;
155 156
156 /* 157 /*
157 * Make sure ubc_winshift is sane. 158 * Make sure ubc_winshift is sane.
158 */ 159 */
159 if (ubc_winshift < PAGE_SHIFT) 160 if (ubc_winshift < PAGE_SHIFT)
160 ubc_winshift = PAGE_SHIFT; 161 ubc_winshift = PAGE_SHIFT;
161 162
162 /* 163 /*
163 * init ubc_object. 164 * init ubc_object.
164 * alloc and init ubc_map's. 165 * alloc and init ubc_map's.
165 * init inactive queues. 166 * init inactive queues.
166 * alloc and init hashtable. 167 * alloc and init hashtable.
167 * map in ubc_object. 168 * map in ubc_object.
168 */ 169 */
169 170
170 UVM_OBJ_INIT(&ubc_object.uobj, &ubc_pager, UVM_OBJ_KERN); 171 UVM_OBJ_INIT(&ubc_object.uobj, &ubc_pager, UVM_OBJ_KERN);
171 172
172 ubc_object.umap = kmem_zalloc(ubc_nwins * sizeof(struct ubc_map), 173 ubc_object.umap = kmem_zalloc(ubc_nwins * sizeof(struct ubc_map),
173 KM_SLEEP); 174 KM_SLEEP);
174 if (ubc_object.umap == NULL) 175 if (ubc_object.umap == NULL)
175 panic("ubc_init: failed to allocate ubc_map"); 176 panic("ubc_init: failed to allocate ubc_map");
176 177
177 if (ubc_winshift < PAGE_SHIFT) { 178 if (ubc_winshift < PAGE_SHIFT) {
178 ubc_winshift = PAGE_SHIFT; 179 ubc_winshift = PAGE_SHIFT;
179 } 180 }
180 va = (vaddr_t)1L; 181 va = (vaddr_t)1L;
181#ifdef PMAP_PREFER 182#ifdef PMAP_PREFER
182 PMAP_PREFER(0, &va, 0, 0); /* kernel is never topdown */ 183 PMAP_PREFER(0, &va, 0, 0); /* kernel is never topdown */
183 ubc_nqueues = va >> ubc_winshift; 184 ubc_nqueues = va >> ubc_winshift;
184 if (ubc_nqueues == 0) { 185 if (ubc_nqueues == 0) {
185 ubc_nqueues = 1; 186 ubc_nqueues = 1;
186 } 187 }
187#endif 188#endif
188 ubc_winsize = 1 << ubc_winshift; 189 ubc_winsize = 1 << ubc_winshift;
189 ubc_object.inactive = kmem_alloc(UBC_NQUEUES * 190 ubc_object.inactive = kmem_alloc(UBC_NQUEUES *
190 sizeof(struct ubc_inactive_head), KM_SLEEP); 191 sizeof(struct ubc_inactive_head), KM_SLEEP);
191 if (ubc_object.inactive == NULL) 192 if (ubc_object.inactive == NULL)
192 panic("ubc_init: failed to allocate inactive queue heads"); 193 panic("ubc_init: failed to allocate inactive queue heads");
193 for (i = 0; i < UBC_NQUEUES; i++) { 194 for (i = 0; i < UBC_NQUEUES; i++) {
194 TAILQ_INIT(&ubc_object.inactive[i]); 195 TAILQ_INIT(&ubc_object.inactive[i]);
195 } 196 }
196 for (i = 0; i < ubc_nwins; i++) { 197 for (i = 0; i < ubc_nwins; i++) {
197 umap = &ubc_object.umap[i]; 198 umap = &ubc_object.umap[i];
198 TAILQ_INSERT_TAIL(&ubc_object.inactive[i & (UBC_NQUEUES - 1)], 199 TAILQ_INSERT_TAIL(&ubc_object.inactive[i & (UBC_NQUEUES - 1)],
199 umap, inactive); 200 umap, inactive);
200 } 201 }
201 202
202 ubc_object.hash = hashinit(ubc_nwins, HASH_LIST, true, 203 ubc_object.hash = hashinit(ubc_nwins, HASH_LIST, true,
203 &ubc_object.hashmask); 204 &ubc_object.hashmask);
204 for (i = 0; i <= ubc_object.hashmask; i++) { 205 for (i = 0; i <= ubc_object.hashmask; i++) {
205 LIST_INIT(&ubc_object.hash[i]); 206 LIST_INIT(&ubc_object.hash[i]);
206 } 207 }
207 208
208 if (uvm_map(kernel_map, (vaddr_t *)&ubc_object.kva, 209 if (uvm_map(kernel_map, (vaddr_t *)&ubc_object.kva,
209 ubc_nwins << ubc_winshift, &ubc_object.uobj, 0, (vsize_t)va, 210 ubc_nwins << ubc_winshift, &ubc_object.uobj, 0, (vsize_t)va,
210 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_NONE, 211 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_NONE,
211 UVM_ADV_RANDOM, UVM_FLAG_NOMERGE)) != 0) { 212 UVM_ADV_RANDOM, UVM_FLAG_NOMERGE)) != 0) {
212 panic("ubc_init: failed to map ubc_object"); 213 panic("ubc_init: failed to map ubc_object");
213 } 214 }
214 UVMHIST_INIT(ubchist, 300); 215 UVMHIST_INIT(ubchist, 300);
215} 216}
216 217
217/* 218/*
218 * ubc_fault: fault routine for ubc mapping 219 * ubc_fault: fault routine for ubc mapping
219 */ 220 */
220 221
221static int 222static int
222ubc_fault(struct uvm_faultinfo *ufi, vaddr_t ign1, struct vm_page **ign2, 223ubc_fault(struct uvm_faultinfo *ufi, vaddr_t ign1, struct vm_page **ign2,
223 int ign3, int ign4, vm_prot_t access_type, int flags) 224 int ign3, int ign4, vm_prot_t access_type, int flags)
224{ 225{
225 struct uvm_object *uobj; 226 struct uvm_object *uobj;
226 struct ubc_map *umap; 227 struct ubc_map *umap;
227 vaddr_t va, eva, ubc_offset, slot_offset; 228 vaddr_t va, eva, ubc_offset, slot_offset;
228 int i, error, npages; 229 int i, error, npages;
229 struct vm_page *pgs[ubc_winsize >> PAGE_SHIFT], *pg; 230 struct vm_page *pgs[ubc_winsize >> PAGE_SHIFT], *pg;
230 vm_prot_t prot; 231 vm_prot_t prot;
231 UVMHIST_FUNC("ubc_fault"); UVMHIST_CALLED(ubchist); 232 UVMHIST_FUNC("ubc_fault"); UVMHIST_CALLED(ubchist);
232 233
233 /* 234 /*
234 * no need to try with PGO_LOCKED... 235 * no need to try with PGO_LOCKED...
235 * we don't need to have the map locked since we know that 236 * we don't need to have the map locked since we know that
236 * no one will mess with it until our reference is released. 237 * no one will mess with it until our reference is released.
237 */ 238 */
238 239
239 if (flags & PGO_LOCKED) { 240 if (flags & PGO_LOCKED) {
240 uvmfault_unlockall(ufi, NULL, &ubc_object.uobj, NULL); 241 uvmfault_unlockall(ufi, NULL, &ubc_object.uobj, NULL);
241 flags &= ~PGO_LOCKED; 242 flags &= ~PGO_LOCKED;
242 } 243 }
243 244
244 va = ufi->orig_rvaddr; 245 va = ufi->orig_rvaddr;
245 ubc_offset = va - (vaddr_t)ubc_object.kva; 246 ubc_offset = va - (vaddr_t)ubc_object.kva;
246 umap = &ubc_object.umap[ubc_offset >> ubc_winshift]; 247 umap = &ubc_object.umap[ubc_offset >> ubc_winshift];
247 KASSERT(umap->refcount != 0); 248 KASSERT(umap->refcount != 0);
248 KASSERT((umap->flags & UMAP_PAGES_LOCKED) == 0); 249 KASSERT((umap->flags & UMAP_PAGES_LOCKED) == 0);
249 slot_offset = ubc_offset & (ubc_winsize - 1); 250 slot_offset = ubc_offset & (ubc_winsize - 1);
250 251
251 /* 252 /*
252 * some platforms cannot write to individual bytes atomically, so 253 * some platforms cannot write to individual bytes atomically, so
253 * software has to do read/modify/write of larger quantities instead. 254 * software has to do read/modify/write of larger quantities instead.
254 * this means that the access_type for "write" operations 255 * this means that the access_type for "write" operations
255 * can be VM_PROT_READ, which confuses us mightily. 256 * can be VM_PROT_READ, which confuses us mightily.
256 * 257 *
257 * deal with this by resetting access_type based on the info 258 * deal with this by resetting access_type based on the info
258 * that ubc_alloc() stores for us. 259 * that ubc_alloc() stores for us.
259 */ 260 */
260 261
261 access_type = umap->writelen ? VM_PROT_WRITE : VM_PROT_READ; 262 access_type = umap->writelen ? VM_PROT_WRITE : VM_PROT_READ;
262 UVMHIST_LOG(ubchist, "va 0x%lx ubc_offset 0x%lx access_type %d", 263 UVMHIST_LOG(ubchist, "va 0x%lx ubc_offset 0x%lx access_type %d",
263 va, ubc_offset, access_type, 0); 264 va, ubc_offset, access_type, 0);
264 265
265#ifdef DIAGNOSTIC 266#ifdef DIAGNOSTIC
266 if ((access_type & VM_PROT_WRITE) != 0) { 267 if ((access_type & VM_PROT_WRITE) != 0) {
267 if (slot_offset < trunc_page(umap->writeoff) || 268 if (slot_offset < trunc_page(umap->writeoff) ||
268 umap->writeoff + umap->writelen <= slot_offset) { 269 umap->writeoff + umap->writelen <= slot_offset) {
269 panic("ubc_fault: out of range write"); 270 panic("ubc_fault: out of range write");
270 } 271 }
271 } 272 }
272#endif 273#endif
273 274
274 /* no umap locking needed since we have a ref on the umap */ 275 /* no umap locking needed since we have a ref on the umap */
275 uobj = umap->uobj; 276 uobj = umap->uobj;
276 277
277 if ((access_type & VM_PROT_WRITE) == 0) { 278 if ((access_type & VM_PROT_WRITE) == 0) {
278 npages = (ubc_winsize - slot_offset) >> PAGE_SHIFT; 279 npages = (ubc_winsize - slot_offset) >> PAGE_SHIFT;
279 } else { 280 } else {
280 npages = (round_page(umap->offset + umap->writeoff + 281 npages = (round_page(umap->offset + umap->writeoff +
281 umap->writelen) - (umap->offset + slot_offset)) 282 umap->writelen) - (umap->offset + slot_offset))
282 >> PAGE_SHIFT; 283 >> PAGE_SHIFT;
283 flags |= PGO_PASTEOF; 284 flags |= PGO_PASTEOF;
284 } 285 }
285 286
286again: 287again:
287 memset(pgs, 0, sizeof (pgs)); 288 memset(pgs, 0, sizeof (pgs));
288 mutex_enter(&uobj->vmobjlock); 289 mutex_enter(&uobj->vmobjlock);
289 290
290 UVMHIST_LOG(ubchist, "slot_offset 0x%x writeoff 0x%x writelen 0x%x ", 291 UVMHIST_LOG(ubchist, "slot_offset 0x%x writeoff 0x%x writelen 0x%x ",
291 slot_offset, umap->writeoff, umap->writelen, 0); 292 slot_offset, umap->writeoff, umap->writelen, 0);
292 UVMHIST_LOG(ubchist, "getpages uobj %p offset 0x%x npages %d", 293 UVMHIST_LOG(ubchist, "getpages uobj %p offset 0x%x npages %d",
293 uobj, umap->offset + slot_offset, npages, 0); 294 uobj, umap->offset + slot_offset, npages, 0);
294 295
295 error = (*uobj->pgops->pgo_get)(uobj, umap->offset + slot_offset, pgs, 296 error = (*uobj->pgops->pgo_get)(uobj, umap->offset + slot_offset, pgs,
296 &npages, 0, access_type, umap->advice, flags | PGO_NOBLOCKALLOC | 297 &npages, 0, access_type, umap->advice, flags | PGO_NOBLOCKALLOC |
297 PGO_NOTIMESTAMP); 298 PGO_NOTIMESTAMP);
298 UVMHIST_LOG(ubchist, "getpages error %d npages %d", error, npages, 0, 299 UVMHIST_LOG(ubchist, "getpages error %d npages %d", error, npages, 0,
299 0); 300 0);
300 301
301 if (error == EAGAIN) { 302 if (error == EAGAIN) {
302 kpause("ubc_fault", false, hz, NULL); 303 kpause("ubc_fault", false, hz, NULL);
303 goto again; 304 goto again;
304 } 305 }
305 if (error) { 306 if (error) {
306 return error; 307 return error;
307 } 308 }
308 309
309 va = ufi->orig_rvaddr; 310 va = ufi->orig_rvaddr;
310 eva = ufi->orig_rvaddr + (npages << PAGE_SHIFT); 311 eva = ufi->orig_rvaddr + (npages << PAGE_SHIFT);
311 312
312 UVMHIST_LOG(ubchist, "va 0x%lx eva 0x%lx", va, eva, 0, 0); 313 UVMHIST_LOG(ubchist, "va 0x%lx eva 0x%lx", va, eva, 0, 0);
313 for (i = 0; va < eva; i++, va += PAGE_SIZE) { 314 for (i = 0; va < eva; i++, va += PAGE_SIZE) {
314 bool rdonly; 315 bool rdonly;
315 vm_prot_t mask; 316 vm_prot_t mask;
316 317
317 /* 318 /*
318 * for virtually-indexed, virtually-tagged caches we should 319 * for virtually-indexed, virtually-tagged caches we should
319 * avoid creating writable mappings when we don't absolutely 320 * avoid creating writable mappings when we don't absolutely
320 * need them, since the "compatible alias" trick doesn't work 321 * need them, since the "compatible alias" trick doesn't work
321 * on such caches. otherwise, we can always map the pages 322 * on such caches. otherwise, we can always map the pages
322 * writable. 323 * writable.
323 */ 324 */
324 325
325#ifdef PMAP_CACHE_VIVT 326#ifdef PMAP_CACHE_VIVT
326 prot = VM_PROT_READ | access_type; 327 prot = VM_PROT_READ | access_type;
327#else 328#else
328 prot = VM_PROT_READ | VM_PROT_WRITE; 329 prot = VM_PROT_READ | VM_PROT_WRITE;
329#endif 330#endif
330 UVMHIST_LOG(ubchist, "pgs[%d] = %p", i, pgs[i], 0, 0); 331 UVMHIST_LOG(ubchist, "pgs[%d] = %p", i, pgs[i], 0, 0);
331 pg = pgs[i]; 332 pg = pgs[i];
332 333
333 if (pg == NULL || pg == PGO_DONTCARE) { 334 if (pg == NULL || pg == PGO_DONTCARE) {
334 continue; 335 continue;
335 } 336 }
336 337
337 uobj = pg->uobject; 338 uobj = pg->uobject;
338 mutex_enter(&uobj->vmobjlock); 339 mutex_enter(&uobj->vmobjlock);
339 if (pg->flags & PG_WANTED) { 340 if (pg->flags & PG_WANTED) {
340 wakeup(pg); 341 wakeup(pg);
341 } 342 }
342 KASSERT((pg->flags & PG_FAKE) == 0); 343 KASSERT((pg->flags & PG_FAKE) == 0);
343 if (pg->flags & PG_RELEASED) { 344 if (pg->flags & PG_RELEASED) {
344 mutex_enter(&uvm_pageqlock); 345 mutex_enter(&uvm_pageqlock);
345 uvm_pagefree(pg); 346 uvm_pagefree(pg);
346 mutex_exit(&uvm_pageqlock); 347 mutex_exit(&uvm_pageqlock);
347 mutex_exit(&uobj->vmobjlock); 348 mutex_exit(&uobj->vmobjlock);
348 continue; 349 continue;
349 } 350 }
350 if (pg->loan_count != 0) { 351 if (pg->loan_count != 0) {
351 352
352 /* 353 /*
353 * avoid unneeded loan break if possible. 354 * avoid unneeded loan break if possible.
354 */ 355 */
355 356
356 if ((access_type & VM_PROT_WRITE) == 0) 357 if ((access_type & VM_PROT_WRITE) == 0)
357 prot &= ~VM_PROT_WRITE; 358 prot &= ~VM_PROT_WRITE;
358 359
359 if (prot & VM_PROT_WRITE) { 360 if (prot & VM_PROT_WRITE) {
360 struct vm_page *newpg; 361 struct vm_page *newpg;
361 362
362 newpg = uvm_loanbreak(pg); 363 newpg = uvm_loanbreak(pg);
363 if (newpg == NULL) { 364 if (newpg == NULL) {
364 uvm_page_unbusy(&pg, 1); 365 uvm_page_unbusy(&pg, 1);
365 mutex_exit(&uobj->vmobjlock); 366 mutex_exit(&uobj->vmobjlock);
366 uvm_wait("ubc_loanbrk"); 367 uvm_wait("ubc_loanbrk");
367 continue; /* will re-fault */ 368 continue; /* will re-fault */
368 } 369 }
369 pg = newpg; 370 pg = newpg;
370 } 371 }
371 } 372 }
372 373
373 /* 374 /*
374 * note that a page whose backing store is partially allocated 375 * note that a page whose backing store is partially allocated
375 * is marked as PG_RDONLY. 376 * is marked as PG_RDONLY.
376 */ 377 */
377 378
378 rdonly = ((access_type & VM_PROT_WRITE) == 0 && 379 rdonly = ((access_type & VM_PROT_WRITE) == 0 &&
379 (pg->flags & PG_RDONLY) != 0) || 380 (pg->flags & PG_RDONLY) != 0) ||
380 UVM_OBJ_NEEDS_WRITEFAULT(uobj); 381 UVM_OBJ_NEEDS_WRITEFAULT(uobj);
381 KASSERT((pg->flags & PG_RDONLY) == 0 || 382 KASSERT((pg->flags & PG_RDONLY) == 0 ||
382 (access_type & VM_PROT_WRITE) == 0 || 383 (access_type & VM_PROT_WRITE) == 0 ||
383 pg->offset < umap->writeoff || 384 pg->offset < umap->writeoff ||
384 pg->offset + PAGE_SIZE > umap->writeoff + umap->writelen); 385 pg->offset + PAGE_SIZE > umap->writeoff + umap->writelen);
385 mask = rdonly ? ~VM_PROT_WRITE : VM_PROT_ALL; 386 mask = rdonly ? ~VM_PROT_WRITE : VM_PROT_ALL;
386 error = pmap_enter(ufi->orig_map->pmap, va, VM_PAGE_TO_PHYS(pg), 387 error = pmap_enter(ufi->orig_map->pmap, va, VM_PAGE_TO_PHYS(pg),
387 prot & mask, PMAP_CANFAIL | (access_type & mask)); 388 prot & mask, PMAP_CANFAIL | (access_type & mask));
388 mutex_enter(&uvm_pageqlock); 389 mutex_enter(&uvm_pageqlock);
389 uvm_pageactivate(pg); 390 uvm_pageactivate(pg);
390 mutex_exit(&uvm_pageqlock); 391 mutex_exit(&uvm_pageqlock);
391 pg->flags &= ~(PG_BUSY|PG_WANTED); 392 pg->flags &= ~(PG_BUSY|PG_WANTED);
392 UVM_PAGE_OWN(pg, NULL); 393 UVM_PAGE_OWN(pg, NULL);
393 mutex_exit(&uobj->vmobjlock); 394 mutex_exit(&uobj->vmobjlock);
394 if (error) { 395 if (error) {
395 UVMHIST_LOG(ubchist, "pmap_enter fail %d", 396 UVMHIST_LOG(ubchist, "pmap_enter fail %d",
396 error, 0, 0, 0); 397 error, 0, 0, 0);
397 uvm_wait("ubc_pmfail"); 398 uvm_wait("ubc_pmfail");
398 /* will refault */ 399 /* will refault */
399 } 400 }
400 } 401 }
401 pmap_update(ufi->orig_map->pmap); 402 pmap_update(ufi->orig_map->pmap);
402 return 0; 403 return 0;
403} 404}
404 405
405/* 406/*
406 * local functions 407 * local functions
407 */ 408 */
408 409
409static struct ubc_map * 410static struct ubc_map *
410ubc_find_mapping(struct uvm_object *uobj, voff_t offset) 411ubc_find_mapping(struct uvm_object *uobj, voff_t offset)
411{ 412{
412 struct ubc_map *umap; 413 struct ubc_map *umap;
413 414
414 LIST_FOREACH(umap, &ubc_object.hash[UBC_HASH(uobj, offset)], hash) { 415 LIST_FOREACH(umap, &ubc_object.hash[UBC_HASH(uobj, offset)], hash) {
415 if (umap->uobj == uobj && umap->offset == offset) { 416 if (umap->uobj == uobj && umap->offset == offset) {
416 return umap; 417 return umap;
417 } 418 }
418 } 419 }
419 return NULL; 420 return NULL;
420} 421}
421 422
422 423
423/* 424/*
424 * ubc interface functions 425 * ubc interface functions
425 */ 426 */
426 427
427/* 428/*
428 * ubc_alloc: allocate a file mapping window 429 * ubc_alloc: allocate a file mapping window
429 */ 430 */
430 431
431void * 432void *
432ubc_alloc(struct uvm_object *uobj, voff_t offset, vsize_t *lenp, int advice, 433ubc_alloc(struct uvm_object *uobj, voff_t offset, vsize_t *lenp, int advice,
433 int flags) 434 int flags)
434{ 435{
435 vaddr_t slot_offset, va; 436 vaddr_t slot_offset, va;
436 struct ubc_map *umap; 437 struct ubc_map *umap;
437 voff_t umap_offset; 438 voff_t umap_offset;
438 int error; 439 int error;
439 UVMHIST_FUNC("ubc_alloc"); UVMHIST_CALLED(ubchist); 440 UVMHIST_FUNC("ubc_alloc"); UVMHIST_CALLED(ubchist);
440 441
441 UVMHIST_LOG(ubchist, "uobj %p offset 0x%lx len 0x%lx", 442 UVMHIST_LOG(ubchist, "uobj %p offset 0x%lx len 0x%lx",
442 uobj, offset, *lenp, 0); 443 uobj, offset, *lenp, 0);
443 444
444 KASSERT(*lenp > 0); 445 KASSERT(*lenp > 0);
445 umap_offset = (offset & ~((voff_t)ubc_winsize - 1)); 446 umap_offset = (offset & ~((voff_t)ubc_winsize - 1));
446 slot_offset = (vaddr_t)(offset & ((voff_t)ubc_winsize - 1)); 447 slot_offset = (vaddr_t)(offset & ((voff_t)ubc_winsize - 1));
447 *lenp = MIN(*lenp, ubc_winsize - slot_offset); 448 *lenp = MIN(*lenp, ubc_winsize - slot_offset);
448 449
449 /* 450 /*
450 * the object is always locked here, so we don't need to add a ref. 451 * the object is always locked here, so we don't need to add a ref.
451 */ 452 */
452 453
453again: 454again:
454 mutex_enter(&ubc_object.uobj.vmobjlock); 455 mutex_enter(&ubc_object.uobj.vmobjlock);
455 umap = ubc_find_mapping(uobj, umap_offset); 456 umap = ubc_find_mapping(uobj, umap_offset);
456 if (umap == NULL) { 457 if (umap == NULL) {
457 UBC_EVCNT_INCR(wincachemiss); 458 UBC_EVCNT_INCR(wincachemiss);
458 umap = TAILQ_FIRST(UBC_QUEUE(offset)); 459 umap = TAILQ_FIRST(UBC_QUEUE(offset));
459 if (umap == NULL) { 460 if (umap == NULL) {
460 mutex_exit(&ubc_object.uobj.vmobjlock); 461 mutex_exit(&ubc_object.uobj.vmobjlock);
461 kpause("ubc_alloc", false, hz, NULL); 462 kpause("ubc_alloc", false, hz, NULL);
462 goto again; 463 goto again;
463 } 464 }
464 465
465 /* 466 /*
466 * remove from old hash (if any), add to new hash. 467 * remove from old hash (if any), add to new hash.
467 */ 468 */
468 469
469 if (umap->uobj != NULL) { 470 if (umap->uobj != NULL) {
470 LIST_REMOVE(umap, hash); 471 LIST_REMOVE(umap, hash);
471 } 472 }
472 umap->uobj = uobj; 473 umap->uobj = uobj;
473 umap->offset = umap_offset; 474 umap->offset = umap_offset;
474 LIST_INSERT_HEAD(&ubc_object.hash[UBC_HASH(uobj, umap_offset)], 475 LIST_INSERT_HEAD(&ubc_object.hash[UBC_HASH(uobj, umap_offset)],
475 umap, hash); 476 umap, hash);
476 va = UBC_UMAP_ADDR(umap); 477 va = UBC_UMAP_ADDR(umap);
477 if (umap->flags & UMAP_MAPPING_CACHED) { 478 if (umap->flags & UMAP_MAPPING_CACHED) {
478 umap->flags &= ~UMAP_MAPPING_CACHED; 479 umap->flags &= ~UMAP_MAPPING_CACHED;
479 pmap_remove(pmap_kernel(), va, va + ubc_winsize); 480 pmap_remove(pmap_kernel(), va, va + ubc_winsize);
480 pmap_update(pmap_kernel()); 481 pmap_update(pmap_kernel());
481 } 482 }
482 } else { 483 } else {
483 UBC_EVCNT_INCR(wincachehit); 484 UBC_EVCNT_INCR(wincachehit);
484 va = UBC_UMAP_ADDR(umap); 485 va = UBC_UMAP_ADDR(umap);
485 } 486 }
486 487
487 if (umap->refcount == 0) { 488 if (umap->refcount == 0) {
488 TAILQ_REMOVE(UBC_QUEUE(offset), umap, inactive); 489 TAILQ_REMOVE(UBC_QUEUE(offset), umap, inactive);
489 } 490 }
490 491
491#ifdef DIAGNOSTIC 492#ifdef DIAGNOSTIC
492 if ((flags & UBC_WRITE) && (umap->writeoff || umap->writelen)) { 493 if ((flags & UBC_WRITE) && (umap->writeoff || umap->writelen)) {
493 panic("ubc_alloc: concurrent writes uobj %p", uobj); 494 panic("ubc_alloc: concurrent writes uobj %p", uobj);
494 } 495 }
495#endif 496#endif
496 if (flags & UBC_WRITE) { 497 if (flags & UBC_WRITE) {
497 umap->writeoff = slot_offset; 498 umap->writeoff = slot_offset;
498 umap->writelen = *lenp; 499 umap->writelen = *lenp;
499 } 500 }
500 501
501 umap->refcount++; 502 umap->refcount++;
502 umap->advice = advice; 503 umap->advice = advice;
503 mutex_exit(&ubc_object.uobj.vmobjlock); 504 mutex_exit(&ubc_object.uobj.vmobjlock);
504 UVMHIST_LOG(ubchist, "umap %p refs %d va %p flags 0x%x", 505 UVMHIST_LOG(ubchist, "umap %p refs %d va %p flags 0x%x",
505 umap, umap->refcount, va, flags); 506 umap, umap->refcount, va, flags);
506 507
507 if (flags & UBC_FAULTBUSY) { 508 if (flags & UBC_FAULTBUSY) {
508 int npages = (*lenp + PAGE_SIZE - 1) >> PAGE_SHIFT; 509 int npages = (*lenp + PAGE_SIZE - 1) >> PAGE_SHIFT;
509 struct vm_page *pgs[npages]; 510 struct vm_page *pgs[npages];
510 int gpflags = 511 int gpflags =
511 PGO_SYNCIO|PGO_OVERWRITE|PGO_PASTEOF|PGO_NOBLOCKALLOC| 512 PGO_SYNCIO|PGO_OVERWRITE|PGO_PASTEOF|PGO_NOBLOCKALLOC|
512 PGO_NOTIMESTAMP; 513 PGO_NOTIMESTAMP;
513 int i; 514 int i;
514 KDASSERT(flags & UBC_WRITE); 515 KDASSERT(flags & UBC_WRITE);
515 KASSERT(umap->refcount == 1); 516 KASSERT(umap->refcount == 1);
516 517
517 UBC_EVCNT_INCR(faultbusy); 518 UBC_EVCNT_INCR(faultbusy);
518 if (umap->flags & UMAP_MAPPING_CACHED) { 519 if (umap->flags & UMAP_MAPPING_CACHED) {
519 umap->flags &= ~UMAP_MAPPING_CACHED; 520 umap->flags &= ~UMAP_MAPPING_CACHED;
520 pmap_remove(pmap_kernel(), va, va + ubc_winsize); 521 pmap_remove(pmap_kernel(), va, va + ubc_winsize);
521 } 522 }
522again_faultbusy: 523again_faultbusy:
523 memset(pgs, 0, sizeof(pgs)); 524 memset(pgs, 0, sizeof(pgs));
524 mutex_enter(&uobj->vmobjlock); 525 mutex_enter(&uobj->vmobjlock);
525 error = (*uobj->pgops->pgo_get)(uobj, trunc_page(offset), pgs, 526 error = (*uobj->pgops->pgo_get)(uobj, trunc_page(offset), pgs,
526 &npages, 0, VM_PROT_READ | VM_PROT_WRITE, advice, gpflags); 527 &npages, 0, VM_PROT_READ | VM_PROT_WRITE, advice, gpflags);
527 UVMHIST_LOG(ubchist, "faultbusy getpages %d", error, 0, 0, 0); 528 UVMHIST_LOG(ubchist, "faultbusy getpages %d", error, 0, 0, 0);
528 if (error) { 529 if (error) {
529 goto out; 530 goto out;
530 } 531 }
531 for (i = 0; i < npages; i++) { 532 for (i = 0; i < npages; i++) {
532 struct vm_page *pg = pgs[i]; 533 struct vm_page *pg = pgs[i];
533 534
534 KASSERT(pg->uobject == uobj); 535 KASSERT(pg->uobject == uobj);
535 if (pg->loan_count != 0) { 536 if (pg->loan_count != 0) {
536 mutex_enter(&uobj->vmobjlock); 537 mutex_enter(&uobj->vmobjlock);
537 if (pg->loan_count != 0) { 538 if (pg->loan_count != 0) {
538 pg = uvm_loanbreak(pg); 539 pg = uvm_loanbreak(pg);
539 } 540 }
540 mutex_exit(&uobj->vmobjlock); 541 mutex_exit(&uobj->vmobjlock);
541 if (pg == NULL) { 542 if (pg == NULL) {
542 pmap_kremove(va, ubc_winsize); 543 pmap_kremove(va, ubc_winsize);
543 pmap_update(pmap_kernel()); 544 pmap_update(pmap_kernel());
544 mutex_enter(&uobj->vmobjlock); 545 mutex_enter(&uobj->vmobjlock);
545 uvm_page_unbusy(pgs, npages); 546 uvm_page_unbusy(pgs, npages);
546 mutex_exit(&uobj->vmobjlock); 547 mutex_exit(&uobj->vmobjlock);
547 uvm_wait("ubc_alloc"); 548 uvm_wait("ubc_alloc");
548 goto again_faultbusy; 549 goto again_faultbusy;
549 } 550 }
550 pgs[i] = pg; 551 pgs[i] = pg;
551 } 552 }
552 pmap_kenter_pa(va + slot_offset + (i << PAGE_SHIFT), 553 pmap_kenter_pa(va + slot_offset + (i << PAGE_SHIFT),
553 VM_PAGE_TO_PHYS(pg), VM_PROT_READ | VM_PROT_WRITE); 554 VM_PAGE_TO_PHYS(pg), VM_PROT_READ | VM_PROT_WRITE);
554 } 555 }
555 pmap_update(pmap_kernel()); 556 pmap_update(pmap_kernel());
556 umap->flags |= UMAP_PAGES_LOCKED; 557 umap->flags |= UMAP_PAGES_LOCKED;
557 } else { 558 } else {
558 KASSERT((umap->flags & UMAP_PAGES_LOCKED) == 0); 559 KASSERT((umap->flags & UMAP_PAGES_LOCKED) == 0);
559 } 560 }
560 561
561out: 562out:
562 return (void *)(va + slot_offset); 563 return (void *)(va + slot_offset);
563} 564}
564 565
565/* 566/*
566 * ubc_release: free a file mapping window. 567 * ubc_release: free a file mapping window.
567 */ 568 */
568 569
569void 570void
570ubc_release(void *va, int flags) 571ubc_release(void *va, int flags)
571{ 572{
572 struct ubc_map *umap; 573 struct ubc_map *umap;
573 struct uvm_object *uobj; 574 struct uvm_object *uobj;
574 vaddr_t umapva; 575 vaddr_t umapva;
575 bool unmapped; 576 bool unmapped;
576 UVMHIST_FUNC("ubc_release"); UVMHIST_CALLED(ubchist); 577 UVMHIST_FUNC("ubc_release"); UVMHIST_CALLED(ubchist);
577 578
578 UVMHIST_LOG(ubchist, "va %p", va, 0, 0, 0); 579 UVMHIST_LOG(ubchist, "va %p", va, 0, 0, 0);
579 umap = &ubc_object.umap[((char *)va - ubc_object.kva) >> ubc_winshift]; 580 umap = &ubc_object.umap[((char *)va - ubc_object.kva) >> ubc_winshift];
580 umapva = UBC_UMAP_ADDR(umap); 581 umapva = UBC_UMAP_ADDR(umap);
581 uobj = umap->uobj; 582 uobj = umap->uobj;
582 KASSERT(uobj != NULL); 583 KASSERT(uobj != NULL);
583 584
584 if (umap->flags & UMAP_PAGES_LOCKED) { 585 if (umap->flags & UMAP_PAGES_LOCKED) {
585 int slot_offset = umap->writeoff; 586 int slot_offset = umap->writeoff;
586 int endoff = umap->writeoff + umap->writelen; 587 int endoff = umap->writeoff + umap->writelen;
587 int zerolen = round_page(endoff) - endoff; 588 int zerolen = round_page(endoff) - endoff;
588 int npages = (int)(round_page(umap->writeoff + umap->writelen) 589 int npages = (int)(round_page(umap->writeoff + umap->writelen)
589 - trunc_page(umap->writeoff)) >> PAGE_SHIFT; 590 - trunc_page(umap->writeoff)) >> PAGE_SHIFT;
590 struct vm_page *pgs[npages]; 591 struct vm_page *pgs[npages];
591 paddr_t pa; 592 paddr_t pa;
592 int i; 593 int i;
593 bool rv; 594 bool rv;
594 595
595 KASSERT((umap->flags & UMAP_MAPPING_CACHED) == 0); 596 KASSERT((umap->flags & UMAP_MAPPING_CACHED) == 0);
596 if (zerolen) { 597 if (zerolen) {
597 memset((char *)umapva + endoff, 0, zerolen); 598 memset((char *)umapva + endoff, 0, zerolen);
598 } 599 }
599 umap->flags &= ~UMAP_PAGES_LOCKED; 600 umap->flags &= ~UMAP_PAGES_LOCKED;
600 mutex_enter(&uvm_pageqlock); 601 mutex_enter(&uvm_pageqlock);
601 for (i = 0; i < npages; i++) { 602 for (i = 0; i < npages; i++) {
602 rv = pmap_extract(pmap_kernel(), 603 rv = pmap_extract(pmap_kernel(),
603 umapva + slot_offset + (i << PAGE_SHIFT), &pa); 604 umapva + slot_offset + (i << PAGE_SHIFT), &pa);
604 KASSERT(rv); 605 KASSERT(rv);
605 pgs[i] = PHYS_TO_VM_PAGE(pa); 606 pgs[i] = PHYS_TO_VM_PAGE(pa);
606 pgs[i]->flags &= ~(PG_FAKE|PG_CLEAN); 607 pgs[i]->flags &= ~(PG_FAKE|PG_CLEAN);
607 KASSERT(pgs[i]->loan_count == 0); 608 KASSERT(pgs[i]->loan_count == 0);
608 uvm_pageactivate(pgs[i]); 609 uvm_pageactivate(pgs[i]);
609 } 610 }
610 mutex_exit(&uvm_pageqlock); 611 mutex_exit(&uvm_pageqlock);
611 pmap_kremove(umapva, ubc_winsize); 612 pmap_kremove(umapva, ubc_winsize);
612 pmap_update(pmap_kernel()); 613 pmap_update(pmap_kernel());
613 mutex_enter(&uobj->vmobjlock); 614 mutex_enter(&uobj->vmobjlock);
614 uvm_page_unbusy(pgs, npages); 615 uvm_page_unbusy(pgs, npages);
615 mutex_exit(&uobj->vmobjlock); 616 mutex_exit(&uobj->vmobjlock);
616 unmapped = true; 617 unmapped = true;
617 } else { 618 } else {
618 unmapped = false; 619 unmapped = false;
619 } 620 }
620 621
621 mutex_enter(&ubc_object.uobj.vmobjlock); 622 mutex_enter(&ubc_object.uobj.vmobjlock);
622 umap->writeoff = 0; 623 umap->writeoff = 0;
623 umap->writelen = 0; 624 umap->writelen = 0;
624 umap->refcount--; 625 umap->refcount--;
625 if (umap->refcount == 0) { 626 if (umap->refcount == 0) {
626 if (flags & UBC_UNMAP) { 627 if (flags & UBC_UNMAP) {
627 628
628 /* 629 /*
629 * Invalidate any cached mappings if requested. 630 * Invalidate any cached mappings if requested.
630 * This is typically used to avoid leaving 631 * This is typically used to avoid leaving
631 * incompatible cache aliases around indefinitely. 632 * incompatible cache aliases around indefinitely.
632 */ 633 */
633 634
634 pmap_remove(pmap_kernel(), umapva, 635 pmap_remove(pmap_kernel(), umapva,
635 umapva + ubc_winsize); 636 umapva + ubc_winsize);
636 umap->flags &= ~UMAP_MAPPING_CACHED; 637 umap->flags &= ~UMAP_MAPPING_CACHED;
637 pmap_update(pmap_kernel()); 638 pmap_update(pmap_kernel());
638 LIST_REMOVE(umap, hash); 639 LIST_REMOVE(umap, hash);
639 umap->uobj = NULL; 640 umap->uobj = NULL;
640 TAILQ_INSERT_HEAD(UBC_QUEUE(umap->offset), umap, 641 TAILQ_INSERT_HEAD(UBC_QUEUE(umap->offset), umap,
641 inactive); 642 inactive);
642 } else { 643 } else {
643 if (!unmapped) { 644 if (!unmapped) {
644 umap->flags |= UMAP_MAPPING_CACHED; 645 umap->flags |= UMAP_MAPPING_CACHED;
645 } 646 }
646 TAILQ_INSERT_TAIL(UBC_QUEUE(umap->offset), umap, 647 TAILQ_INSERT_TAIL(UBC_QUEUE(umap->offset), umap,
647 inactive); 648 inactive);
648 } 649 }
649 } 650 }
650 UVMHIST_LOG(ubchist, "umap %p refs %d", umap, umap->refcount, 0, 0); 651 UVMHIST_LOG(ubchist, "umap %p refs %d", umap, umap->refcount, 0, 0);
651 mutex_exit(&ubc_object.uobj.vmobjlock); 652 mutex_exit(&ubc_object.uobj.vmobjlock);
652} 653}
653 654
654/* 655/*
655 * ubc_uiomove: move data to/from an object. 656 * ubc_uiomove: move data to/from an object.
656 */ 657 */
657 658
658int 659int
659ubc_uiomove(struct uvm_object *uobj, struct uio *uio, vsize_t todo, int advice, 660ubc_uiomove(struct uvm_object *uobj, struct uio *uio, vsize_t todo, int advice,
660 int flags) 661 int flags)
661{ 662{
662 voff_t off; 663 voff_t off;
663 const bool overwrite = (flags & UBC_FAULTBUSY) != 0; 664 const bool overwrite = (flags & UBC_FAULTBUSY) != 0;
664 int error; 665 int error;
665 666
666 KASSERT(todo <= uio->uio_resid); 667 KASSERT(todo <= uio->uio_resid);
667 KASSERT(((flags & UBC_WRITE) != 0 && uio->uio_rw == UIO_WRITE) || 668 KASSERT(((flags & UBC_WRITE) != 0 && uio->uio_rw == UIO_WRITE) ||
668 ((flags & UBC_READ) != 0 && uio->uio_rw == UIO_READ)); 669 ((flags & UBC_READ) != 0 && uio->uio_rw == UIO_READ));
669 670
670 off = uio->uio_offset; 671 off = uio->uio_offset;
671 error = 0; 672 error = 0;
672 while (todo > 0) { 673 while (todo > 0) {
673 vsize_t bytelen = todo; 674 vsize_t bytelen = todo;
674 void *win; 675 void *win;
675 676
676 win = ubc_alloc(uobj, off, &bytelen, advice, flags); 677 win = ubc_alloc(uobj, off, &bytelen, advice, flags);
677 if (error == 0) { 678 if (error == 0) {
678 error = uiomove(win, bytelen, uio); 679 error = uiomove(win, bytelen, uio);
679 } 680 }
680 if (error != 0 && overwrite) { 681 if (error != 0 && overwrite) {
681 /* 682 /*
682 * if we haven't initialized the pages yet, 683 * if we haven't initialized the pages yet,
683 * do it now. it's safe to use memset here 684 * do it now. it's safe to use memset here
684 * because we just mapped the pages above. 685 * because we just mapped the pages above.
685 */ 686 */
686 printf("%s: error=%d\n", __func__, error); 687 printf("%s: error=%d\n", __func__, error);
687 memset(win, 0, bytelen); 688 memset(win, 0, bytelen);
688 } 689 }
689 ubc_release(win, flags); 690 ubc_release(win, flags);
690 off += bytelen; 691 off += bytelen;
691 todo -= bytelen; 692 todo -= bytelen;
692 if (error != 0 && (flags & UBC_PARTIALOK) != 0) { 693 if (error != 0 && (flags & UBC_PARTIALOK) != 0) {
693 break; 694 break;
694 } 695 }
695 } 696 }
696 697
697 return error; 698 return error;
698} 699}
 700
 701
 702/*
 703 * uvm_vnp_zerorange: set a range of bytes in a file to zero.
 704 */
 705
 706void
 707uvm_vnp_zerorange(struct vnode *vp, off_t off, size_t len)
 708{
 709 void *win;
 710 int flags;
 711
 712 /*
 713 * XXXUBC invent kzero() and use it
 714 */
 715
 716 while (len) {
 717 vsize_t bytelen = len;
 718
 719 win = ubc_alloc(&vp->v_uobj, off, &bytelen, UVM_ADV_NORMAL,
 720 UBC_WRITE);
 721 memset(win, 0, bytelen);
 722 flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0;
 723 ubc_release(win, flags);
 724
 725 off += bytelen;
 726 len -= bytelen;
 727 }
 728}

cvs diff -r1.91 -r1.92 src/sys/uvm/uvm_vnode.c (switch to unified diff)

--- src/sys/uvm/uvm_vnode.c 2009/08/04 23:03:01 1.91
+++ src/sys/uvm/uvm_vnode.c 2009/08/04 23:31:57 1.92
@@ -1,426 +1,398 @@ @@ -1,426 +1,398 @@
1/* $NetBSD: uvm_vnode.c,v 1.91 2009/08/04 23:03:01 pooka Exp $ */ 1/* $NetBSD: uvm_vnode.c,v 1.92 2009/08/04 23:31:57 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1997 Charles D. Cranor and Washington University. 4 * Copyright (c) 1997 Charles D. Cranor and Washington University.
5 * Copyright (c) 1991, 1993 5 * Copyright (c) 1991, 1993
6 * The Regents of the University of California. 6 * The Regents of the University of California.
7 * Copyright (c) 1990 University of Utah. 7 * Copyright (c) 1990 University of Utah.
8 * 8 *
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * This code is derived from software contributed to Berkeley by 11 * This code is derived from software contributed to Berkeley by
12 * the Systems Programming Group of the University of Utah Computer 12 * the Systems Programming Group of the University of Utah Computer
13 * Science Department. 13 * Science Department.
14 * 14 *
15 * Redistribution and use in source and binary forms, with or without 15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions 16 * modification, are permitted provided that the following conditions
17 * are met: 17 * are met:
18 * 1. Redistributions of source code must retain the above copyright 18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer. 19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright 20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the 21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution. 22 * documentation and/or other materials provided with the distribution.
23 * 3. All advertising materials mentioning features or use of this software 23 * 3. All advertising materials mentioning features or use of this software
24 * must display the following acknowledgement: 24 * must display the following acknowledgement:
25 * This product includes software developed by Charles D. Cranor, 25 * This product includes software developed by Charles D. Cranor,
26 * Washington University, the University of California, Berkeley and 26 * Washington University, the University of California, Berkeley and
27 * its contributors. 27 * its contributors.
28 * 4. Neither the name of the University nor the names of its contributors 28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software 29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission. 30 * without specific prior written permission.
31 * 31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * SUCH DAMAGE. 42 * SUCH DAMAGE.
43 * 43 *
44 * @(#)vnode_pager.c 8.8 (Berkeley) 2/13/94 44 * @(#)vnode_pager.c 8.8 (Berkeley) 2/13/94
45 * from: Id: uvm_vnode.c,v 1.1.2.26 1998/02/02 20:38:07 chuck Exp 45 * from: Id: uvm_vnode.c,v 1.1.2.26 1998/02/02 20:38:07 chuck Exp
46 */ 46 */
47 47
48/* 48/*
49 * uvm_vnode.c: the vnode pager. 49 * uvm_vnode.c: the vnode pager.
50 */ 50 */
51 51
52#include <sys/cdefs.h> 52#include <sys/cdefs.h>
53__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.91 2009/08/04 23:03:01 pooka Exp $"); 53__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.92 2009/08/04 23:31:57 pooka Exp $");
54 54
55#include "opt_uvmhist.h" 55#include "opt_uvmhist.h"
56 56
57#include <sys/param.h> 57#include <sys/param.h>
58#include <sys/systm.h> 58#include <sys/systm.h>
59#include <sys/kernel.h> 59#include <sys/kernel.h>
60#include <sys/proc.h> 60#include <sys/proc.h>
61#include <sys/malloc.h> 61#include <sys/malloc.h>
62#include <sys/vnode.h> 62#include <sys/vnode.h>
63#include <sys/disklabel.h> 63#include <sys/disklabel.h>
64#include <sys/ioctl.h> 64#include <sys/ioctl.h>
65#include <sys/fcntl.h> 65#include <sys/fcntl.h>
66#include <sys/conf.h> 66#include <sys/conf.h>
67#include <sys/pool.h> 67#include <sys/pool.h>
68#include <sys/mount.h> 68#include <sys/mount.h>
69 69
70#include <miscfs/specfs/specdev.h> 70#include <miscfs/specfs/specdev.h>
71 71
72#include <uvm/uvm.h> 72#include <uvm/uvm.h>
73#include <uvm/uvm_readahead.h> 73#include <uvm/uvm_readahead.h>
74 74
75/* 75/*
76 * functions 76 * functions
77 */ 77 */
78 78
79static void uvn_detach(struct uvm_object *); 79static void uvn_detach(struct uvm_object *);
80static int uvn_get(struct uvm_object *, voff_t, struct vm_page **, int *, 80static int uvn_get(struct uvm_object *, voff_t, struct vm_page **, int *,
81 int, vm_prot_t, int, int); 81 int, vm_prot_t, int, int);
82static int uvn_put(struct uvm_object *, voff_t, voff_t, int); 82static int uvn_put(struct uvm_object *, voff_t, voff_t, int);
83static void uvn_reference(struct uvm_object *); 83static void uvn_reference(struct uvm_object *);
84 84
85static int uvn_findpage(struct uvm_object *, voff_t, struct vm_page **, 85static int uvn_findpage(struct uvm_object *, voff_t, struct vm_page **,
86 int); 86 int);
87 87
88/* 88/*
89 * master pager structure 89 * master pager structure
90 */ 90 */
91 91
92const struct uvm_pagerops uvm_vnodeops = { 92const struct uvm_pagerops uvm_vnodeops = {
93 .pgo_reference = uvn_reference, 93 .pgo_reference = uvn_reference,
94 .pgo_detach = uvn_detach, 94 .pgo_detach = uvn_detach,
95 .pgo_get = uvn_get, 95 .pgo_get = uvn_get,
96 .pgo_put = uvn_put, 96 .pgo_put = uvn_put,
97}; 97};
98 98
99/* 99/*
100 * the ops! 100 * the ops!
101 */ 101 */
102 102
103/* 103/*
104 * uvn_reference 104 * uvn_reference
105 * 105 *
106 * duplicate a reference to a VM object. Note that the reference 106 * duplicate a reference to a VM object. Note that the reference
107 * count must already be at least one (the passed in reference) so 107 * count must already be at least one (the passed in reference) so
108 * there is no chance of the uvn being killed or locked out here. 108 * there is no chance of the uvn being killed or locked out here.
109 * 109 *
110 * => caller must call with object unlocked. 110 * => caller must call with object unlocked.
111 * => caller must be using the same accessprot as was used at attach time 111 * => caller must be using the same accessprot as was used at attach time
112 */ 112 */
113 113
114static void 114static void
115uvn_reference(struct uvm_object *uobj) 115uvn_reference(struct uvm_object *uobj)
116{ 116{
117 VREF((struct vnode *)uobj); 117 VREF((struct vnode *)uobj);
118} 118}
119 119
120 120
121/* 121/*
122 * uvn_detach 122 * uvn_detach
123 * 123 *
124 * remove a reference to a VM object. 124 * remove a reference to a VM object.
125 * 125 *
126 * => caller must call with object unlocked and map locked. 126 * => caller must call with object unlocked and map locked.
127 */ 127 */
128 128
129static void 129static void
130uvn_detach(struct uvm_object *uobj) 130uvn_detach(struct uvm_object *uobj)
131{ 131{
132 vrele((struct vnode *)uobj); 132 vrele((struct vnode *)uobj);
133} 133}
134 134
135/* 135/*
136 * uvn_put: flush page data to backing store. 136 * uvn_put: flush page data to backing store.
137 * 137 *
138 * => object must be locked on entry! VOP_PUTPAGES must unlock it. 138 * => object must be locked on entry! VOP_PUTPAGES must unlock it.
139 * => flags: PGO_SYNCIO -- use sync. I/O 139 * => flags: PGO_SYNCIO -- use sync. I/O
140 * => note: caller must set PG_CLEAN and pmap_clear_modify (if needed) 140 * => note: caller must set PG_CLEAN and pmap_clear_modify (if needed)
141 */ 141 */
142 142
143static int 143static int
144uvn_put(struct uvm_object *uobj, voff_t offlo, voff_t offhi, int flags) 144uvn_put(struct uvm_object *uobj, voff_t offlo, voff_t offhi, int flags)
145{ 145{
146 struct vnode *vp = (struct vnode *)uobj; 146 struct vnode *vp = (struct vnode *)uobj;
147 int error; 147 int error;
148 148
149 KASSERT(mutex_owned(&vp->v_interlock)); 149 KASSERT(mutex_owned(&vp->v_interlock));
150 error = VOP_PUTPAGES(vp, offlo, offhi, flags); 150 error = VOP_PUTPAGES(vp, offlo, offhi, flags);
151 151
152 return error; 152 return error;
153} 153}
154 154
155 155
156/* 156/*
157 * uvn_get: get pages (synchronously) from backing store 157 * uvn_get: get pages (synchronously) from backing store
158 * 158 *
159 * => prefer map unlocked (not required) 159 * => prefer map unlocked (not required)
160 * => object must be locked! we will _unlock_ it before starting any I/O. 160 * => object must be locked! we will _unlock_ it before starting any I/O.
161 * => flags: PGO_ALLPAGES: get all of the pages 161 * => flags: PGO_ALLPAGES: get all of the pages
162 * PGO_LOCKED: fault data structures are locked 162 * PGO_LOCKED: fault data structures are locked
163 * => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx] 163 * => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx]
164 * => NOTE: caller must check for released pages!! 164 * => NOTE: caller must check for released pages!!
165 */ 165 */
166 166
167static int 167static int
168uvn_get(struct uvm_object *uobj, voff_t offset, 168uvn_get(struct uvm_object *uobj, voff_t offset,
169 struct vm_page **pps /* IN/OUT */, 169 struct vm_page **pps /* IN/OUT */,
170 int *npagesp /* IN (OUT if PGO_LOCKED)*/, 170 int *npagesp /* IN (OUT if PGO_LOCKED)*/,
171 int centeridx, vm_prot_t access_type, int advice, int flags) 171 int centeridx, vm_prot_t access_type, int advice, int flags)
172{ 172{
173 struct vnode *vp = (struct vnode *)uobj; 173 struct vnode *vp = (struct vnode *)uobj;
174 int error; 174 int error;
175 175
176 UVMHIST_FUNC("uvn_get"); UVMHIST_CALLED(ubchist); 176 UVMHIST_FUNC("uvn_get"); UVMHIST_CALLED(ubchist);
177 177
178 UVMHIST_LOG(ubchist, "vp %p off 0x%x", vp, (int)offset, 0,0); 178 UVMHIST_LOG(ubchist, "vp %p off 0x%x", vp, (int)offset, 0,0);
179 179
180 if ((access_type & VM_PROT_WRITE) == 0 && (flags & PGO_LOCKED) == 0) { 180 if ((access_type & VM_PROT_WRITE) == 0 && (flags & PGO_LOCKED) == 0) {
181 vn_ra_allocctx(vp); 181 vn_ra_allocctx(vp);
182 uvm_ra_request(vp->v_ractx, advice, uobj, offset, 182 uvm_ra_request(vp->v_ractx, advice, uobj, offset,
183 *npagesp << PAGE_SHIFT); 183 *npagesp << PAGE_SHIFT);
184 } 184 }
185 185
186 error = VOP_GETPAGES(vp, offset, pps, npagesp, centeridx, 186 error = VOP_GETPAGES(vp, offset, pps, npagesp, centeridx,
187 access_type, advice, flags); 187 access_type, advice, flags);
188 188
189 KASSERT(((flags & PGO_LOCKED) != 0 && mutex_owned(&vp->v_interlock)) || 189 KASSERT(((flags & PGO_LOCKED) != 0 && mutex_owned(&vp->v_interlock)) ||
190 (flags & PGO_LOCKED) == 0); 190 (flags & PGO_LOCKED) == 0);
191 return error; 191 return error;
192} 192}
193 193
194 194
195/* 195/*
196 * uvn_findpages: 196 * uvn_findpages:
197 * return the page for the uobj and offset requested, allocating if needed. 197 * return the page for the uobj and offset requested, allocating if needed.
198 * => uobj must be locked. 198 * => uobj must be locked.
199 * => returned pages will be BUSY. 199 * => returned pages will be BUSY.
200 */ 200 */
201 201
202int 202int
203uvn_findpages(struct uvm_object *uobj, voff_t offset, int *npagesp, 203uvn_findpages(struct uvm_object *uobj, voff_t offset, int *npagesp,
204 struct vm_page **pgs, int flags) 204 struct vm_page **pgs, int flags)
205{ 205{
206 int i, count, found, npages, rv; 206 int i, count, found, npages, rv;
207 207
208 count = found = 0; 208 count = found = 0;
209 npages = *npagesp; 209 npages = *npagesp;
210 if (flags & UFP_BACKWARD) { 210 if (flags & UFP_BACKWARD) {
211 for (i = npages - 1; i >= 0; i--, offset -= PAGE_SIZE) { 211 for (i = npages - 1; i >= 0; i--, offset -= PAGE_SIZE) {
212 rv = uvn_findpage(uobj, offset, &pgs[i], flags); 212 rv = uvn_findpage(uobj, offset, &pgs[i], flags);
213 if (rv == 0) { 213 if (rv == 0) {
214 if (flags & UFP_DIRTYONLY) 214 if (flags & UFP_DIRTYONLY)
215 break; 215 break;
216 } else 216 } else
217 found++; 217 found++;
218 count++; 218 count++;
219 } 219 }
220 } else { 220 } else {
221 for (i = 0; i < npages; i++, offset += PAGE_SIZE) { 221 for (i = 0; i < npages; i++, offset += PAGE_SIZE) {
222 rv = uvn_findpage(uobj, offset, &pgs[i], flags); 222 rv = uvn_findpage(uobj, offset, &pgs[i], flags);
223 if (rv == 0) { 223 if (rv == 0) {
224 if (flags & UFP_DIRTYONLY) 224 if (flags & UFP_DIRTYONLY)
225 break; 225 break;
226 } else 226 } else
227 found++; 227 found++;
228 count++; 228 count++;
229 } 229 }
230 } 230 }
231 *npagesp = count; 231 *npagesp = count;
232 return (found); 232 return (found);
233} 233}
234 234
235static int 235static int
236uvn_findpage(struct uvm_object *uobj, voff_t offset, struct vm_page **pgp, 236uvn_findpage(struct uvm_object *uobj, voff_t offset, struct vm_page **pgp,
237 int flags) 237 int flags)
238{ 238{
239 struct vm_page *pg; 239 struct vm_page *pg;
240 bool dirty; 240 bool dirty;
241 UVMHIST_FUNC("uvn_findpage"); UVMHIST_CALLED(ubchist); 241 UVMHIST_FUNC("uvn_findpage"); UVMHIST_CALLED(ubchist);
242 UVMHIST_LOG(ubchist, "vp %p off 0x%lx", uobj, offset,0,0); 242 UVMHIST_LOG(ubchist, "vp %p off 0x%lx", uobj, offset,0,0);
243 243
244 if (*pgp != NULL) { 244 if (*pgp != NULL) {
245 UVMHIST_LOG(ubchist, "dontcare", 0,0,0,0); 245 UVMHIST_LOG(ubchist, "dontcare", 0,0,0,0);
246 return 0; 246 return 0;
247 } 247 }
248 for (;;) { 248 for (;;) {
249 /* look for an existing page */ 249 /* look for an existing page */
250 pg = uvm_pagelookup(uobj, offset); 250 pg = uvm_pagelookup(uobj, offset);
251 251
252 /* nope? allocate one now */ 252 /* nope? allocate one now */
253 if (pg == NULL) { 253 if (pg == NULL) {
254 if (flags & UFP_NOALLOC) { 254 if (flags & UFP_NOALLOC) {
255 UVMHIST_LOG(ubchist, "noalloc", 0,0,0,0); 255 UVMHIST_LOG(ubchist, "noalloc", 0,0,0,0);
256 return 0; 256 return 0;
257 } 257 }
258 pg = uvm_pagealloc(uobj, offset, NULL, 0); 258 pg = uvm_pagealloc(uobj, offset, NULL, 0);
259 if (pg == NULL) { 259 if (pg == NULL) {
260 if (flags & UFP_NOWAIT) { 260 if (flags & UFP_NOWAIT) {
261 UVMHIST_LOG(ubchist, "nowait",0,0,0,0); 261 UVMHIST_LOG(ubchist, "nowait",0,0,0,0);
262 return 0; 262 return 0;
263 } 263 }
264 mutex_exit(&uobj->vmobjlock); 264 mutex_exit(&uobj->vmobjlock);
265 uvm_wait("uvn_fp1"); 265 uvm_wait("uvn_fp1");
266 mutex_enter(&uobj->vmobjlock); 266 mutex_enter(&uobj->vmobjlock);
267 continue; 267 continue;
268 } 268 }
269 UVMHIST_LOG(ubchist, "alloced %p", pg,0,0,0); 269 UVMHIST_LOG(ubchist, "alloced %p", pg,0,0,0);
270 break; 270 break;
271 } else if (flags & UFP_NOCACHE) { 271 } else if (flags & UFP_NOCACHE) {
272 UVMHIST_LOG(ubchist, "nocache",0,0,0,0); 272 UVMHIST_LOG(ubchist, "nocache",0,0,0,0);
273 return 0; 273 return 0;
274 } 274 }
275 275
276 /* page is there, see if we need to wait on it */ 276 /* page is there, see if we need to wait on it */
277 if ((pg->flags & PG_BUSY) != 0) { 277 if ((pg->flags & PG_BUSY) != 0) {
278 if (flags & UFP_NOWAIT) { 278 if (flags & UFP_NOWAIT) {
279 UVMHIST_LOG(ubchist, "nowait",0,0,0,0); 279 UVMHIST_LOG(ubchist, "nowait",0,0,0,0);
280 return 0; 280 return 0;
281 } 281 }
282 pg->flags |= PG_WANTED; 282 pg->flags |= PG_WANTED;
283 UVMHIST_LOG(ubchist, "wait %p", pg,0,0,0); 283 UVMHIST_LOG(ubchist, "wait %p", pg,0,0,0);
284 UVM_UNLOCK_AND_WAIT(pg, &uobj->vmobjlock, 0, 284 UVM_UNLOCK_AND_WAIT(pg, &uobj->vmobjlock, 0,
285 "uvn_fp2", 0); 285 "uvn_fp2", 0);
286 mutex_enter(&uobj->vmobjlock); 286 mutex_enter(&uobj->vmobjlock);
287 continue; 287 continue;
288 } 288 }
289 289
290 /* skip PG_RDONLY pages if requested */ 290 /* skip PG_RDONLY pages if requested */
291 if ((flags & UFP_NORDONLY) && (pg->flags & PG_RDONLY)) { 291 if ((flags & UFP_NORDONLY) && (pg->flags & PG_RDONLY)) {
292 UVMHIST_LOG(ubchist, "nordonly",0,0,0,0); 292 UVMHIST_LOG(ubchist, "nordonly",0,0,0,0);
293 return 0; 293 return 0;
294 } 294 }
295 295
296 /* stop on clean pages if requested */ 296 /* stop on clean pages if requested */
297 if (flags & UFP_DIRTYONLY) { 297 if (flags & UFP_DIRTYONLY) {
298 dirty = pmap_clear_modify(pg) || 298 dirty = pmap_clear_modify(pg) ||
299 (pg->flags & PG_CLEAN) == 0; 299 (pg->flags & PG_CLEAN) == 0;
300 pg->flags |= PG_CLEAN; 300 pg->flags |= PG_CLEAN;
301 if (!dirty) { 301 if (!dirty) {
302 UVMHIST_LOG(ubchist, "dirtonly", 0,0,0,0); 302 UVMHIST_LOG(ubchist, "dirtonly", 0,0,0,0);
303 return 0; 303 return 0;
304 } 304 }
305 } 305 }
306 306
307 /* mark the page BUSY and we're done. */ 307 /* mark the page BUSY and we're done. */
308 pg->flags |= PG_BUSY; 308 pg->flags |= PG_BUSY;
309 UVM_PAGE_OWN(pg, "uvn_findpage"); 309 UVM_PAGE_OWN(pg, "uvn_findpage");
310 UVMHIST_LOG(ubchist, "found %p", pg,0,0,0); 310 UVMHIST_LOG(ubchist, "found %p", pg,0,0,0);
311 break; 311 break;
312 } 312 }
313 *pgp = pg; 313 *pgp = pg;
314 return 1; 314 return 1;
315} 315}
316 316
317/* 317/*
318 * uvm_vnp_setsize: grow or shrink a vnode uobj 318 * uvm_vnp_setsize: grow or shrink a vnode uobj
319 * 319 *
320 * grow => just update size value 320 * grow => just update size value
321 * shrink => toss un-needed pages 321 * shrink => toss un-needed pages
322 * 322 *
323 * => we assume that the caller has a reference of some sort to the 323 * => we assume that the caller has a reference of some sort to the
324 * vnode in question so that it will not be yanked out from under 324 * vnode in question so that it will not be yanked out from under
325 * us. 325 * us.
326 */ 326 */
327 327
328void 328void
329uvm_vnp_setsize(struct vnode *vp, voff_t newsize) 329uvm_vnp_setsize(struct vnode *vp, voff_t newsize)
330{ 330{
331 struct uvm_object *uobj = &vp->v_uobj; 331 struct uvm_object *uobj = &vp->v_uobj;
332 voff_t pgend = round_page(newsize); 332 voff_t pgend = round_page(newsize);
333 voff_t oldsize; 333 voff_t oldsize;
334 UVMHIST_FUNC("uvm_vnp_setsize"); UVMHIST_CALLED(ubchist); 334 UVMHIST_FUNC("uvm_vnp_setsize"); UVMHIST_CALLED(ubchist);
335 335
336 mutex_enter(&uobj->vmobjlock); 336 mutex_enter(&uobj->vmobjlock);
337 UVMHIST_LOG(ubchist, "vp %p old 0x%x new 0x%x", 337 UVMHIST_LOG(ubchist, "vp %p old 0x%x new 0x%x",
338 vp, vp->v_size, newsize, 0); 338 vp, vp->v_size, newsize, 0);
339 339
340 /* 340 /*
341 * now check if the size has changed: if we shrink we had better 341 * now check if the size has changed: if we shrink we had better
342 * toss some pages... 342 * toss some pages...
343 */ 343 */
344 344
345 KASSERT(newsize != VSIZENOTSET); 345 KASSERT(newsize != VSIZENOTSET);
346 KASSERT(vp->v_size <= vp->v_writesize); 346 KASSERT(vp->v_size <= vp->v_writesize);
347 KASSERT(vp->v_size == vp->v_writesize || 347 KASSERT(vp->v_size == vp->v_writesize ||
348 newsize == vp->v_writesize || newsize <= vp->v_size); 348 newsize == vp->v_writesize || newsize <= vp->v_size);
349 349
350 oldsize = vp->v_writesize; 350 oldsize = vp->v_writesize;
351 KASSERT(oldsize != VSIZENOTSET || pgend > oldsize); 351 KASSERT(oldsize != VSIZENOTSET || pgend > oldsize);
352 352
353 if (oldsize > pgend) { 353 if (oldsize > pgend) {
354 (void) uvn_put(uobj, pgend, 0, PGO_FREE | PGO_SYNCIO); 354 (void) uvn_put(uobj, pgend, 0, PGO_FREE | PGO_SYNCIO);
355 mutex_enter(&uobj->vmobjlock); 355 mutex_enter(&uobj->vmobjlock);
356 } 356 }
357 vp->v_size = vp->v_writesize = newsize; 357 vp->v_size = vp->v_writesize = newsize;
358 mutex_exit(&uobj->vmobjlock); 358 mutex_exit(&uobj->vmobjlock);
359} 359}
360 360
361void 361void
362uvm_vnp_setwritesize(struct vnode *vp, voff_t newsize) 362uvm_vnp_setwritesize(struct vnode *vp, voff_t newsize)
363{ 363{
364 364
365 mutex_enter(&vp->v_interlock); 365 mutex_enter(&vp->v_interlock);
366 KASSERT(newsize != VSIZENOTSET); 366 KASSERT(newsize != VSIZENOTSET);
367 KASSERT(vp->v_size != VSIZENOTSET); 367 KASSERT(vp->v_size != VSIZENOTSET);
368 KASSERT(vp->v_writesize != VSIZENOTSET); 368 KASSERT(vp->v_writesize != VSIZENOTSET);
369 KASSERT(vp->v_size <= vp->v_writesize); 369 KASSERT(vp->v_size <= vp->v_writesize);
370 KASSERT(vp->v_size <= newsize); 370 KASSERT(vp->v_size <= newsize);
371 vp->v_writesize = newsize; 371 vp->v_writesize = newsize;
372 mutex_exit(&vp->v_interlock); 372 mutex_exit(&vp->v_interlock);
373} 373}
374 374
375/* 
376 * uvm_vnp_zerorange: set a range of bytes in a file to zero. 
377 */ 
378 
379void 
380uvm_vnp_zerorange(struct vnode *vp, off_t off, size_t len) 
381{ 
382 void *win; 
383 int flags; 
384 
385 /* 
386 * XXXUBC invent kzero() and use it 
387 */ 
388 
389 while (len) { 
390 vsize_t bytelen = len; 
391 
392 win = ubc_alloc(&vp->v_uobj, off, &bytelen, UVM_ADV_NORMAL, 
393 UBC_WRITE); 
394 memset(win, 0, bytelen); 
395 flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0; 
396 ubc_release(win, flags); 
397 
398 off += bytelen; 
399 len -= bytelen; 
400 } 
401} 
402 
403bool 375bool
404uvn_text_p(struct uvm_object *uobj) 376uvn_text_p(struct uvm_object *uobj)
405{ 377{
406 struct vnode *vp = (struct vnode *)uobj; 378 struct vnode *vp = (struct vnode *)uobj;
407 379
408 return (vp->v_iflag & VI_EXECMAP) != 0; 380 return (vp->v_iflag & VI_EXECMAP) != 0;
409} 381}
410 382
411bool 383bool
412uvn_clean_p(struct uvm_object *uobj) 384uvn_clean_p(struct uvm_object *uobj)
413{ 385{
414 struct vnode *vp = (struct vnode *)uobj; 386 struct vnode *vp = (struct vnode *)uobj;
415 387
416 return (vp->v_iflag & VI_ONWORKLST) == 0; 388 return (vp->v_iflag & VI_ONWORKLST) == 0;
417} 389}
418 390
419bool 391bool
420uvn_needs_writefault_p(struct uvm_object *uobj) 392uvn_needs_writefault_p(struct uvm_object *uobj)
421{ 393{
422 struct vnode *vp = (struct vnode *)uobj; 394 struct vnode *vp = (struct vnode *)uobj;
423 395
424 return uvn_clean_p(uobj) || 396 return uvn_clean_p(uobj) ||
425 (vp->v_iflag & (VI_WRMAP|VI_WRMAPDIRTY)) == VI_WRMAP; 397 (vp->v_iflag & (VI_WRMAP|VI_WRMAPDIRTY)) == VI_WRMAP;
426} 398}