|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: #include <mach_nbc.h>
23: #include <mach/boolean.h>
24: #include <sys/param.h>
25: #include <sys/systm.h>
26: #include <sys/lock.h>
27: #include <sys/proc.h>
28: #include <sys/buf.h>
29: #include <sys/uio.h>
30: #include <sys/vnode.h>
31: #include <ufs/ufs/quota.h>
32: #include <ufs/ufs/inode.h>
33: #include <sys/namei.h>
34: #include <sys/mach_swapon.h>
35: #include <ufs/ffs/fs.h>
36: #include <sys/mount.h>
37: #include <net/if.h>
38: #include <netinet/in.h>
39: #include <nfs/rpcv2.h>
40: #include <nfs/nfsproto.h>
41: #include <nfs/nfs.h>
42: #undef fs_fsok
43: #undef fs_tsize
44: #undef fs_bsize
45: #undef fs_blocks
46: #undef fs_bfree
47: #undef fs_bavail
48:
49: #include <mach/mach_types.h>
50: #include <vm/vm_map.h>
51: #include <vm/vm_kern.h>
52: #include <kern/parallel.h>
53: #include <kern/zalloc.h>
54: #include <kern/kalloc.h>
55: #include <libkern/libkern.h>
56: #include <sys/malloc.h>
57: #include <sys/resourcevar.h>
58: #include <sys/signalvar.h>
59:
60: #include <vm/vnode_pager.h>
61: #include <kern/mapfs.h>
62:
63: default_pager_init_flag = 0; /* temporary support for delayed instantiation */
64: /* of default_pager */
65:
66:
67:
68:
69: /* Get rid of this when component interface is in place */
70: struct host {
71: void *host_self;
72: void *host_priv_self;
73: void *host_security_self;
74: };
75: typedef struct host host_data_t;
76:
77: extern host_data_t realhost;
78: struct vnode *default_pager_vnode = 0;
79:
80: struct bs_map bs_port_table[MAX_BACKING_STORE] = {
81: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
82: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
83: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
84: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
85: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
86: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
87: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
88: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
89: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
90: {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}};
91:
92: /* ###################################################### */
93:
94:
95: #include <kern/assert.h>
96:
97: /*
98: * Routine: macx_swapon
99: * Function:
100: * Syscall interface to add a file to backing store
101: */
102: int
103: macx_swapon(
104: char *filename,
105: int flags,
106: long size,
107: long priority)
108: {
109: struct vnode *vp = 0;
110: struct nameidata nd, *ndp;
111: struct proc *p = current_proc();
112: pager_file_t pf;
113: register int error;
114: kern_return_t kr;
115: mach_port_t backing_store;
116: mach_port_t default_pager_port = MACH_PORT_NULL;
117: int i;
118:
119: struct vattr vattr;
120:
121: /*
122: printf("macx_swapon: function called\n");
123: */
124: ndp = &nd;
125:
126:
127: if ((error = suser(p->p_ucred, &p->p_acflag)))
128: goto swapon_bailout;
129:
130: unix_master();
131:
132: if(default_pager_init_flag == 0) {
133: start_def_pager(NULL);
134: default_pager_init_flag = 1;
135: }
136:
137: /*
138: * Get a vnode for the paging area.
139: */
140: NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
141: filename, p);
142:
143: if ((error = namei(ndp)))
144: goto swapon_bailout;
145: vp = ndp->ni_vp;
146:
147: if (vp->v_type != VREG) {
148: error = EINVAL;
149: VOP_UNLOCK(vp, 0, p);
150: goto swapon_bailout;
151: }
152:
153: if (!vp->v_vm_info) {
154: vm_info_init(vp);
155: }
156:
157: if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) {
158: VOP_UNLOCK(vp, 0, p);
159: goto swapon_bailout;
160: }
161:
162: /*
163: printf("macx_swapon: check size va_size = 0x%x, lowat = 0x%x\n", (int)vattr.va_size, size);
164: */
165: if (vattr.va_size < (u_quad_t)size) {
166: vattr_null(&vattr);
167: vattr.va_size = (u_quad_t)size;
168: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
169: if (error) {
170: VOP_UNLOCK(vp, 0, p);
171: goto swapon_bailout;
172: }
173: }
174:
175:
176: vp->v_vm_info->vnode_size = vattr.va_size;
177:
178: /* add new backing store to list */
179: i = 0;
180: while(bs_port_table[i].vp != 0) {
181: if(i == MAX_BACKING_STORE)
182: break;
183: i++;
184: }
185: if(i == MAX_BACKING_STORE) {
186: error = ENOMEM;
187: VOP_UNLOCK(vp, 0, p);
188: goto swapon_bailout;
189: }
190: bs_port_table[i].vp = vp;
191:
192:
193: /*
194: * Look to see if we are already paging to this file.
195: */
196: /* make certain the copy send of kernel call will work */
197: /*
198: put this back in when component interfaces are available
199: kr = host_default_memory_manager(mach_host_self(),
200: &default_pager_port, 0);
201: */
202: kr = host_default_memory_manager(realhost.host_priv_self, &default_pager_port, 0);
203: if(kr != KERN_SUCCESS) {
204: error = EAGAIN;
205: VOP_UNLOCK(vp, 0, p);
206: bs_port_table[i].vp = 0;
207: goto swapon_bailout;
208: }
209:
210: kr = default_pager_backing_store_create(default_pager_port,
211: -1, /* default priority */
212: 0, /* default cluster size */
213: &backing_store);
214: if(kr != KERN_SUCCESS) {
215: error = ENOMEM;
216: VOP_UNLOCK(vp, 0, p);
217: bs_port_table[i].vp = 0;
218: goto swapon_bailout;
219: }
220:
221:
222: /* NOTE: we are able to supply PAGE_SIZE here instead of an actual */
223: /* record size or block number because: a: we do not support offsets */
224: /* from the beginning of the file (allowing for non page size/record */
225: /* modulo offsets. b: because allow paging will be done modulo page size */
226:
227: /*
228: printf("macx_swapon: calling default_pager_add_file, bs port 0x%x, vnode 0x%x, record_size 0x%x, size 0x%x\n",backing_store, vp, PAGE_SIZE, (int)vattr.va_size);
229: */
230: VOP_UNLOCK(vp, 0, p);
231: kr = default_pager_add_file(backing_store, vp, PAGE_SIZE,
232: ((int)vattr.va_size)/PAGE_SIZE);
233: if(kr != KERN_SUCCESS) {
234: bs_port_table[i].vp = 0;
235: if(kr == KERN_INVALID_ARGUMENT)
236: error = EINVAL;
237: else
238: error = ENOMEM;
239: goto swapon_bailout;
240: }
241: bs_port_table[i].bs = (void *)backing_store;
242: /* grab a reference to hold on to the paging file vnode */
243: VREF(vp);
244: VREF(vp);
245: VREF(vp);
246: VREF(vp);
247: error = 0;
248:
249: swapon_bailout:
250: if (vp) {
251: vrele(vp);
252: }
253: unix_release();
254: return(error);
255: }
256:
257: /*
258: * Routine: macx_swapoff
259: * Function:
260: * Syscall interface to remove a file from backing store
261: */
262: int
263: macx_swapoff(
264: char *filename,
265: int flags)
266: {
267: kern_return_t kr;
268: mach_port_t backing_store;
269:
270: struct vnode *vp = 0;
271: struct nameidata nd, *ndp;
272: struct proc *p = current_proc();
273: int i;
274: int error;
275:
276: /*
277: printf("macx_swapoff: function called\n");
278: */
279: backing_store = NULL;
280: ndp = &nd;
281:
282:
283: if ((error = suser(p->p_ucred, &p->p_acflag)))
284: goto swapoff_bailout;
285:
286: unix_master();
287:
288: /*
289: * Get the vnode for the paging area.
290: */
291: NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
292: filename, p);
293:
294: if ((error = namei(ndp)))
295: goto swapoff_bailout;
296: vp = ndp->ni_vp;
297:
298: if (vp->v_type != VREG) {
299: error = EINVAL;
300: VOP_UNLOCK(vp, 0, p);
301: goto swapoff_bailout;
302: }
303:
304: for(i = 0; i < MAX_BACKING_STORE; i++) {
305: if(bs_port_table[i].vp == vp) {
306: backing_store;
307: break;
308: }
309: }
310: if (i == MAX_BACKING_STORE) {
311: error = EINVAL;
312: VOP_UNLOCK(vp, 0, p);
313: goto swapoff_bailout;
314: }
315: backing_store = (mach_port_t)bs_port_table[i].bs;
316:
317:
318: VOP_UNLOCK(vp, 0, p);
319: kr = default_pager_backing_store_delete(backing_store);
320: switch (kr) {
321: case KERN_SUCCESS:
322: error = 0;
323: bs_port_table[i].vp = 0;
324: vrele(vp);
325: vrele(vp);
326: vrele(vp);
327: vrele(vp);
328: break;
329: case KERN_FAILURE:
330: error = EAGAIN;
331: break;
332: default:
333: error = EAGAIN;
334: break;
335: }
336: swapoff_bailout:
337: if (vp) {
338: vrele(vp);
339: }
340: unix_release();
341: return(error);
342: }
343:
344: /*
345: * Routine: mach_swapon
346: * Function:
347: * Syscall interface to add a file to backing store
348: */
349: int
350: mach_swapon(
351: char *filename,
352: int flags,
353: long lowat,
354: long hiwat)
355: {
356: struct vnode *vp = 0;
357: struct nameidata nd, *ndp;
358: struct proc *p = current_proc();
359: pager_file_t pf;
360: register int error;
361: kern_return_t kr;
362: mach_port_t backing_store;
363: mach_port_t default_pager_port = MACH_PORT_NULL;
364:
365: struct vattr vattr;
366:
367: ndp = &nd;
368:
369: if ((error = suser(p->p_ucred, &p->p_acflag)))
370: goto bailout;
371:
372: unix_master();
373:
374: if(default_pager_init_flag == 0) {
375: start_def_pager(NULL);
376: default_pager_init_flag = 1;
377: }
378:
379: /*
380: * Get a vnode for the paging area.
381: */
382: NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
383: filename, p);
384:
385: if ((error = namei(ndp)))
386: goto bailout;
387: vp = ndp->ni_vp;
388:
389: if (vp->v_type != VREG) {
390: error = EINVAL;
391: goto bailout;
392: }
393:
394: if (!vp->v_vm_info) {
395: vm_info_init(vp);
396: }
397:
398: if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) {
399: goto bailout;
400: }
401:
402: /*
403: printf("mach_swapon: check lowat va_size = 0x%x, lowat = 0x%x\n", (int)vattr.va_size, lowat);
404: */
405: if (vattr.va_size < (u_quad_t)lowat) {
406: vattr_null(&vattr);
407: vattr.va_size = (u_quad_t)lowat;
408: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
409: if (error) {
410: goto bailout;
411: }
412: }
413:
414:
415: vp->v_vm_info->vnode_size = vattr.va_size;
416:
417: /*
418: * Look to see if we are already paging to this file.
419: */
420: /* make certain the copy send of kernel call will work */
421: /*
422: put this back in when component interfaces are available
423: kr = host_default_memory_manager(mach_host_self(),
424: &default_pager_port, 0);
425: */
426: kr = host_default_memory_manager(realhost.host_priv_self, &default_pager_port, 0);
427: if(kr != KERN_SUCCESS) {
428: error = kr;
429: goto bailout;
430: }
431:
432: kr = default_pager_backing_store_create(default_pager_port,
433: -1, /* default priority */
434: 0, /* default cluster size */
435: &backing_store);
436: if(kr != KERN_SUCCESS) {
437: error = kr;
438: goto bailout;
439: }
440:
441:
442: /* NOTE: we are able to supply PAGE_SIZE here instead of an actual */
443: /* record size or block number because: a: we do not support offsets */
444: /* from the beginning of the file (allowing for non page size/record */
445: /* modulo offsets. b: because allow paging will be done modulo page size */
446:
447: /*
448: printf("mach_swapon: calling default_pager_add_file, bs port 0x%x, vnode 0x%x, record_size 0x%x, size 0x%x\n",backing_store, vp, PAGE_SIZE, (int)vattr.va_size);
449: */
450: kr = default_pager_add_file(backing_store, vp, PAGE_SIZE,
451: ((int)vattr.va_size)/PAGE_SIZE);
452: if(kr != KERN_SUCCESS) {
453: error = kr;
454: goto bailout;
455: }
456: /* grab a reference to hold on to the paging file vnode */
457: VREF(vp);
458: default_pager_vnode = vp;
459:
460: error = 0;
461:
462: bailout:
463: if (vp) {
464: VOP_UNLOCK(vp, 0, p);
465: vrele(vp);
466: }
467: unix_release();
468: return(error);
469: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.