2005-01-07 02:29:27 +00:00
|
|
|
/*-
|
1994-05-24 10:09:53 +00:00
|
|
|
* Copyright (c) 1988 University of Utah.
|
|
|
|
* Copyright (c) 1991, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* the Systems Programming Group of the University of Utah Computer
|
|
|
|
* Science Department.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
|
|
|
|
*
|
|
|
|
* @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mapped file (mmap) interface to VM
|
|
|
|
*/
|
|
|
|
|
2003-06-11 23:50:51 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1997-12-16 17:40:42 +00:00
|
|
|
#include "opt_compat.h"
|
2006-03-26 12:20:54 +00:00
|
|
|
#include "opt_hwpmc_hooks.h"
|
1996-12-22 23:17:09 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2011-08-11 12:30:23 +00:00
|
|
|
#include <sys/capability.h>
|
|
|
|
#include <sys/kernel.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/lock.h>
|
2001-05-19 01:28:09 +00:00
|
|
|
#include <sys/mutex.h>
|
1995-11-12 06:43:28 +00:00
|
|
|
#include <sys/sysproto.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/filedesc.h>
|
2006-11-06 13:42:10 +00:00
|
|
|
#include <sys/priv.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/proc.h>
|
2013-09-19 18:53:42 +00:00
|
|
|
#include <sys/procctl.h>
|
2011-04-05 20:23:59 +00:00
|
|
|
#include <sys/racct.h>
|
2002-06-26 00:29:28 +00:00
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <sys/resourcevar.h>
|
2013-03-09 02:32:23 +00:00
|
|
|
#include <sys/rwlock.h>
|
2012-12-18 07:35:01 +00:00
|
|
|
#include <sys/sysctl.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/vnode.h>
|
1997-03-23 03:37:54 +00:00
|
|
|
#include <sys/fcntl.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/file.h>
|
|
|
|
#include <sys/mman.h>
|
2004-03-18 20:58:51 +00:00
|
|
|
#include <sys/mount.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/conf.h>
|
1998-05-19 07:13:21 +00:00
|
|
|
#include <sys/stat.h>
|
2013-09-19 18:53:42 +00:00
|
|
|
#include <sys/syscallsubr.h>
|
2009-09-20 12:40:56 +00:00
|
|
|
#include <sys/sysent.h>
|
1995-12-07 12:48:31 +00:00
|
|
|
#include <sys/vmmeter.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-10-22 11:52:19 +00:00
|
|
|
#include <security/mac/mac_framework.h>
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <vm/vm.h>
|
1995-12-07 12:48:31 +00:00
|
|
|
#include <vm/vm_param.h>
|
|
|
|
#include <vm/pmap.h>
|
|
|
|
#include <vm/vm_map.h>
|
|
|
|
#include <vm/vm_object.h>
|
1999-01-21 08:29:12 +00:00
|
|
|
#include <vm/vm_page.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <vm/vm_pager.h>
|
1995-03-16 18:17:34 +00:00
|
|
|
#include <vm/vm_pageout.h>
|
1995-12-07 12:48:31 +00:00
|
|
|
#include <vm/vm_extern.h>
|
1996-05-19 07:36:50 +00:00
|
|
|
#include <vm/vm_page.h>
|
2012-02-23 21:07:16 +00:00
|
|
|
#include <vm/vnode_pager.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-03-26 12:20:54 +00:00
|
|
|
#ifdef HWPMC_HOOKS
|
|
|
|
#include <sys/pmckern.h>
|
|
|
|
#endif
|
|
|
|
|
2012-12-18 07:35:01 +00:00
|
|
|
int old_mlock = 0;
|
|
|
|
SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RW | CTLFLAG_TUN, &old_mlock, 0,
|
|
|
|
"Do not apply RLIMIT_MEMLOCK on mlockall");
|
|
|
|
TUNABLE_INT("vm.old_mlock", &old_mlock);
|
|
|
|
|
2013-09-09 18:11:59 +00:00
|
|
|
#ifdef MAP_32BIT
|
|
|
|
#define MAP_32BIT_MAX_ADDR ((vm_offset_t)1 << 31)
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
2004-02-27 22:02:15 +00:00
|
|
|
static int vm_mmap_vnode(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
|
2012-02-23 21:07:16 +00:00
|
|
|
int *, struct vnode *, vm_ooffset_t *, vm_object_t *, boolean_t *);
|
2005-04-01 20:00:11 +00:00
|
|
|
static int vm_mmap_cdev(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
|
2009-06-01 21:32:52 +00:00
|
|
|
int *, struct cdev *, vm_ooffset_t *, vm_object_t *);
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
static int vm_mmap_shm(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
|
|
|
|
int *, struct shmfd *, vm_ooffset_t, vm_object_t *);
|
2004-02-27 22:02:15 +00:00
|
|
|
|
2013-09-09 18:11:59 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct sbrk_args {
|
|
|
|
int incr;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_sbrk(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sbrk_args *uap;
|
|
|
|
{
|
|
|
|
/* Not yet implemented */
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sstk_args {
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
int incr;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_sstk(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sstk_args *uap;
|
|
|
|
{
|
|
|
|
/* Not yet implemented */
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct getpagesize_args {
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
int dummy;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2001-09-12 08:38:13 +00:00
|
|
|
ogetpagesize(td, uap)
|
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct getpagesize_args *uap;
|
|
|
|
{
|
2001-07-04 16:20:28 +00:00
|
|
|
/* MP SAFE */
|
2001-09-12 08:38:13 +00:00
|
|
|
td->td_retval[0] = PAGE_SIZE;
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2004-06-11 11:16:26 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-08-30 18:50:06 +00:00
|
|
|
|
2003-12-08 02:45:45 +00:00
|
|
|
/*
|
1997-08-30 18:50:06 +00:00
|
|
|
* Memory Map (mmap) system call. Note that the file offset
|
|
|
|
* and address are allowed to be NOT page aligned, though if
|
|
|
|
* the MAP_FIXED flag it set, both must have the same remainder
|
|
|
|
* modulo the PAGE_SIZE (POSIX 1003.1b). If the address is not
|
|
|
|
* page-aligned, the actual mapping starts at trunc_page(addr)
|
|
|
|
* and the return value is adjusted up by the page offset.
|
1999-09-21 05:00:48 +00:00
|
|
|
*
|
|
|
|
* Generally speaking, only character devices which are themselves
|
|
|
|
* memory-based, such as a video framebuffer, can be mmap'd. Otherwise
|
|
|
|
* there would be no cache coherency between a descriptor and a VM mapping
|
|
|
|
* both to the same character device.
|
1997-08-30 18:50:06 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mmap_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
size_t len;
|
|
|
|
int prot;
|
|
|
|
int flags;
|
|
|
|
int fd;
|
|
|
|
long pad;
|
|
|
|
off_t pos;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_mmap(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
2001-07-04 19:00:13 +00:00
|
|
|
struct mmap_args *uap;
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-03-26 12:20:54 +00:00
|
|
|
#ifdef HWPMC_HOOKS
|
|
|
|
struct pmckern_map_in pkm;
|
|
|
|
#endif
|
2004-02-27 22:02:15 +00:00
|
|
|
struct file *fp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct vnode *vp;
|
|
|
|
vm_offset_t addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
vm_size_t size, pageoff;
|
2011-08-11 12:30:23 +00:00
|
|
|
vm_prot_t cap_maxprot, prot, maxprot;
|
1997-12-31 02:35:29 +00:00
|
|
|
void *handle;
|
2005-04-01 20:00:11 +00:00
|
|
|
objtype_t handle_type;
|
2013-08-16 21:13:55 +00:00
|
|
|
int align, error, flags;
|
1997-08-30 18:50:06 +00:00
|
|
|
off_t pos;
|
2001-09-12 08:38:13 +00:00
|
|
|
struct vmspace *vms = td->td_proc->p_vmspace;
|
2011-08-11 12:30:23 +00:00
|
|
|
cap_rights_t rights;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-08-30 18:50:06 +00:00
|
|
|
addr = (vm_offset_t) uap->addr;
|
|
|
|
size = uap->len;
|
1994-05-24 10:09:53 +00:00
|
|
|
prot = uap->prot & VM_PROT_ALL;
|
|
|
|
flags = uap->flags;
|
1997-08-30 18:50:06 +00:00
|
|
|
pos = uap->pos;
|
|
|
|
|
2002-01-13 11:58:06 +00:00
|
|
|
fp = NULL;
|
2009-09-27 14:49:51 +00:00
|
|
|
|
2012-08-14 11:47:07 +00:00
|
|
|
/*
|
|
|
|
* Enforce the constraints.
|
|
|
|
* Mapping of length 0 is only allowed for old binaries.
|
|
|
|
* Anonymous mapping shall specify -1 as filedescriptor and
|
|
|
|
* zero position for new code. Be nice to ancient a.out
|
|
|
|
* binaries and correct pos for anonymous mapping, since old
|
|
|
|
* ld.so sometimes issues anonymous map requests with non-zero
|
|
|
|
* pos.
|
|
|
|
*/
|
|
|
|
if (!SV_CURPROC_FLAG(SV_AOUT)) {
|
|
|
|
if ((uap->len == 0 && curproc->p_osrel >= P_OSREL_MAP_ANON) ||
|
|
|
|
((flags & MAP_ANON) != 0 && (uap->fd != -1 || pos != 0)))
|
|
|
|
return (EINVAL);
|
|
|
|
} else {
|
|
|
|
if ((flags & MAP_ANON) != 0)
|
|
|
|
pos = 0;
|
|
|
|
}
|
1996-03-02 17:14:09 +00:00
|
|
|
|
1999-01-06 23:05:42 +00:00
|
|
|
if (flags & MAP_STACK) {
|
|
|
|
if ((uap->fd != -1) ||
|
|
|
|
((prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)))
|
|
|
|
return (EINVAL);
|
|
|
|
flags |= MAP_ANON;
|
|
|
|
pos = 0;
|
1999-01-26 02:49:52 +00:00
|
|
|
}
|
|
|
|
|
1996-03-02 17:14:09 +00:00
|
|
|
/*
|
1997-08-30 18:50:06 +00:00
|
|
|
* Align the file position to a page boundary,
|
|
|
|
* and save its page offset component.
|
1996-03-02 17:14:09 +00:00
|
|
|
*/
|
1997-08-30 18:50:06 +00:00
|
|
|
pageoff = (pos & PAGE_MASK);
|
|
|
|
pos -= pageoff;
|
|
|
|
|
|
|
|
/* Adjust size for rounding (on both ends). */
|
|
|
|
size += pageoff; /* low end... */
|
|
|
|
size = (vm_size_t) round_page(size); /* hi end */
|
1996-03-02 17:14:09 +00:00
|
|
|
|
2013-08-16 21:13:55 +00:00
|
|
|
/* Ensure alignment is at least a page and fits in a pointer. */
|
|
|
|
align = flags & MAP_ALIGNMENT_MASK;
|
|
|
|
if (align != 0 && align != MAP_ALIGNED_SUPER &&
|
|
|
|
(align >> MAP_ALIGNMENT_SHIFT >= sizeof(void *) * NBBY ||
|
|
|
|
align >> MAP_ALIGNMENT_SHIFT < PAGE_SHIFT))
|
|
|
|
return (EINVAL);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
* Check for illegal addresses. Watch out for address wrap... Note
|
|
|
|
* that VM_*_ADDRESS are not constants due to casts (argh).
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
if (flags & MAP_FIXED) {
|
1997-08-30 18:50:06 +00:00
|
|
|
/*
|
|
|
|
* The specified address must have the same remainder
|
|
|
|
* as the file offset taken modulo PAGE_SIZE, so it
|
|
|
|
* should be aligned after adjustment by pageoff.
|
|
|
|
*/
|
|
|
|
addr -= pageoff;
|
|
|
|
if (addr & PAGE_MASK)
|
|
|
|
return (EINVAL);
|
2009-09-27 14:49:51 +00:00
|
|
|
|
1997-08-30 18:50:06 +00:00
|
|
|
/* Address range must be all in user VM space. */
|
2002-09-21 22:07:17 +00:00
|
|
|
if (addr < vm_map_min(&vms->vm_map) ||
|
|
|
|
addr + size > vm_map_max(&vms->vm_map))
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
1994-08-04 03:06:48 +00:00
|
|
|
if (addr + size < addr)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
2013-09-09 18:11:59 +00:00
|
|
|
#ifdef MAP_32BIT
|
|
|
|
if (flags & MAP_32BIT && addr + size > MAP_32BIT_MAX_ADDR)
|
|
|
|
return (EINVAL);
|
|
|
|
} else if (flags & MAP_32BIT) {
|
|
|
|
/*
|
|
|
|
* For MAP_32BIT, override the hint if it is too high and
|
|
|
|
* do not bother moving the mapping past the heap (since
|
|
|
|
* the heap is usually above 2GB).
|
|
|
|
*/
|
|
|
|
if (addr + size > MAP_32BIT_MAX_ADDR)
|
|
|
|
addr = 0;
|
|
|
|
#endif
|
2004-02-04 21:52:57 +00:00
|
|
|
} else {
|
2010-12-04 17:41:58 +00:00
|
|
|
/*
|
|
|
|
* XXX for non-fixed mappings where no hint is provided or
|
|
|
|
* the hint would fall in the potential heap space,
|
|
|
|
* place it after the end of the largest possible heap.
|
|
|
|
*
|
|
|
|
* There should really be a pmap call to determine a reasonable
|
|
|
|
* location.
|
|
|
|
*/
|
2004-02-04 21:52:57 +00:00
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
if (addr == 0 ||
|
|
|
|
(addr >= round_page((vm_offset_t)vms->vm_taddr) &&
|
|
|
|
addr < round_page((vm_offset_t)vms->vm_daddr +
|
|
|
|
lim_max(td->td_proc, RLIMIT_DATA))))
|
|
|
|
addr = round_page((vm_offset_t)vms->vm_daddr +
|
|
|
|
lim_max(td->td_proc, RLIMIT_DATA));
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2004-03-01 02:44:33 +00:00
|
|
|
if (flags & MAP_ANON) {
|
|
|
|
/*
|
|
|
|
* Mapping blank space is trivial.
|
|
|
|
*/
|
|
|
|
handle = NULL;
|
2005-04-01 20:00:11 +00:00
|
|
|
handle_type = OBJT_DEFAULT;
|
2004-03-01 02:44:33 +00:00
|
|
|
maxprot = VM_PROT_ALL;
|
2011-08-11 12:30:23 +00:00
|
|
|
cap_maxprot = VM_PROT_ALL;
|
2004-03-01 02:44:33 +00:00
|
|
|
} else {
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2011-08-11 12:30:23 +00:00
|
|
|
* Mapping file, get fp for validation and don't let the
|
|
|
|
* descriptor disappear on us if we block. Check capability
|
|
|
|
* rights, but also return the maximum rights to be combined
|
|
|
|
* with maxprot later.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_init(&rights, CAP_MMAP);
|
2011-08-11 12:30:23 +00:00
|
|
|
if (prot & PROT_READ)
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(&rights, CAP_MMAP_R);
|
2011-08-11 12:30:23 +00:00
|
|
|
if ((flags & MAP_SHARED) != 0) {
|
|
|
|
if (prot & PROT_WRITE)
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(&rights, CAP_MMAP_W);
|
2011-08-11 12:30:23 +00:00
|
|
|
}
|
|
|
|
if (prot & PROT_EXEC)
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(&rights, CAP_MMAP_X);
|
|
|
|
error = fget_mmap(td, uap->fd, &rights, &cap_maxprot, &fp);
|
|
|
|
if (error != 0)
|
2002-01-13 11:58:06 +00:00
|
|
|
goto done;
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
if (fp->f_type == DTYPE_SHM) {
|
|
|
|
handle = fp->f_data;
|
|
|
|
handle_type = OBJT_SWAP;
|
|
|
|
maxprot = VM_PROT_NONE;
|
|
|
|
|
|
|
|
/* FREAD should always be set. */
|
|
|
|
if (fp->f_flag & FREAD)
|
|
|
|
maxprot |= VM_PROT_EXECUTE | VM_PROT_READ;
|
|
|
|
if (fp->f_flag & FWRITE)
|
|
|
|
maxprot |= VM_PROT_WRITE;
|
|
|
|
goto map;
|
|
|
|
}
|
2001-05-23 22:17:43 +00:00
|
|
|
if (fp->f_type != DTYPE_VNODE) {
|
2006-04-21 07:17:25 +00:00
|
|
|
error = ENODEV;
|
2002-01-13 11:58:06 +00:00
|
|
|
goto done;
|
2001-05-23 22:17:43 +00:00
|
|
|
}
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
#if defined(COMPAT_FREEBSD7) || defined(COMPAT_FREEBSD6) || \
|
|
|
|
defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4)
|
2000-04-22 15:22:31 +00:00
|
|
|
/*
|
|
|
|
* POSIX shared-memory objects are defined to have
|
|
|
|
* kernel persistence, and are not defined to support
|
|
|
|
* read(2)/write(2) -- or even open(2). Thus, we can
|
|
|
|
* use MAP_ASYNC to trade on-disk coherence for speed.
|
|
|
|
* The shm_open(3) library routine turns on the FPOSIXSHM
|
|
|
|
* flag to request this behavior.
|
|
|
|
*/
|
|
|
|
if (fp->f_flag & FPOSIXSHM)
|
|
|
|
flags |= MAP_NOSYNC;
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
#endif
|
2003-06-22 08:41:43 +00:00
|
|
|
vp = fp->f_vnode;
|
2003-06-21 08:27:06 +00:00
|
|
|
/*
|
|
|
|
* Ensure that file and memory protections are
|
|
|
|
* compatible. Note that we only worry about
|
|
|
|
* writability if mapping is shared; in this case,
|
|
|
|
* current and max prot are dictated by the open file.
|
|
|
|
* XXX use the vnode instead? Problem is: what
|
|
|
|
* credentials do we use for determination? What if
|
|
|
|
* proc does a setuid?
|
|
|
|
*/
|
2004-05-11 10:26:37 +00:00
|
|
|
if (vp->v_mount != NULL && vp->v_mount->mnt_flag & MNT_NOEXEC)
|
2004-03-18 20:58:51 +00:00
|
|
|
maxprot = VM_PROT_NONE;
|
|
|
|
else
|
|
|
|
maxprot = VM_PROT_EXECUTE;
|
2003-06-21 08:27:06 +00:00
|
|
|
if (fp->f_flag & FREAD) {
|
|
|
|
maxprot |= VM_PROT_READ;
|
|
|
|
} else if (prot & PROT_READ) {
|
|
|
|
error = EACCES;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If we are sharing potential changes (either via
|
|
|
|
* MAP_SHARED or via the implicit sharing of character
|
|
|
|
* device mappings), and we are trying to get write
|
|
|
|
* permission although we opened it without asking
|
2004-02-27 22:02:15 +00:00
|
|
|
* for it, bail out.
|
2003-06-21 08:27:06 +00:00
|
|
|
*/
|
2004-04-05 04:54:22 +00:00
|
|
|
if ((flags & MAP_SHARED) != 0) {
|
2003-06-21 08:27:06 +00:00
|
|
|
if ((fp->f_flag & FWRITE) != 0) {
|
2004-02-27 22:02:15 +00:00
|
|
|
maxprot |= VM_PROT_WRITE;
|
2003-06-21 08:27:06 +00:00
|
|
|
} else if ((prot & PROT_WRITE) != 0) {
|
|
|
|
error = EACCES;
|
|
|
|
goto done;
|
2000-11-18 21:01:04 +00:00
|
|
|
}
|
2004-04-05 04:54:22 +00:00
|
|
|
} else if (vp->v_type != VCHR || (fp->f_flag & FWRITE) != 0) {
|
2003-06-21 08:27:06 +00:00
|
|
|
maxprot |= VM_PROT_WRITE;
|
2011-08-11 12:30:23 +00:00
|
|
|
cap_maxprot |= VM_PROT_WRITE;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2003-06-21 08:27:06 +00:00
|
|
|
handle = (void *)vp;
|
2005-04-01 20:00:11 +00:00
|
|
|
handle_type = OBJT_VNODE;
|
2004-03-01 02:44:33 +00:00
|
|
|
}
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
map:
|
2008-09-20 19:56:02 +00:00
|
|
|
td->td_fpop = fp;
|
2011-08-11 12:30:23 +00:00
|
|
|
maxprot &= cap_maxprot;
|
2004-02-27 22:02:15 +00:00
|
|
|
error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
|
2005-04-01 20:00:11 +00:00
|
|
|
flags, handle_type, handle, pos);
|
2008-09-20 19:56:02 +00:00
|
|
|
td->td_fpop = NULL;
|
2006-03-26 12:20:54 +00:00
|
|
|
#ifdef HWPMC_HOOKS
|
|
|
|
/* inform hwpmc(4) if an executable is being mapped */
|
|
|
|
if (error == 0 && handle_type == OBJT_VNODE &&
|
|
|
|
(prot & PROT_EXEC)) {
|
|
|
|
pkm.pm_file = handle;
|
|
|
|
pkm.pm_address = (uintptr_t) addr;
|
|
|
|
PMC_CALL_HOOK(td, PMC_FN_MMAP, (void *) &pkm);
|
|
|
|
}
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
if (error == 0)
|
2001-09-12 08:38:13 +00:00
|
|
|
td->td_retval[0] = (register_t) (addr + pageoff);
|
2000-11-18 21:01:04 +00:00
|
|
|
done:
|
|
|
|
if (fp)
|
2001-09-12 08:38:13 +00:00
|
|
|
fdrop(fp, td);
|
2002-07-06 22:14:38 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2007-07-04 22:57:21 +00:00
|
|
|
int
|
|
|
|
freebsd6_mmap(struct thread *td, struct freebsd6_mmap_args *uap)
|
|
|
|
{
|
|
|
|
struct mmap_args oargs;
|
|
|
|
|
|
|
|
oargs.addr = uap->addr;
|
|
|
|
oargs.len = uap->len;
|
|
|
|
oargs.prot = uap->prot;
|
|
|
|
oargs.flags = uap->flags;
|
|
|
|
oargs.fd = uap->fd;
|
|
|
|
oargs.pos = uap->pos;
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_mmap(td, &oargs));
|
2007-07-04 22:57:21 +00:00
|
|
|
}
|
|
|
|
|
1994-10-09 01:52:19 +00:00
|
|
|
#ifdef COMPAT_43
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-10-09 01:52:19 +00:00
|
|
|
struct ommap_args {
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
caddr_t addr;
|
|
|
|
int len;
|
|
|
|
int prot;
|
|
|
|
int flags;
|
|
|
|
int fd;
|
|
|
|
long pos;
|
1994-10-09 01:52:19 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-10-09 01:52:19 +00:00
|
|
|
int
|
2001-09-12 08:38:13 +00:00
|
|
|
ommap(td, uap)
|
|
|
|
struct thread *td;
|
2001-07-04 19:00:13 +00:00
|
|
|
struct ommap_args *uap;
|
1994-10-09 01:52:19 +00:00
|
|
|
{
|
|
|
|
struct mmap_args nargs;
|
|
|
|
static const char cvtbsdprot[8] = {
|
|
|
|
0,
|
|
|
|
PROT_EXEC,
|
|
|
|
PROT_WRITE,
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
PROT_EXEC | PROT_WRITE,
|
1994-10-09 01:52:19 +00:00
|
|
|
PROT_READ,
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
PROT_EXEC | PROT_READ,
|
|
|
|
PROT_WRITE | PROT_READ,
|
|
|
|
PROT_EXEC | PROT_WRITE | PROT_READ,
|
1994-10-09 01:52:19 +00:00
|
|
|
};
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
1994-10-09 01:52:19 +00:00
|
|
|
#define OMAP_ANON 0x0002
|
|
|
|
#define OMAP_COPY 0x0020
|
|
|
|
#define OMAP_SHARED 0x0010
|
|
|
|
#define OMAP_FIXED 0x0100
|
|
|
|
|
|
|
|
nargs.addr = uap->addr;
|
|
|
|
nargs.len = uap->len;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
nargs.prot = cvtbsdprot[uap->prot & 0x7];
|
2012-08-14 12:11:48 +00:00
|
|
|
#ifdef COMPAT_FREEBSD32
|
|
|
|
#if defined(__amd64__) || defined(__ia64__)
|
|
|
|
if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
|
|
|
|
nargs.prot != 0)
|
|
|
|
nargs.prot |= PROT_EXEC;
|
|
|
|
#endif
|
|
|
|
#endif
|
1994-10-09 01:52:19 +00:00
|
|
|
nargs.flags = 0;
|
|
|
|
if (uap->flags & OMAP_ANON)
|
|
|
|
nargs.flags |= MAP_ANON;
|
|
|
|
if (uap->flags & OMAP_COPY)
|
|
|
|
nargs.flags |= MAP_COPY;
|
|
|
|
if (uap->flags & OMAP_SHARED)
|
|
|
|
nargs.flags |= MAP_SHARED;
|
|
|
|
else
|
|
|
|
nargs.flags |= MAP_PRIVATE;
|
|
|
|
if (uap->flags & OMAP_FIXED)
|
|
|
|
nargs.flags |= MAP_FIXED;
|
|
|
|
nargs.fd = uap->fd;
|
|
|
|
nargs.pos = uap->pos;
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_mmap(td, &nargs));
|
1994-10-09 01:52:19 +00:00
|
|
|
}
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-10-09 01:52:19 +00:00
|
|
|
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct msync_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
2007-10-18 22:47:39 +00:00
|
|
|
size_t len;
|
1995-03-25 16:55:46 +00:00
|
|
|
int flags;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_msync(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct msync_args *uap;
|
|
|
|
{
|
|
|
|
vm_offset_t addr;
|
1996-02-23 18:49:25 +00:00
|
|
|
vm_size_t size, pageoff;
|
1995-03-25 16:55:46 +00:00
|
|
|
int flags;
|
1994-05-24 10:09:53 +00:00
|
|
|
vm_map_t map;
|
|
|
|
int rv;
|
|
|
|
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
addr = (vm_offset_t) uap->addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size = uap->len;
|
1995-03-25 16:55:46 +00:00
|
|
|
flags = uap->flags;
|
|
|
|
|
1996-02-23 18:49:25 +00:00
|
|
|
pageoff = (addr & PAGE_MASK);
|
|
|
|
addr -= pageoff;
|
|
|
|
size += pageoff;
|
|
|
|
size = (vm_size_t) round_page(size);
|
1996-03-02 17:14:09 +00:00
|
|
|
if (addr + size < addr)
|
2002-03-10 21:52:48 +00:00
|
|
|
return (EINVAL);
|
1996-02-23 18:49:25 +00:00
|
|
|
|
|
|
|
if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE))
|
1995-03-25 17:36:00 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2001-09-12 08:38:13 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
1996-03-02 17:14:09 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Clean the pages and interpret the return value.
|
|
|
|
*/
|
2003-11-09 05:25:35 +00:00
|
|
|
rv = vm_map_sync(map, addr, addr + size, (flags & MS_ASYNC) == 0,
|
1995-03-25 16:55:46 +00:00
|
|
|
(flags & MS_INVALIDATE) != 0);
|
1994-05-24 10:09:53 +00:00
|
|
|
switch (rv) {
|
|
|
|
case KERN_SUCCESS:
|
2002-03-10 21:52:48 +00:00
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
case KERN_INVALID_ADDRESS:
|
|
|
|
return (EINVAL); /* Sun returns ENOMEM? */
|
2003-11-14 06:55:11 +00:00
|
|
|
case KERN_INVALID_ARGUMENT:
|
|
|
|
return (EBUSY);
|
2012-03-17 23:00:32 +00:00
|
|
|
case KERN_FAILURE:
|
|
|
|
return (EIO);
|
1994-05-24 10:09:53 +00:00
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct munmap_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_munmap(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
2001-07-04 19:00:13 +00:00
|
|
|
struct munmap_args *uap;
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-03-26 12:20:54 +00:00
|
|
|
#ifdef HWPMC_HOOKS
|
|
|
|
struct pmckern_map_out pkm;
|
|
|
|
vm_map_entry_t entry;
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
vm_offset_t addr;
|
1996-02-23 18:49:25 +00:00
|
|
|
vm_size_t size, pageoff;
|
1994-05-24 10:09:53 +00:00
|
|
|
vm_map_t map;
|
|
|
|
|
|
|
|
addr = (vm_offset_t) uap->addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size = uap->len;
|
2003-11-10 01:37:40 +00:00
|
|
|
if (size == 0)
|
|
|
|
return (EINVAL);
|
1996-02-23 18:49:25 +00:00
|
|
|
|
|
|
|
pageoff = (addr & PAGE_MASK);
|
|
|
|
addr -= pageoff;
|
|
|
|
size += pageoff;
|
|
|
|
size = (vm_size_t) round_page(size);
|
1996-03-02 17:14:09 +00:00
|
|
|
if (addr + size < addr)
|
2002-03-10 21:52:48 +00:00
|
|
|
return (EINVAL);
|
1996-03-02 17:14:09 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2002-09-21 22:07:17 +00:00
|
|
|
* Check for illegal addresses. Watch out for address wrap...
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2001-09-12 08:38:13 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
2002-09-21 22:07:17 +00:00
|
|
|
if (addr < vm_map_min(map) || addr + size > vm_map_max(map))
|
|
|
|
return (EINVAL);
|
2003-11-10 01:37:40 +00:00
|
|
|
vm_map_lock(map);
|
2006-03-26 12:20:54 +00:00
|
|
|
#ifdef HWPMC_HOOKS
|
|
|
|
/*
|
|
|
|
* Inform hwpmc if the address range being unmapped contains
|
|
|
|
* an executable region.
|
|
|
|
*/
|
2010-09-07 00:23:45 +00:00
|
|
|
pkm.pm_address = (uintptr_t) NULL;
|
2006-03-26 12:20:54 +00:00
|
|
|
if (vm_map_lookup_entry(map, addr, &entry)) {
|
|
|
|
for (;
|
|
|
|
entry != &map->header && entry->start < addr + size;
|
|
|
|
entry = entry->next) {
|
|
|
|
if (vm_map_check_protection(map, entry->start,
|
|
|
|
entry->end, VM_PROT_EXECUTE) == TRUE) {
|
|
|
|
pkm.pm_address = (uintptr_t) addr;
|
|
|
|
pkm.pm_size = (size_t) size;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2009-02-24 20:57:43 +00:00
|
|
|
vm_map_delete(map, addr, addr + size);
|
2010-09-07 00:23:45 +00:00
|
|
|
|
|
|
|
#ifdef HWPMC_HOOKS
|
|
|
|
/* downgrade the lock to prevent a LOR with the pmc-sx lock */
|
|
|
|
vm_map_lock_downgrade(map);
|
2010-09-07 02:51:11 +00:00
|
|
|
if (pkm.pm_address != (uintptr_t) NULL)
|
2010-09-07 00:23:45 +00:00
|
|
|
PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm);
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
#else
|
2003-11-10 01:37:40 +00:00
|
|
|
vm_map_unlock(map);
|
2010-09-07 00:23:45 +00:00
|
|
|
#endif
|
|
|
|
/* vm_map_delete returns nothing but KERN_SUCCESS anyway */
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mprotect_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
const void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
int prot;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_mprotect(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mprotect_args *uap;
|
|
|
|
{
|
|
|
|
vm_offset_t addr;
|
1996-02-23 18:49:25 +00:00
|
|
|
vm_size_t size, pageoff;
|
2001-07-04 19:00:13 +00:00
|
|
|
vm_prot_t prot;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
addr = (vm_offset_t) uap->addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size = uap->len;
|
1994-05-24 10:09:53 +00:00
|
|
|
prot = uap->prot & VM_PROT_ALL;
|
|
|
|
|
1996-02-23 18:49:25 +00:00
|
|
|
pageoff = (addr & PAGE_MASK);
|
|
|
|
addr -= pageoff;
|
|
|
|
size += pageoff;
|
|
|
|
size = (vm_size_t) round_page(size);
|
1996-03-02 17:14:09 +00:00
|
|
|
if (addr + size < addr)
|
2002-03-10 21:52:48 +00:00
|
|
|
return (EINVAL);
|
1996-02-23 18:49:25 +00:00
|
|
|
|
2002-05-18 03:58:16 +00:00
|
|
|
switch (vm_map_protect(&td->td_proc->p_vmspace->vm_map, addr,
|
|
|
|
addr + size, prot, FALSE)) {
|
1994-05-24 10:09:53 +00:00
|
|
|
case KERN_SUCCESS:
|
|
|
|
return (0);
|
|
|
|
case KERN_PROTECTION_FAILURE:
|
|
|
|
return (EACCES);
|
Implement global and per-uid accounting of the anonymous memory. Add
rlimit RLIMIT_SWAP that limits the amount of swap that may be reserved
for the uid.
The accounting information (charge) is associated with either map entry,
or vm object backing the entry, assuming the object is the first one
in the shadow chain and entry does not require COW. Charge is moved
from entry to object on allocation of the object, e.g. during the mmap,
assuming the object is allocated, or on the first page fault on the
entry. It moves back to the entry on forks due to COW setup.
The per-entry granularity of accounting makes the charge process fair
for processes that change uid during lifetime, and decrements charge
for proper uid when region is unmapped.
The interface of vm_pager_allocate(9) is extended by adding struct ucred *,
that is used to charge appropriate uid when allocation if performed by
kernel, e.g. md(4).
Several syscalls, among them is fork(2), may now return ENOMEM when
global or per-uid limits are enforced.
In collaboration with: pho
Reviewed by: alc
Approved by: re (kensmith)
2009-06-23 20:45:22 +00:00
|
|
|
case KERN_RESOURCE_SHORTAGE:
|
|
|
|
return (ENOMEM);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
1996-02-23 18:49:25 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct minherit_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
1996-02-23 18:49:25 +00:00
|
|
|
int inherit;
|
|
|
|
};
|
|
|
|
#endif
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1996-02-23 18:49:25 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_minherit(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1996-02-23 18:49:25 +00:00
|
|
|
struct minherit_args *uap;
|
|
|
|
{
|
|
|
|
vm_offset_t addr;
|
|
|
|
vm_size_t size, pageoff;
|
2001-07-04 19:00:13 +00:00
|
|
|
vm_inherit_t inherit;
|
1996-02-23 18:49:25 +00:00
|
|
|
|
|
|
|
addr = (vm_offset_t)uap->addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size = uap->len;
|
1996-02-23 18:49:25 +00:00
|
|
|
inherit = uap->inherit;
|
|
|
|
|
|
|
|
pageoff = (addr & PAGE_MASK);
|
|
|
|
addr -= pageoff;
|
|
|
|
size += pageoff;
|
|
|
|
size = (vm_size_t) round_page(size);
|
1996-03-02 17:14:09 +00:00
|
|
|
if (addr + size < addr)
|
2002-03-10 21:52:48 +00:00
|
|
|
return (EINVAL);
|
1996-02-23 18:49:25 +00:00
|
|
|
|
2002-05-18 18:59:00 +00:00
|
|
|
switch (vm_map_inherit(&td->td_proc->p_vmspace->vm_map, addr,
|
|
|
|
addr + size, inherit)) {
|
1996-02-23 18:49:25 +00:00
|
|
|
case KERN_SUCCESS:
|
|
|
|
return (0);
|
|
|
|
case KERN_PROTECTION_FAILURE:
|
|
|
|
return (EACCES);
|
|
|
|
}
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct madvise_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
int behav;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_madvise(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct madvise_args *uap;
|
|
|
|
{
|
1996-05-31 00:38:04 +00:00
|
|
|
vm_offset_t start, end;
|
2002-09-21 22:07:17 +00:00
|
|
|
vm_map_t map;
|
2013-09-19 18:53:42 +00:00
|
|
|
int flags;
|
1999-09-21 05:00:48 +00:00
|
|
|
|
2003-03-31 21:09:57 +00:00
|
|
|
/*
|
|
|
|
* Check for our special case, advising the swap pager we are
|
|
|
|
* "immortal."
|
|
|
|
*/
|
|
|
|
if (uap->behav == MADV_PROTECT) {
|
2013-09-19 18:53:42 +00:00
|
|
|
flags = PPROT_SET;
|
|
|
|
return (kern_procctl(td, P_PID, td->td_proc->p_pid,
|
|
|
|
PROC_SPROTECT, &flags));
|
2003-03-31 21:09:57 +00:00
|
|
|
}
|
2013-09-19 18:53:42 +00:00
|
|
|
|
1999-09-21 05:00:48 +00:00
|
|
|
/*
|
|
|
|
* Check for illegal behavior
|
|
|
|
*/
|
2000-02-28 04:10:35 +00:00
|
|
|
if (uap->behav < 0 || uap->behav > MADV_CORE)
|
1999-09-21 05:00:48 +00:00
|
|
|
return (EINVAL);
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Check for illegal addresses. Watch out for address wrap... Note
|
|
|
|
* that VM_*_ADDRESS are not constants due to casts (argh).
|
|
|
|
*/
|
2002-09-21 22:07:17 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
|
|
|
if ((vm_offset_t)uap->addr < vm_map_min(map) ||
|
|
|
|
(vm_offset_t)uap->addr + uap->len > vm_map_max(map))
|
1996-05-19 07:36:50 +00:00
|
|
|
return (EINVAL);
|
|
|
|
if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since this routine is only advisory, we default to conservative
|
|
|
|
* behavior.
|
|
|
|
*/
|
1996-09-19 10:12:41 +00:00
|
|
|
start = trunc_page((vm_offset_t) uap->addr);
|
|
|
|
end = round_page((vm_offset_t) uap->addr + uap->len);
|
2003-12-08 02:45:45 +00:00
|
|
|
|
2002-09-21 22:07:17 +00:00
|
|
|
if (vm_map_madvise(map, start, end, uap->behav))
|
2002-05-18 07:48:06 +00:00
|
|
|
return (EINVAL);
|
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mincore_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
const void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
char *vec;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_mincore(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mincore_args *uap;
|
|
|
|
{
|
1996-05-19 07:36:50 +00:00
|
|
|
vm_offset_t addr, first_addr;
|
|
|
|
vm_offset_t end, cend;
|
|
|
|
pmap_t pmap;
|
|
|
|
vm_map_t map;
|
1995-10-21 17:42:28 +00:00
|
|
|
char *vec;
|
2001-08-31 01:26:30 +00:00
|
|
|
int error = 0;
|
1996-05-19 07:36:50 +00:00
|
|
|
int vecindex, lastvecindex;
|
2001-07-04 19:00:13 +00:00
|
|
|
vm_map_entry_t current;
|
1996-05-19 07:36:50 +00:00
|
|
|
vm_map_entry_t entry;
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
vm_object_t object;
|
|
|
|
vm_paddr_t locked_pa;
|
|
|
|
vm_page_t m;
|
|
|
|
vm_pindex_t pindex;
|
1996-05-19 07:36:50 +00:00
|
|
|
int mincoreinfo;
|
1999-03-02 22:55:02 +00:00
|
|
|
unsigned int timestamp;
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
boolean_t locked;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Make sure that the addresses presented are valid for user
|
|
|
|
* mode.
|
|
|
|
*/
|
|
|
|
first_addr = addr = trunc_page((vm_offset_t) uap->addr);
|
1996-03-02 17:14:09 +00:00
|
|
|
end = addr + (vm_size_t)round_page(uap->len);
|
2002-09-21 22:07:17 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
|
|
|
if (end > vm_map_max(map) || end < addr)
|
2006-06-21 12:59:05 +00:00
|
|
|
return (ENOMEM);
|
1995-10-21 17:42:28 +00:00
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Address of byte vector
|
|
|
|
*/
|
1995-10-21 17:42:28 +00:00
|
|
|
vec = uap->vec;
|
1996-05-19 07:36:50 +00:00
|
|
|
|
2001-09-12 08:38:13 +00:00
|
|
|
pmap = vmspace_pmap(td->td_proc->p_vmspace);
|
1996-05-19 07:36:50 +00:00
|
|
|
|
1999-03-01 20:42:16 +00:00
|
|
|
vm_map_lock_read(map);
|
1999-03-02 22:55:02 +00:00
|
|
|
RestartScan:
|
|
|
|
timestamp = map->timestamp;
|
1996-05-19 07:36:50 +00:00
|
|
|
|
2006-06-21 12:59:05 +00:00
|
|
|
if (!vm_map_lookup_entry(map, addr, &entry)) {
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
1996-05-19 07:36:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do this on a map entry basis so that if the pages are not
|
|
|
|
* in the current processes address space, we can easily look
|
|
|
|
* up the pages elsewhere.
|
|
|
|
*/
|
|
|
|
lastvecindex = -1;
|
2001-07-04 19:00:13 +00:00
|
|
|
for (current = entry;
|
|
|
|
(current != &map->header) && (current->start < end);
|
|
|
|
current = current->next) {
|
1996-05-19 07:36:50 +00:00
|
|
|
|
2006-06-21 12:59:05 +00:00
|
|
|
/*
|
|
|
|
* check for contiguity
|
|
|
|
*/
|
|
|
|
if (current->end < end &&
|
|
|
|
(entry->next == &map->header ||
|
|
|
|
current->next->start > current->end)) {
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* ignore submaps (for now) or null objects
|
|
|
|
*/
|
1999-02-07 21:48:23 +00:00
|
|
|
if ((current->eflags & MAP_ENTRY_IS_SUB_MAP) ||
|
1996-05-19 07:36:50 +00:00
|
|
|
current->object.vm_object == NULL)
|
|
|
|
continue;
|
2003-12-08 02:45:45 +00:00
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* limit this scan to the current map entry and the
|
|
|
|
* limits for the mincore call
|
|
|
|
*/
|
|
|
|
if (addr < current->start)
|
|
|
|
addr = current->start;
|
|
|
|
cend = current->end;
|
|
|
|
if (cend > end)
|
|
|
|
cend = end;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* scan this entry one page at a time
|
|
|
|
*/
|
2001-07-04 19:00:13 +00:00
|
|
|
while (addr < cend) {
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Check pmap first, it is likely faster, also
|
|
|
|
* it can provide info as to whether we are the
|
|
|
|
* one referencing or modifying the page.
|
|
|
|
*/
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
object = NULL;
|
|
|
|
locked_pa = 0;
|
|
|
|
retry:
|
|
|
|
m = NULL;
|
|
|
|
mincoreinfo = pmap_mincore(pmap, addr, &locked_pa);
|
|
|
|
if (locked_pa != 0) {
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
* The page is mapped by this process but not
|
|
|
|
* both accessed and modified. It is also
|
|
|
|
* managed. Acquire the object lock so that
|
|
|
|
* other mappings might be examined.
|
1996-05-19 07:36:50 +00:00
|
|
|
*/
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
m = PHYS_TO_VM_PAGE(locked_pa);
|
|
|
|
if (m->object != object) {
|
|
|
|
if (object != NULL)
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WUNLOCK(object);
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
object = m->object;
|
2013-03-09 02:32:23 +00:00
|
|
|
locked = VM_OBJECT_TRYWLOCK(object);
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
vm_page_unlock(m);
|
|
|
|
if (!locked) {
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WLOCK(object);
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
vm_page_lock(m);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
vm_page_unlock(m);
|
|
|
|
KASSERT(m->valid == VM_PAGE_BITS_ALL,
|
|
|
|
("mincore: page %p is mapped but invalid",
|
|
|
|
m));
|
|
|
|
} else if (mincoreinfo == 0) {
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
* The page is not mapped by this process. If
|
|
|
|
* the object implements managed pages, then
|
|
|
|
* determine if the page is resident so that
|
|
|
|
* the mappings might be examined.
|
1996-05-19 07:36:50 +00:00
|
|
|
*/
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (current->object.vm_object != object) {
|
|
|
|
if (object != NULL)
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WUNLOCK(object);
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
object = current->object.vm_object;
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WLOCK(object);
|
1996-05-19 07:36:50 +00:00
|
|
|
}
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (object->type == OBJT_DEFAULT ||
|
|
|
|
object->type == OBJT_SWAP ||
|
|
|
|
object->type == OBJT_VNODE) {
|
|
|
|
pindex = OFF_TO_IDX(current->offset +
|
|
|
|
(addr - current->start));
|
|
|
|
m = vm_page_lookup(object, pindex);
|
2012-04-08 18:25:12 +00:00
|
|
|
if (m == NULL &&
|
|
|
|
vm_page_is_cached(object, pindex))
|
|
|
|
mincoreinfo = MINCORE_INCORE;
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (m != NULL && m->valid == 0)
|
|
|
|
m = NULL;
|
|
|
|
if (m != NULL)
|
|
|
|
mincoreinfo = MINCORE_INCORE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m != NULL) {
|
|
|
|
/* Examine other mappings to the page. */
|
|
|
|
if (m->dirty == 0 && pmap_is_modified(m))
|
|
|
|
vm_page_dirty(m);
|
|
|
|
if (m->dirty != 0)
|
|
|
|
mincoreinfo |= MINCORE_MODIFIED_OTHER;
|
2010-05-26 18:00:44 +00:00
|
|
|
/*
|
2011-09-06 10:30:11 +00:00
|
|
|
* The first test for PGA_REFERENCED is an
|
2010-05-26 18:00:44 +00:00
|
|
|
* optimization. The second test is
|
|
|
|
* required because a concurrent pmap
|
|
|
|
* operation could clear the last reference
|
2011-09-06 10:30:11 +00:00
|
|
|
* and set PGA_REFERENCED before the call to
|
2010-05-26 18:00:44 +00:00
|
|
|
* pmap_is_referenced().
|
|
|
|
*/
|
2011-09-06 10:30:11 +00:00
|
|
|
if ((m->aflags & PGA_REFERENCED) != 0 ||
|
2010-05-26 18:00:44 +00:00
|
|
|
pmap_is_referenced(m) ||
|
2011-09-06 10:30:11 +00:00
|
|
|
(m->aflags & PGA_REFERENCED) != 0)
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
mincoreinfo |= MINCORE_REFERENCED_OTHER;
|
1996-05-19 07:36:50 +00:00
|
|
|
}
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (object != NULL)
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WUNLOCK(object);
|
1996-05-19 07:36:50 +00:00
|
|
|
|
1999-03-02 22:55:02 +00:00
|
|
|
/*
|
|
|
|
* subyte may page fault. In case it needs to modify
|
|
|
|
* the map, we release the lock.
|
|
|
|
*/
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* calculate index into user supplied byte vector
|
|
|
|
*/
|
|
|
|
vecindex = OFF_TO_IDX(addr - first_addr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have skipped map entries, we need to make sure that
|
|
|
|
* the byte vector is zeroed for those skipped entries.
|
|
|
|
*/
|
2001-07-04 19:00:13 +00:00
|
|
|
while ((lastvecindex + 1) < vecindex) {
|
2013-09-12 20:46:32 +00:00
|
|
|
++lastvecindex;
|
2002-03-10 21:52:48 +00:00
|
|
|
error = subyte(vec + lastvecindex, 0);
|
1996-05-19 07:36:50 +00:00
|
|
|
if (error) {
|
2001-08-31 01:26:30 +00:00
|
|
|
error = EFAULT;
|
|
|
|
goto done2;
|
1996-05-19 07:36:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pass the page information to the user
|
|
|
|
*/
|
2002-03-10 21:52:48 +00:00
|
|
|
error = subyte(vec + vecindex, mincoreinfo);
|
1996-05-19 07:36:50 +00:00
|
|
|
if (error) {
|
2001-08-31 01:26:30 +00:00
|
|
|
error = EFAULT;
|
|
|
|
goto done2;
|
1996-05-19 07:36:50 +00:00
|
|
|
}
|
1999-03-02 22:55:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the map has changed, due to the subyte, the previous
|
|
|
|
* output may be invalid.
|
|
|
|
*/
|
|
|
|
vm_map_lock_read(map);
|
|
|
|
if (timestamp != map->timestamp)
|
|
|
|
goto RestartScan;
|
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
lastvecindex = vecindex;
|
|
|
|
addr += PAGE_SIZE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-02 22:55:02 +00:00
|
|
|
/*
|
|
|
|
* subyte may page fault. In case it needs to modify
|
|
|
|
* the map, we release the lock.
|
|
|
|
*/
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Zero the last entries in the byte vector.
|
|
|
|
*/
|
|
|
|
vecindex = OFF_TO_IDX(end - first_addr);
|
2001-07-04 19:00:13 +00:00
|
|
|
while ((lastvecindex + 1) < vecindex) {
|
2013-09-12 20:46:32 +00:00
|
|
|
++lastvecindex;
|
2002-03-10 21:52:48 +00:00
|
|
|
error = subyte(vec + lastvecindex, 0);
|
1996-05-19 07:36:50 +00:00
|
|
|
if (error) {
|
2001-08-31 01:26:30 +00:00
|
|
|
error = EFAULT;
|
|
|
|
goto done2;
|
1995-10-21 17:42:28 +00:00
|
|
|
}
|
|
|
|
}
|
2003-12-08 02:45:45 +00:00
|
|
|
|
1999-03-02 22:55:02 +00:00
|
|
|
/*
|
|
|
|
* If the map has changed, due to the subyte, the previous
|
|
|
|
* output may be invalid.
|
|
|
|
*/
|
|
|
|
vm_map_lock_read(map);
|
|
|
|
if (timestamp != map->timestamp)
|
|
|
|
goto RestartScan;
|
1999-03-01 20:42:16 +00:00
|
|
|
vm_map_unlock_read(map);
|
2001-08-31 01:26:30 +00:00
|
|
|
done2:
|
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mlock_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
const void *addr;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
size_t len;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_mlock(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mlock_args *uap;
|
|
|
|
{
|
2013-06-08 13:13:40 +00:00
|
|
|
|
|
|
|
return (vm_mlock(td->td_proc, td->td_ucred, uap->addr, uap->len));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
vm_mlock(struct proc *proc, struct ucred *cred, const void *addr0, size_t len)
|
|
|
|
{
|
2004-03-15 09:11:23 +00:00
|
|
|
vm_offset_t addr, end, last, start;
|
|
|
|
vm_size_t npages, size;
|
2013-01-10 12:43:58 +00:00
|
|
|
vm_map_t map;
|
2011-04-05 20:23:59 +00:00
|
|
|
unsigned long nsize;
|
2004-03-15 09:11:23 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2013-06-08 13:13:40 +00:00
|
|
|
error = priv_check_cred(cred, PRIV_VM_MLOCK, 0);
|
2004-02-26 00:27:04 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2013-06-08 13:13:40 +00:00
|
|
|
addr = (vm_offset_t)addr0;
|
|
|
|
size = len;
|
2004-03-15 09:11:23 +00:00
|
|
|
last = addr + size;
|
2004-03-05 22:03:11 +00:00
|
|
|
start = trunc_page(addr);
|
2004-03-15 09:11:23 +00:00
|
|
|
end = round_page(last);
|
|
|
|
if (last < addr || end < addr)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
2004-03-05 22:03:11 +00:00
|
|
|
npages = atop(end - start);
|
|
|
|
if (npages > vm_page_max_wired)
|
|
|
|
return (ENOMEM);
|
2013-01-10 12:43:58 +00:00
|
|
|
map = &proc->p_vmspace->vm_map;
|
2004-02-26 00:27:04 +00:00
|
|
|
PROC_LOCK(proc);
|
2013-01-10 12:43:58 +00:00
|
|
|
nsize = ptoa(npages + pmap_wired_count(map->pmap));
|
2011-04-05 20:23:59 +00:00
|
|
|
if (nsize > lim_cur(proc, RLIMIT_MEMLOCK)) {
|
2004-02-26 00:27:04 +00:00
|
|
|
PROC_UNLOCK(proc);
|
1997-06-15 23:35:32 +00:00
|
|
|
return (ENOMEM);
|
2004-02-04 21:52:57 +00:00
|
|
|
}
|
2004-02-26 00:27:04 +00:00
|
|
|
PROC_UNLOCK(proc);
|
2007-05-31 22:52:15 +00:00
|
|
|
if (npages + cnt.v_wire_count > vm_page_max_wired)
|
2004-03-05 22:03:11 +00:00
|
|
|
return (EAGAIN);
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_LOCK(proc);
|
|
|
|
error = racct_set(proc, RACCT_MEMLOCK, nsize);
|
|
|
|
PROC_UNLOCK(proc);
|
|
|
|
if (error != 0)
|
|
|
|
return (ENOMEM);
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2013-01-10 12:43:58 +00:00
|
|
|
error = vm_map_wire(map, start, end,
|
2004-03-15 06:43:51 +00:00
|
|
|
VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2011-04-05 20:23:59 +00:00
|
|
|
if (error != KERN_SUCCESS) {
|
|
|
|
PROC_LOCK(proc);
|
|
|
|
racct_set(proc, RACCT_MEMLOCK,
|
2013-01-10 12:43:58 +00:00
|
|
|
ptoa(pmap_wired_count(map->pmap)));
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_UNLOCK(proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error == KERN_SUCCESS ? 0 : ENOMEM);
|
|
|
|
}
|
|
|
|
|
1997-06-15 23:35:32 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct mlockall_args {
|
|
|
|
int how;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1997-06-15 23:35:32 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_mlockall(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1997-06-15 23:35:32 +00:00
|
|
|
struct mlockall_args *uap;
|
|
|
|
{
|
2003-08-11 07:14:08 +00:00
|
|
|
vm_map_t map;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
2012-12-18 07:35:01 +00:00
|
|
|
error = priv_check(td, PRIV_VM_MLOCK);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2003-08-11 07:14:08 +00:00
|
|
|
|
|
|
|
if ((uap->how == 0) || ((uap->how & ~(MCL_CURRENT|MCL_FUTURE)) != 0))
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If wiring all pages in the process would cause it to exceed
|
|
|
|
* a hard resource limit, return ENOMEM.
|
|
|
|
*/
|
2012-12-18 07:35:01 +00:00
|
|
|
if (!old_mlock && uap->how & MCL_CURRENT) {
|
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
if (map->size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
2004-02-04 21:52:57 +00:00
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
error = racct_set(td->td_proc, RACCT_MEMLOCK, map->size);
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
if (error != 0)
|
|
|
|
return (ENOMEM);
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2003-08-11 07:14:08 +00:00
|
|
|
|
|
|
|
if (uap->how & MCL_FUTURE) {
|
|
|
|
vm_map_lock(map);
|
|
|
|
vm_map_modflags(map, MAP_WIREFUTURE, 0);
|
|
|
|
vm_map_unlock(map);
|
|
|
|
error = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uap->how & MCL_CURRENT) {
|
|
|
|
/*
|
|
|
|
* P1003.1-2001 mandates that all currently mapped pages
|
|
|
|
* will be memory resident and locked (wired) upon return
|
|
|
|
* from mlockall(). vm_map_wire() will wire pages, by
|
|
|
|
* calling vm_fault_wire() for each page in the region.
|
|
|
|
*/
|
|
|
|
error = vm_map_wire(map, vm_map_min(map), vm_map_max(map),
|
|
|
|
VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK);
|
|
|
|
error = (error == KERN_SUCCESS ? 0 : EAGAIN);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2011-04-05 20:23:59 +00:00
|
|
|
if (error != KERN_SUCCESS) {
|
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
racct_set(td->td_proc, RACCT_MEMLOCK,
|
2013-01-10 12:43:58 +00:00
|
|
|
ptoa(pmap_wired_count(map->pmap)));
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2003-08-11 07:14:08 +00:00
|
|
|
|
|
|
|
return (error);
|
1997-06-15 23:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
2002-06-06 18:51:14 +00:00
|
|
|
struct munlockall_args {
|
2003-08-11 07:14:08 +00:00
|
|
|
register_t dummy;
|
1997-06-15 23:35:32 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1997-06-15 23:35:32 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_munlockall(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1997-06-15 23:35:32 +00:00
|
|
|
struct munlockall_args *uap;
|
|
|
|
{
|
2003-08-11 07:14:08 +00:00
|
|
|
vm_map_t map;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VM_MUNLOCK);
|
2003-08-11 07:14:08 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
/* Clear the MAP_WIREFUTURE flag from this vm_map. */
|
|
|
|
vm_map_lock(map);
|
|
|
|
vm_map_modflags(map, 0, MAP_WIREFUTURE);
|
|
|
|
vm_map_unlock(map);
|
|
|
|
|
|
|
|
/* Forcibly unwire all pages. */
|
|
|
|
error = vm_map_unwire(map, vm_map_min(map), vm_map_max(map),
|
|
|
|
VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK);
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2011-04-05 20:23:59 +00:00
|
|
|
if (error == KERN_SUCCESS) {
|
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
racct_set(td->td_proc, RACCT_MEMLOCK, 0);
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2003-08-11 07:14:08 +00:00
|
|
|
|
|
|
|
return (error);
|
1997-06-15 23:35:32 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct munlock_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
const void *addr;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
size_t len;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
2001-08-31 01:26:30 +00:00
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_munlock(td, uap)
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct munlock_args *uap;
|
|
|
|
{
|
2004-03-15 09:11:23 +00:00
|
|
|
vm_offset_t addr, end, last, start;
|
2004-03-05 22:03:11 +00:00
|
|
|
vm_size_t size;
|
2013-07-22 22:16:47 +00:00
|
|
|
#ifdef RACCT
|
2013-07-22 21:47:14 +00:00
|
|
|
vm_map_t map;
|
2013-07-22 22:16:47 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
int error;
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VM_MUNLOCK);
|
2004-02-26 00:27:04 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2004-03-05 22:03:11 +00:00
|
|
|
addr = (vm_offset_t)uap->addr;
|
|
|
|
size = uap->len;
|
2004-03-15 09:11:23 +00:00
|
|
|
last = addr + size;
|
2004-03-05 22:03:11 +00:00
|
|
|
start = trunc_page(addr);
|
2004-03-15 09:11:23 +00:00
|
|
|
end = round_page(last);
|
|
|
|
if (last < addr || end < addr)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
2004-03-05 22:03:11 +00:00
|
|
|
error = vm_map_unwire(&td->td_proc->p_vmspace->vm_map, start, end,
|
2004-03-15 06:43:51 +00:00
|
|
|
VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2011-04-05 20:23:59 +00:00
|
|
|
if (error == KERN_SUCCESS) {
|
|
|
|
PROC_LOCK(td->td_proc);
|
2013-07-22 21:47:14 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
|
|
|
racct_set(td->td_proc, RACCT_MEMLOCK,
|
|
|
|
ptoa(pmap_wired_count(map->pmap)));
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error == KERN_SUCCESS ? 0 : ENOMEM);
|
|
|
|
}
|
|
|
|
|
2004-02-27 22:02:15 +00:00
|
|
|
/*
|
|
|
|
* vm_mmap_vnode()
|
|
|
|
*
|
|
|
|
* Helper function for vm_mmap. Perform sanity check specific for mmap
|
|
|
|
* operations on vnodes.
|
2012-02-23 21:07:16 +00:00
|
|
|
*
|
|
|
|
* For VCHR vnodes, the vnode lock is held over the call to
|
|
|
|
* vm_mmap_cdev() to keep vp->v_rdev valid.
|
2004-02-27 22:02:15 +00:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
vm_mmap_vnode(struct thread *td, vm_size_t objsize,
|
|
|
|
vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp,
|
2012-02-23 21:07:16 +00:00
|
|
|
struct vnode *vp, vm_ooffset_t *foffp, vm_object_t *objp,
|
|
|
|
boolean_t *writecounted)
|
2004-02-27 22:02:15 +00:00
|
|
|
{
|
|
|
|
struct vattr va;
|
|
|
|
vm_object_t obj;
|
2009-06-01 21:32:52 +00:00
|
|
|
vm_offset_t foff;
|
2005-01-24 10:48:29 +00:00
|
|
|
struct mount *mp;
|
2008-08-28 15:23:18 +00:00
|
|
|
struct ucred *cred;
|
2012-10-22 17:50:54 +00:00
|
|
|
int error, flags, locktype;
|
2004-02-27 22:02:15 +00:00
|
|
|
|
2005-01-24 10:48:29 +00:00
|
|
|
mp = vp->v_mount;
|
2008-08-28 15:23:18 +00:00
|
|
|
cred = td->td_ucred;
|
2012-02-23 21:07:16 +00:00
|
|
|
if ((*maxprotp & VM_PROT_WRITE) && (*flagsp & MAP_SHARED))
|
|
|
|
locktype = LK_EXCLUSIVE;
|
|
|
|
else
|
|
|
|
locktype = LK_SHARED;
|
2012-10-22 17:50:54 +00:00
|
|
|
if ((error = vget(vp, locktype, td)) != 0)
|
2004-02-27 22:02:15 +00:00
|
|
|
return (error);
|
2009-06-01 21:32:52 +00:00
|
|
|
foff = *foffp;
|
2004-02-27 22:02:15 +00:00
|
|
|
flags = *flagsp;
|
2005-01-25 00:40:01 +00:00
|
|
|
obj = vp->v_object;
|
2004-02-27 22:02:15 +00:00
|
|
|
if (vp->v_type == VREG) {
|
|
|
|
/*
|
|
|
|
* Get the proper underlying object
|
|
|
|
*/
|
2005-01-25 00:40:01 +00:00
|
|
|
if (obj == NULL) {
|
2004-02-27 22:02:15 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
2013-04-28 19:25:09 +00:00
|
|
|
if (obj->type == OBJT_VNODE && obj->handle != vp) {
|
2004-02-27 22:02:15 +00:00
|
|
|
vput(vp);
|
2012-02-23 21:07:16 +00:00
|
|
|
vp = (struct vnode *)obj->handle;
|
|
|
|
/*
|
|
|
|
* Bypass filesystems obey the mpsafety of the
|
2013-05-02 18:35:12 +00:00
|
|
|
* underlying fs. Tmpfs never bypasses.
|
2012-02-23 21:07:16 +00:00
|
|
|
*/
|
|
|
|
error = vget(vp, locktype, td);
|
2012-10-22 17:50:54 +00:00
|
|
|
if (error != 0)
|
2012-02-23 21:07:16 +00:00
|
|
|
return (error);
|
2012-02-24 10:41:58 +00:00
|
|
|
}
|
|
|
|
if (locktype == LK_EXCLUSIVE) {
|
|
|
|
*writecounted = TRUE;
|
|
|
|
vnode_pager_update_writecount(obj, 0, objsize);
|
2004-02-27 22:02:15 +00:00
|
|
|
}
|
|
|
|
} else if (vp->v_type == VCHR) {
|
2009-06-01 21:32:52 +00:00
|
|
|
error = vm_mmap_cdev(td, objsize, prot, maxprotp, flagsp,
|
|
|
|
vp->v_rdev, foffp, objp);
|
|
|
|
if (error == 0)
|
|
|
|
goto mark_atime;
|
|
|
|
goto done;
|
2004-02-27 22:02:15 +00:00
|
|
|
} else {
|
|
|
|
error = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
2008-08-28 15:23:18 +00:00
|
|
|
if ((error = VOP_GETATTR(vp, &va, cred)))
|
2004-02-27 22:02:15 +00:00
|
|
|
goto done;
|
2005-04-14 16:03:30 +00:00
|
|
|
#ifdef MAC
|
2008-08-28 15:23:18 +00:00
|
|
|
error = mac_vnode_check_mmap(cred, vp, prot, flags);
|
2005-04-14 16:03:30 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto done;
|
|
|
|
#endif
|
2004-02-27 22:02:15 +00:00
|
|
|
if ((flags & MAP_SHARED) != 0) {
|
|
|
|
if ((va.va_flags & (SF_SNAPSHOT|IMMUTABLE|APPEND)) != 0) {
|
|
|
|
if (prot & PROT_WRITE) {
|
|
|
|
error = EPERM;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
*maxprotp &= ~VM_PROT_WRITE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If it is a regular file without any references
|
|
|
|
* we do not need to sync it.
|
|
|
|
* Adjust object size to be the size of actual file.
|
|
|
|
*/
|
2009-06-01 21:32:52 +00:00
|
|
|
objsize = round_page(va.va_size);
|
|
|
|
if (va.va_nlink == 0)
|
|
|
|
flags |= MAP_NOSYNC;
|
2013-04-28 19:25:09 +00:00
|
|
|
if (obj->type == OBJT_VNODE)
|
|
|
|
obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff,
|
|
|
|
cred);
|
|
|
|
else {
|
|
|
|
KASSERT(obj->type == OBJT_DEFAULT || obj->type == OBJT_SWAP,
|
|
|
|
("wrong object type"));
|
|
|
|
vm_object_reference(obj);
|
|
|
|
}
|
2004-02-27 22:02:15 +00:00
|
|
|
if (obj == NULL) {
|
2009-06-01 21:32:52 +00:00
|
|
|
error = ENOMEM;
|
2004-02-27 22:02:15 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
*objp = obj;
|
|
|
|
*flagsp = flags;
|
2009-06-01 21:32:52 +00:00
|
|
|
|
|
|
|
mark_atime:
|
2008-08-28 15:23:18 +00:00
|
|
|
vfs_mark_atime(vp, cred);
|
2005-10-04 14:58:58 +00:00
|
|
|
|
2004-02-27 22:02:15 +00:00
|
|
|
done:
|
2013-03-28 06:39:27 +00:00
|
|
|
if (error != 0 && *writecounted) {
|
|
|
|
*writecounted = FALSE;
|
|
|
|
vnode_pager_update_writecount(obj, objsize, 0);
|
|
|
|
}
|
2004-02-27 22:02:15 +00:00
|
|
|
vput(vp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2005-04-01 20:00:11 +00:00
|
|
|
/*
|
|
|
|
* vm_mmap_cdev()
|
|
|
|
*
|
|
|
|
* MPSAFE
|
|
|
|
*
|
|
|
|
* Helper function for vm_mmap. Perform sanity check specific for mmap
|
|
|
|
* operations on cdevs.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
vm_mmap_cdev(struct thread *td, vm_size_t objsize,
|
|
|
|
vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp,
|
2009-06-01 21:32:52 +00:00
|
|
|
struct cdev *cdev, vm_ooffset_t *foff, vm_object_t *objp)
|
2005-04-01 20:00:11 +00:00
|
|
|
{
|
|
|
|
vm_object_t obj;
|
2008-03-20 16:08:42 +00:00
|
|
|
struct cdevsw *dsw;
|
2010-08-06 09:42:15 +00:00
|
|
|
int error, flags, ref;
|
2005-04-01 20:00:11 +00:00
|
|
|
|
|
|
|
flags = *flagsp;
|
|
|
|
|
2010-08-06 09:42:15 +00:00
|
|
|
dsw = dev_refthread(cdev, &ref);
|
2008-03-20 16:08:42 +00:00
|
|
|
if (dsw == NULL)
|
|
|
|
return (ENXIO);
|
|
|
|
if (dsw->d_flags & D_MMAP_ANON) {
|
2010-08-06 09:42:15 +00:00
|
|
|
dev_relthread(cdev, ref);
|
2005-04-01 20:00:11 +00:00
|
|
|
*maxprotp = VM_PROT_ALL;
|
|
|
|
*flagsp |= MAP_ANON;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
/*
|
2009-06-01 21:32:52 +00:00
|
|
|
* cdevs do not provide private mappings of any kind.
|
2005-04-01 20:00:11 +00:00
|
|
|
*/
|
|
|
|
if ((*maxprotp & VM_PROT_WRITE) == 0 &&
|
2009-06-01 21:32:52 +00:00
|
|
|
(prot & PROT_WRITE) != 0) {
|
2010-08-06 09:42:15 +00:00
|
|
|
dev_relthread(cdev, ref);
|
2005-04-01 20:00:11 +00:00
|
|
|
return (EACCES);
|
2009-06-01 21:32:52 +00:00
|
|
|
}
|
|
|
|
if (flags & (MAP_PRIVATE|MAP_COPY)) {
|
2010-08-06 09:42:15 +00:00
|
|
|
dev_relthread(cdev, ref);
|
2005-04-01 20:00:11 +00:00
|
|
|
return (EINVAL);
|
2009-06-01 21:32:52 +00:00
|
|
|
}
|
2005-04-01 20:00:11 +00:00
|
|
|
/*
|
|
|
|
* Force device mappings to be shared.
|
|
|
|
*/
|
|
|
|
flags |= MAP_SHARED;
|
|
|
|
#ifdef MAC_XXX
|
2009-06-01 21:32:52 +00:00
|
|
|
error = mac_cdev_check_mmap(td->td_ucred, cdev, prot);
|
|
|
|
if (error != 0) {
|
2010-08-06 09:42:15 +00:00
|
|
|
dev_relthread(cdev, ref);
|
2005-04-01 20:00:11 +00:00
|
|
|
return (error);
|
2009-06-01 21:32:52 +00:00
|
|
|
}
|
2005-04-01 20:00:11 +00:00
|
|
|
#endif
|
2009-06-01 21:32:52 +00:00
|
|
|
/*
|
|
|
|
* First, try d_mmap_single(). If that is not implemented
|
|
|
|
* (returns ENODEV), fall back to using the device pager.
|
|
|
|
* Note that d_mmap_single() must return a reference to the
|
|
|
|
* object (it needs to bump the reference count of the object
|
|
|
|
* it returns somehow).
|
|
|
|
*
|
|
|
|
* XXX assumes VM_PROT_* == PROT_*
|
|
|
|
*/
|
|
|
|
error = dsw->d_mmap_single(cdev, foff, objsize, objp, (int)prot);
|
2010-08-06 09:42:15 +00:00
|
|
|
dev_relthread(cdev, ref);
|
2009-06-01 21:32:52 +00:00
|
|
|
if (error != ENODEV)
|
|
|
|
return (error);
|
Implement global and per-uid accounting of the anonymous memory. Add
rlimit RLIMIT_SWAP that limits the amount of swap that may be reserved
for the uid.
The accounting information (charge) is associated with either map entry,
or vm object backing the entry, assuming the object is the first one
in the shadow chain and entry does not require COW. Charge is moved
from entry to object on allocation of the object, e.g. during the mmap,
assuming the object is allocated, or on the first page fault on the
entry. It moves back to the entry on forks due to COW setup.
The per-entry granularity of accounting makes the charge process fair
for processes that change uid during lifetime, and decrements charge
for proper uid when region is unmapped.
The interface of vm_pager_allocate(9) is extended by adding struct ucred *,
that is used to charge appropriate uid when allocation if performed by
kernel, e.g. md(4).
Several syscalls, among them is fork(2), may now return ENOMEM when
global or per-uid limits are enforced.
In collaboration with: pho
Reviewed by: alc
Approved by: re (kensmith)
2009-06-23 20:45:22 +00:00
|
|
|
obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff,
|
|
|
|
td->td_ucred);
|
2005-04-01 20:00:11 +00:00
|
|
|
if (obj == NULL)
|
|
|
|
return (EINVAL);
|
|
|
|
*objp = obj;
|
|
|
|
*flagsp = flags;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
/*
|
|
|
|
* vm_mmap_shm()
|
|
|
|
*
|
|
|
|
* MPSAFE
|
|
|
|
*
|
|
|
|
* Helper function for vm_mmap. Perform sanity check specific for mmap
|
|
|
|
* operations on shm file descriptors.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
vm_mmap_shm(struct thread *td, vm_size_t objsize,
|
|
|
|
vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp,
|
|
|
|
struct shmfd *shmfd, vm_ooffset_t foff, vm_object_t *objp)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
2010-09-19 19:42:04 +00:00
|
|
|
if ((*flagsp & MAP_SHARED) != 0 &&
|
|
|
|
(*maxprotp & VM_PROT_WRITE) == 0 &&
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
(prot & PROT_WRITE) != 0)
|
|
|
|
return (EACCES);
|
|
|
|
#ifdef MAC
|
|
|
|
error = mac_posixshm_check_mmap(td->td_ucred, shmfd, prot, *flagsp);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
#endif
|
|
|
|
error = shm_mmap(shmfd, objsize, foff, objp);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2001-08-31 01:26:30 +00:00
|
|
|
* vm_mmap()
|
|
|
|
*
|
|
|
|
* MPSAFE
|
|
|
|
*
|
|
|
|
* Internal version of mmap. Currently used by mmap, exec, and sys5
|
|
|
|
* shared memory. Handle is either a vnode pointer or NULL for MAP_ANON.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
int
|
1997-08-25 22:15:31 +00:00
|
|
|
vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
|
|
|
|
vm_prot_t maxprot, int flags,
|
2005-04-01 20:00:11 +00:00
|
|
|
objtype_t handle_type, void *handle,
|
1997-08-25 22:15:31 +00:00
|
|
|
vm_ooffset_t foff)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
boolean_t fitit;
|
2007-06-17 04:17:48 +00:00
|
|
|
vm_object_t object = NULL;
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td = curthread;
|
2013-08-16 21:13:55 +00:00
|
|
|
int docow, error, findspace, rv;
|
2012-02-23 21:07:16 +00:00
|
|
|
boolean_t writecounted;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
if (size == 0)
|
|
|
|
return (0);
|
|
|
|
|
2005-09-20 22:08:27 +00:00
|
|
|
size = round_page(size);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2012-02-16 06:45:51 +00:00
|
|
|
if (map == &td->td_proc->p_vmspace->vm_map) {
|
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
if (map->size + size > lim_cur(td->td_proc, RLIMIT_VMEM)) {
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
|
|
|
if (racct_set(td->td_proc, RACCT_VMEM, map->size + size)) {
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
2012-12-18 07:35:01 +00:00
|
|
|
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
|
2013-01-10 12:43:58 +00:00
|
|
|
if (ptoa(pmap_wired_count(map->pmap)) + size >
|
|
|
|
lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
|
2012-12-18 07:35:01 +00:00
|
|
|
racct_set_force(td->td_proc, RACCT_VMEM,
|
|
|
|
map->size);
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
|
|
|
error = racct_set(td->td_proc, RACCT_MEMLOCK,
|
2013-01-10 12:43:58 +00:00
|
|
|
ptoa(pmap_wired_count(map->pmap)) + size);
|
2012-12-18 07:35:01 +00:00
|
|
|
if (error != 0) {
|
|
|
|
racct_set_force(td->td_proc, RACCT_VMEM,
|
|
|
|
map->size);
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
}
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2002-06-26 00:29:28 +00:00
|
|
|
|
1995-03-21 10:15:52 +00:00
|
|
|
/*
|
|
|
|
* We currently can only deal with page aligned file offsets.
|
|
|
|
* The check is here rather than in the syscall because the
|
|
|
|
* kernel calls this function internally for other mmaping
|
|
|
|
* operations (such as in exec) and non-aligned offsets will
|
|
|
|
* cause pmap inconsistencies...so we want to be sure to
|
|
|
|
* disallow this in all cases.
|
|
|
|
*/
|
|
|
|
if (foff & PAGE_MASK)
|
|
|
|
return (EINVAL);
|
|
|
|
|
1995-07-09 06:58:03 +00:00
|
|
|
if ((flags & MAP_FIXED) == 0) {
|
|
|
|
fitit = TRUE;
|
|
|
|
*addr = round_page(*addr);
|
|
|
|
} else {
|
|
|
|
if (*addr != trunc_page(*addr))
|
|
|
|
return (EINVAL);
|
|
|
|
fitit = FALSE;
|
|
|
|
}
|
2012-02-23 21:07:16 +00:00
|
|
|
writecounted = FALSE;
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
NOTE: libkvm, w, ps, 'top', and any other utility which depends on struct
proc or any VM system structure will have to be rebuilt!!!
Much needed overhaul of the VM system. Included in this first round of
changes:
1) Improved pager interfaces: init, alloc, dealloc, getpages, putpages,
haspage, and sync operations are supported. The haspage interface now
provides information about clusterability. All pager routines now take
struct vm_object's instead of "pagers".
2) Improved data structures. In the previous paradigm, there is constant
confusion caused by pagers being both a data structure ("allocate a
pager") and a collection of routines. The idea of a pager structure has
escentially been eliminated. Objects now have types, and this type is
used to index the appropriate pager. In most cases, items in the pager
structure were duplicated in the object data structure and thus were
unnecessary. In the few cases that remained, a un_pager structure union
was created in the object to contain these items.
3) Because of the cleanup of #1 & #2, a lot of unnecessary layering can now
be removed. For instance, vm_object_enter(), vm_object_lookup(),
vm_object_remove(), and the associated object hash list were some of the
things that were removed.
4) simple_lock's removed. Discussion with several people reveals that the
SMP locking primitives used in the VM system aren't likely the mechanism
that we'll be adopting. Even if it were, the locking that was in the code
was very inadequate and would have to be mostly re-done anyway. The
locking in a uni-processor kernel was a no-op but went a long way toward
making the code difficult to read and debug.
5) Places that attempted to kludge-up the fact that we don't have kernel
thread support have been fixed to reflect the reality that we are really
dealing with processes, not threads. The VM system didn't have complete
thread support, so the comments and mis-named routines were just wrong.
We now use tsleep and wakeup directly in the lock routines, for instance.
6) Where appropriate, the pagers have been improved, especially in the
pager_alloc routines. Most of the pager_allocs have been rewritten and
are now faster and easier to maintain.
7) The pagedaemon pageout clustering algorithm has been rewritten and
now tries harder to output an even number of pages before and after
the requested page. This is sort of the reverse of the ideal pagein
algorithm and should provide better overall performance.
8) Unnecessary (incorrect) casts to caddr_t in calls to tsleep & wakeup
have been removed. Some other unnecessary casts have also been removed.
9) Some almost useless debugging code removed.
10) Terminology of shadow objects vs. backing objects straightened out.
The fact that the vm_object data structure escentially had this
backwards really confused things. The use of "shadow" and "backing
object" throughout the code is now internally consistent and correct
in the Mach terminology.
11) Several minor bug fixes, including one in the vm daemon that caused
0 RSS objects to not get purged as intended.
12) A "default pager" has now been created which cleans up the transition
of objects to the "swap" type. The previous checks throughout the code
for swp->pg_data != NULL were really ugly. This change also provides
the rudiments for future backing of "anonymous" memory by something
other than the swap pager (via the vnode pager, for example), and it
allows the decision about which of these pagers to use to be made
dynamically (although will need some additional decision code to do
this, of course).
13) (dyson) MAP_COPY has been deprecated and the corresponding "copy
object" code has been removed. MAP_COPY was undocumented and non-
standard. It was furthermore broken in several ways which caused its
behavior to degrade to MAP_PRIVATE. Binaries that use MAP_COPY will
continue to work correctly, but via the slightly different semantics
of MAP_PRIVATE.
14) (dyson) Sharing maps have been removed. It's marginal usefulness in a
threads design can be worked around in other ways. Both #12 and #13
were done to simplify the code and improve readability and maintain-
ability. (As were most all of these changes)
TODO:
1) Rewrite most of the vnode pager to use VOP_GETPAGES/PUTPAGES. Doing
this will reduce the vnode pager to a mere fraction of its current size.
2) Rewrite vm_fault and the swap/vnode pagers to use the clustering
information provided by the new haspage pager interface. This will
substantially reduce the overhead by eliminating a large number of
VOP_BMAP() calls. The VOP_BMAP() filesystem interface should be
improved to provide both a "behind" and "ahead" indication of
contiguousness.
3) Implement the extended features of pager_haspage in swap_pager_haspage().
It currently just says 0 pages ahead/behind.
4) Re-implement the swap device (swstrategy) in a more elegant way, perhaps
via a much more general mechanism that could also be used for disk
striping of regular filesystems.
5) Do something to improve the architecture of vm_object_collapse(). The
fact that it makes calls into the swap pager and knows too much about
how the swap pager operates really bothers me. It also doesn't allow
for collapsing of non-swap pager objects ("unnamed" objects backed by
other pagers).
1995-07-13 08:48:48 +00:00
|
|
|
* Lookup/allocate object.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2005-04-01 20:00:11 +00:00
|
|
|
switch (handle_type) {
|
|
|
|
case OBJT_DEVICE:
|
|
|
|
error = vm_mmap_cdev(td, size, prot, &maxprot, &flags,
|
2009-06-01 21:32:52 +00:00
|
|
|
handle, &foff, &object);
|
2005-04-01 20:00:11 +00:00
|
|
|
break;
|
|
|
|
case OBJT_VNODE:
|
2004-02-27 22:02:15 +00:00
|
|
|
error = vm_mmap_vnode(td, size, prot, &maxprot, &flags,
|
2012-02-23 21:07:16 +00:00
|
|
|
handle, &foff, &object, &writecounted);
|
2005-04-01 20:00:11 +00:00
|
|
|
break;
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
case OBJT_SWAP:
|
|
|
|
error = vm_mmap_shm(td, size, prot, &maxprot, &flags,
|
|
|
|
handle, foff, &object);
|
|
|
|
break;
|
2005-04-01 20:00:11 +00:00
|
|
|
case OBJT_DEFAULT:
|
|
|
|
if (handle == NULL) {
|
|
|
|
error = 0;
|
|
|
|
break;
|
2003-12-06 05:45:32 +00:00
|
|
|
}
|
2005-04-01 20:00:11 +00:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
2007-06-17 04:17:48 +00:00
|
|
|
break;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2005-04-01 20:00:11 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2004-02-27 22:02:15 +00:00
|
|
|
if (flags & MAP_ANON) {
|
1996-12-28 22:40:44 +00:00
|
|
|
object = NULL;
|
1999-06-05 18:21:53 +00:00
|
|
|
docow = 0;
|
2004-02-27 22:02:15 +00:00
|
|
|
/*
|
|
|
|
* Unnamed anonymous regions always start at 0.
|
|
|
|
*/
|
|
|
|
if (handle == 0)
|
|
|
|
foff = 0;
|
2010-08-28 16:57:07 +00:00
|
|
|
} else if (flags & MAP_PREFAULT_READ)
|
|
|
|
docow = MAP_PREFAULT;
|
|
|
|
else
|
1999-06-05 18:21:53 +00:00
|
|
|
docow = MAP_PREFAULT_PARTIAL;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-12-12 03:19:33 +00:00
|
|
|
if ((flags & (MAP_ANON|MAP_SHARED)) == 0)
|
1999-06-05 18:21:53 +00:00
|
|
|
docow |= MAP_COPY_ON_WRITE;
|
1999-12-12 03:19:33 +00:00
|
|
|
if (flags & MAP_NOSYNC)
|
|
|
|
docow |= MAP_DISABLE_SYNCER;
|
2000-02-28 04:10:35 +00:00
|
|
|
if (flags & MAP_NOCORE)
|
|
|
|
docow |= MAP_DISABLE_COREDUMP;
|
2012-02-11 17:29:07 +00:00
|
|
|
/* Shared memory is also shared with children. */
|
|
|
|
if (flags & MAP_SHARED)
|
|
|
|
docow |= MAP_INHERIT_SHARE;
|
2012-02-23 21:07:16 +00:00
|
|
|
if (writecounted)
|
|
|
|
docow |= MAP_VN_WRITECOUNT;
|
1996-03-12 02:27:20 +00:00
|
|
|
|
1999-01-06 23:05:42 +00:00
|
|
|
if (flags & MAP_STACK)
|
2003-09-27 22:28:14 +00:00
|
|
|
rv = vm_map_stack(map, *addr, size, prot, maxprot,
|
|
|
|
docow | MAP_STACK_GROWS_DOWN);
|
2013-08-16 21:13:55 +00:00
|
|
|
else if (fitit) {
|
|
|
|
if ((flags & MAP_ALIGNMENT_MASK) == MAP_ALIGNED_SUPER)
|
|
|
|
findspace = VMFS_SUPER_SPACE;
|
|
|
|
else if ((flags & MAP_ALIGNMENT_MASK) != 0)
|
|
|
|
findspace = VMFS_ALIGNED_SPACE(flags >>
|
|
|
|
MAP_ALIGNMENT_SHIFT);
|
|
|
|
else
|
|
|
|
findspace = VMFS_OPTIMAL_SPACE;
|
2013-09-09 18:11:59 +00:00
|
|
|
rv = vm_map_find(map, object, foff, addr, size,
|
|
|
|
#ifdef MAP_32BIT
|
|
|
|
flags & MAP_32BIT ? MAP_32BIT_MAX_ADDR :
|
|
|
|
#endif
|
|
|
|
0, findspace, prot, maxprot, docow);
|
2013-08-16 21:13:55 +00:00
|
|
|
} else
|
2008-04-28 05:30:23 +00:00
|
|
|
rv = vm_map_fixed(map, object, foff, *addr, size,
|
1999-04-19 14:14:14 +00:00
|
|
|
prot, maxprot, docow);
|
1996-07-30 03:08:57 +00:00
|
|
|
|
2012-02-25 21:06:39 +00:00
|
|
|
if (rv == KERN_SUCCESS) {
|
|
|
|
/*
|
|
|
|
* If the process has requested that all future mappings
|
|
|
|
* be wired, then heed this.
|
|
|
|
*/
|
2012-04-21 18:36:53 +00:00
|
|
|
if (map->flags & MAP_WIREFUTURE) {
|
2012-02-25 21:06:39 +00:00
|
|
|
vm_map_wire(map, *addr, *addr + size,
|
2012-04-21 18:36:53 +00:00
|
|
|
VM_MAP_WIRE_USER | ((flags & MAP_STACK) ?
|
|
|
|
VM_MAP_WIRE_HOLESOK : VM_MAP_WIRE_NOHOLES));
|
|
|
|
}
|
2012-02-25 21:06:39 +00:00
|
|
|
} else {
|
1995-10-23 03:49:43 +00:00
|
|
|
/*
|
2012-02-23 21:07:16 +00:00
|
|
|
* If this mapping was accounted for in the vnode's
|
|
|
|
* writecount, then undo that now.
|
1995-10-23 03:49:43 +00:00
|
|
|
*/
|
2012-02-23 21:07:16 +00:00
|
|
|
if (writecounted)
|
|
|
|
vnode_pager_release_writecount(object, 0, size);
|
2012-02-25 21:06:39 +00:00
|
|
|
/*
|
|
|
|
* Lose the object reference. Will destroy the
|
|
|
|
* object if it's an unnamed anonymous mapping
|
|
|
|
* or named anonymous without other references.
|
|
|
|
*/
|
1996-10-24 02:56:23 +00:00
|
|
|
vm_object_deallocate(object);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2011-07-10 20:49:13 +00:00
|
|
|
return (vm_mmap_to_errno(rv));
|
|
|
|
}
|
|
|
|
|
2012-02-25 21:06:39 +00:00
|
|
|
/*
|
|
|
|
* Translate a Mach VM return code to zero on success or the appropriate errno
|
|
|
|
* on failure.
|
|
|
|
*/
|
2011-07-10 20:49:13 +00:00
|
|
|
int
|
|
|
|
vm_mmap_to_errno(int rv)
|
|
|
|
{
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
switch (rv) {
|
|
|
|
case KERN_SUCCESS:
|
|
|
|
return (0);
|
|
|
|
case KERN_INVALID_ADDRESS:
|
|
|
|
case KERN_NO_SPACE:
|
|
|
|
return (ENOMEM);
|
|
|
|
case KERN_PROTECTION_FAILURE:
|
|
|
|
return (EACCES);
|
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
}
|