Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/swapfs/swap_subr.c
+++ new/usr/src/uts/common/fs/swapfs/swap_subr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/param.h>
28 28 #include <sys/systm.h>
29 29 #include <sys/errno.h>
30 30 #include <sys/kmem.h>
31 31 #include <sys/vnode.h>
32 32 #include <sys/vfs_opreg.h>
33 33 #include <sys/swap.h>
34 34 #include <sys/sysmacros.h>
35 35 #include <sys/buf.h>
36 36 #include <sys/callb.h>
37 37 #include <sys/debug.h>
38 38 #include <vm/seg.h>
39 39 #include <sys/fs/swapnode.h>
40 40 #include <fs/fs_subr.h>
41 41 #include <sys/cmn_err.h>
42 42 #include <sys/mem_config.h>
43 43 #include <sys/atomic.h>
44 44
45 45 extern const fs_operation_def_t swap_vnodeops_template[];
46 46
47 47 /*
48 48 * swapfs_minfree is the amount of physical memory (actually remaining
49 49 * availrmem) that we want to keep free for the rest of the system. This
50 50 * means that swapfs can only grow to availrmem - swapfs_minfree. This
51 51 * can be set as just constant value or a certain percentage of installed
52 52 * physical memory. It is set in swapinit().
53 53 *
54 54 * Users who want to change the amount of memory that can be used as swap
55 55 * space should do so by setting swapfs_desfree at boot time,
56 56 * not swapfs_minfree.
57 57 */
58 58
59 59 pgcnt_t swapfs_desfree = 0;
60 60 pgcnt_t swapfs_minfree = 0;
61 61 pgcnt_t swapfs_reserve = 0;
62 62
63 63 #ifdef SWAPFS_DEBUG
64 64 int swapfs_debug;
65 65 #endif /* SWAPFS_DEBUG */
66 66
67 67
68 68 static int swapfs_vpcount;
69 69 static kmutex_t swapfs_lock;
70 70 static struct async_reqs *sw_ar, *sw_pendlist, *sw_freelist;
71 71
72 72 static struct vnode **swap_vnodes; /* ptr's to swap vnodes */
73 73
74 74 static void swap_init_mem_config(void);
75 75
76 76 static pgcnt_t initial_swapfs_desfree;
77 77 static pgcnt_t initial_swapfs_minfree;
78 78 static pgcnt_t initial_swapfs_reserve;
79 79
80 80 static int swap_sync(struct vfs *vfsp, short flag, struct cred *cr);
81 81
82 82 static void
83 83 swapfs_recalc_save_initial(void)
84 84 {
85 85 initial_swapfs_desfree = swapfs_desfree;
86 86 initial_swapfs_minfree = swapfs_minfree;
87 87 initial_swapfs_reserve = swapfs_reserve;
88 88 }
89 89
90 90 static int
91 91 swapfs_recalc(pgcnt_t pgs)
92 92 {
93 93 pgcnt_t new_swapfs_desfree;
94 94 pgcnt_t new_swapfs_minfree;
95 95 pgcnt_t new_swapfs_reserve;
96 96
97 97 new_swapfs_desfree = initial_swapfs_desfree;
98 98 new_swapfs_minfree = initial_swapfs_minfree;
99 99 new_swapfs_reserve = initial_swapfs_reserve;
100 100
101 101 if (new_swapfs_desfree == 0)
102 102 new_swapfs_desfree = btopr(7 * 512 * 1024); /* 3-1/2Mb */;
103 103
104 104 if (new_swapfs_minfree == 0) {
105 105 /*
106 106 * We set this lower than we'd like here, 2Mb, because we
107 107 * always boot on swapfs. It's up to a safer value,
108 108 * swapfs_desfree, when/if we add physical swap devices
109 109 * in swapadd(). Users who want to change the amount of
110 110 * memory that can be used as swap space should do so by
111 111 * setting swapfs_desfree at boot time, not swapfs_minfree.
112 112 * However, swapfs_minfree is tunable by install as a
113 113 * workaround for bugid 1147463.
114 114 */
115 115 new_swapfs_minfree = MAX(btopr(2 * 1024 * 1024), pgs >> 3);
116 116 }
117 117
118 118 /*
119 119 * priv processes can reserve memory as swap as long as availrmem
120 120 * remains greater than swapfs_minfree; in the case of non-priv
121 121 * processes, memory can be reserved as swap only if availrmem
122 122 * doesn't fall below (swapfs_minfree + swapfs_reserve). Thus,
123 123 * swapfs_reserve amount of memswap is not available to non-priv
124 124 * processes. This protects daemons such as automounter dying
125 125 * as a result of application processes eating away almost entire
126 126 * membased swap. This safeguard becomes useless if apps are run
127 127 * with root access.
128 128 *
129 129 * set swapfs_reserve to a minimum of 4Mb or 1/128 of physmem whichever
130 130 * is greater up to the limit of 128 MB.
131 131 */
132 132 if (new_swapfs_reserve == 0)
133 133 new_swapfs_reserve = MIN(btopr(128 * 1024 * 1024),
134 134 MAX(btopr(4 * 1024 * 1024), pgs >> 7));
135 135
136 136 /* Test basic numeric viability. */
137 137 if (new_swapfs_minfree > pgs)
138 138 return (0);
139 139
140 140 /* Equivalent test to anon_resvmem() check. */
141 141 if (availrmem < new_swapfs_minfree) {
142 142 /*
143 143 * If ism pages are being used, then there must be agreement
144 144 * between these two policies.
145 145 */
146 146 if ((availrmem > segspt_minfree) && (segspt_minfree > 0)) {
147 147 new_swapfs_minfree = segspt_minfree;
148 148 } else {
149 149 return (0);
150 150 }
151 151 }
152 152
153 153 swapfs_desfree = new_swapfs_desfree;
154 154 swapfs_minfree = new_swapfs_minfree;
155 155 swapfs_reserve = new_swapfs_reserve;
156 156
157 157 return (1);
↓ open down ↓ |
157 lines elided |
↑ open up ↑ |
158 158 }
159 159
160 160 /*ARGSUSED1*/
161 161 int
162 162 swapinit(int fstype, char *name)
163 163 { /* reserve for mp */
164 164 ssize_t sw_freelist_size = klustsize / PAGESIZE * 2;
165 165 int i, error;
166 166
167 167 static const fs_operation_def_t swap_vfsops[] = {
168 - VFSNAME_SYNC, { .vfs_sync = swap_sync },
169 - NULL, NULL
168 + { VFSNAME_SYNC, { .vfs_sync = swap_sync }},
169 + { NULL, {NULL} }
170 170 };
171 171
172 172 SWAPFS_PRINT(SWAP_SUBR, "swapinit\n", 0, 0, 0, 0, 0);
173 173 mutex_init(&swapfs_lock, NULL, MUTEX_DEFAULT, NULL);
174 174
175 175 swap_vnodes = kmem_zalloc(MAX_SWAP_VNODES * sizeof (struct vnode *),
176 176 KM_SLEEP);
177 177
178 178 swapfs_recalc_save_initial();
179 179 if (!swapfs_recalc(physmem))
180 180 cmn_err(CE_PANIC, "swapfs_minfree(%lu) > physmem(%lu)",
181 181 swapfs_minfree, physmem);
182 182
183 183 /*
184 184 * Arrange for a callback on memory size change.
185 185 */
186 186 swap_init_mem_config();
187 187
188 188 sw_ar = (struct async_reqs *)
189 189 kmem_zalloc(sw_freelist_size*sizeof (struct async_reqs), KM_SLEEP);
190 190
191 191 error = vfs_setfsops(fstype, swap_vfsops, NULL);
192 192 if (error != 0) {
193 193 cmn_err(CE_WARN, "swapinit: bad vfs ops template");
194 194 return (error);
195 195 }
196 196
197 197 error = vn_make_ops(name, swap_vnodeops_template, &swap_vnodeops);
198 198 if (error != 0) {
199 199 (void) vfs_freevfsops_by_type(fstype);
200 200 cmn_err(CE_WARN, "swapinit: bad vnode ops template");
201 201 return (error);
202 202 }
203 203 sw_freelist = sw_ar;
204 204 for (i = 0; i < sw_freelist_size - 1; i++)
205 205 sw_ar[i].a_next = &sw_ar[i + 1];
206 206
207 207 return (0);
208 208 }
209 209
210 210 /*
211 211 * Get a swapfs vnode corresponding to the specified identifier.
212 212 */
213 213 struct vnode *
214 214 swapfs_getvp(ulong_t vidx)
215 215 {
216 216 struct vnode *vp;
217 217
218 218 vp = swap_vnodes[vidx];
219 219 if (vp) {
220 220 return (vp);
221 221 }
222 222
223 223 mutex_enter(&swapfs_lock);
224 224 vp = swap_vnodes[vidx];
225 225 if (vp == NULL) {
226 226 vp = vn_alloc(KM_SLEEP);
227 227 vn_setops(vp, swap_vnodeops);
228 228 vp->v_type = VREG;
229 229 vp->v_flag |= (VISSWAP|VISSWAPFS);
230 230 swap_vnodes[vidx] = vp;
231 231 swapfs_vpcount++;
232 232 }
233 233 mutex_exit(&swapfs_lock);
234 234 return (vp);
235 235 }
236 236
237 237 int swap_lo;
238 238
239 239 /*ARGSUSED*/
240 240 static int
241 241 swap_sync(struct vfs *vfsp, short flag, struct cred *cr)
242 242 {
243 243 struct vnode *vp;
244 244 int i;
245 245
246 246 if (!(flag & SYNC_ALL))
247 247 return (1);
248 248
249 249 /*
250 250 * assumes that we are the only one left to access this so that
251 251 * no need to use swapfs_lock (since it's staticly defined)
252 252 */
253 253 for (i = 0; i < MAX_SWAP_VNODES; i++) {
254 254 vp = swap_vnodes[i];
255 255 if (vp) {
256 256 VN_HOLD(vp);
257 257 (void) VOP_PUTPAGE(vp, (offset_t)0, 0,
258 258 (B_ASYNC | B_FREE), kcred, NULL);
259 259 VN_RELE(vp);
260 260 }
261 261 }
262 262 return (0);
263 263 }
264 264
265 265 extern int sw_pending_size;
266 266
267 267 /*
268 268 * Take an async request off the pending queue
269 269 */
270 270 struct async_reqs *
271 271 sw_getreq()
272 272 {
273 273 struct async_reqs *arg;
274 274
275 275 mutex_enter(&swapfs_lock);
276 276 arg = sw_pendlist;
277 277 if (arg) {
278 278 sw_pendlist = arg->a_next;
279 279 arg->a_next = NULL;
280 280 sw_pending_size -= PAGESIZE;
281 281 }
282 282 ASSERT(sw_pending_size >= 0);
283 283 mutex_exit(&swapfs_lock);
284 284 return (arg);
285 285 }
286 286
287 287 /*
288 288 * Put an async request on the pending queue
289 289 */
290 290 void
291 291 sw_putreq(struct async_reqs *arg)
292 292 {
293 293 /* Hold onto it */
294 294 VN_HOLD(arg->a_vp);
295 295
296 296 mutex_enter(&swapfs_lock);
297 297 arg->a_next = sw_pendlist;
298 298 sw_pendlist = arg;
299 299 sw_pending_size += PAGESIZE;
300 300 mutex_exit(&swapfs_lock);
301 301 }
302 302
303 303 /*
304 304 * Put an async request back on the pending queue
305 305 */
306 306 void
307 307 sw_putbackreq(struct async_reqs *arg)
308 308 {
309 309 mutex_enter(&swapfs_lock);
310 310 arg->a_next = sw_pendlist;
311 311 sw_pendlist = arg;
312 312 sw_pending_size += PAGESIZE;
313 313 mutex_exit(&swapfs_lock);
314 314 }
315 315
316 316 /*
317 317 * Take an async request structure off the free list
318 318 */
319 319 struct async_reqs *
320 320 sw_getfree()
321 321 {
322 322 struct async_reqs *arg;
323 323
324 324 mutex_enter(&swapfs_lock);
325 325 arg = sw_freelist;
326 326 if (arg) {
327 327 sw_freelist = arg->a_next;
328 328 arg->a_next = NULL;
329 329 }
330 330 mutex_exit(&swapfs_lock);
331 331 return (arg);
332 332 }
333 333
334 334 /*
335 335 * Put an async request structure on the free list
336 336 */
337 337 void
338 338 sw_putfree(struct async_reqs *arg)
339 339 {
340 340 /* Release our hold - should have locked the page by now */
341 341 VN_RELE(arg->a_vp);
342 342
343 343 mutex_enter(&swapfs_lock);
344 344 arg->a_next = sw_freelist;
345 345 sw_freelist = arg;
346 346 mutex_exit(&swapfs_lock);
347 347 }
348 348
349 349 static pgcnt_t swapfs_pending_delete;
350 350
351 351 /*ARGSUSED*/
352 352 static void
353 353 swap_mem_config_post_add(
354 354 void *arg,
355 355 pgcnt_t delta_swaps)
356 356 {
357 357 (void) swapfs_recalc(physmem - swapfs_pending_delete);
358 358 }
359 359
360 360 /*ARGSUSED*/
361 361 static int
362 362 swap_mem_config_pre_del(
363 363 void *arg,
364 364 pgcnt_t delta_swaps)
365 365 {
366 366 pgcnt_t nv;
367 367
368 368 nv = atomic_add_long_nv(&swapfs_pending_delete, (spgcnt_t)delta_swaps);
369 369 if (!swapfs_recalc(physmem - nv)) {
370 370 /*
371 371 * Tidy-up is done by the call to post_del which
372 372 * is always made.
373 373 */
374 374 cmn_err(CE_NOTE, "Memory operation refused to ensure system "
375 375 "doesn't deadlock due to excessive consumption by swapfs.");
376 376 return (EBUSY);
377 377 }
378 378 return (0);
379 379 }
380 380
381 381 /*ARGSUSED*/
382 382 static void
383 383 swap_mem_config_post_del(
384 384 void *arg,
385 385 pgcnt_t delta_swaps,
386 386 int cancelled)
387 387 {
388 388 pgcnt_t nv;
389 389
390 390 nv = atomic_add_long_nv(&swapfs_pending_delete, -(spgcnt_t)delta_swaps);
391 391 (void) swapfs_recalc(physmem - nv);
392 392 }
393 393
394 394 static kphysm_setup_vector_t swap_mem_config_vec = {
395 395 KPHYSM_SETUP_VECTOR_VERSION,
396 396 swap_mem_config_post_add,
397 397 swap_mem_config_pre_del,
398 398 swap_mem_config_post_del,
399 399 };
400 400
401 401 static void
402 402 swap_init_mem_config(void)
403 403 {
404 404 int ret;
405 405
406 406 ret = kphysm_setup_func_register(&swap_mem_config_vec, (void *)NULL);
407 407 ASSERT(ret == 0);
408 408 }
↓ open down ↓ |
229 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX