[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree

zrouter-src-freebsd at zrouter.org zrouter-src-freebsd at zrouter.org
Fri Mar 2 15:39:55 UTC 2012


details:   http://zrouter.org/hg/FreeBSD/head//rev/8bf40f27aa20
changeset: 398:8bf40f27aa20
user:      ray at terran.dlink.ua
date:      Fri Mar 02 17:16:20 2012 +0200
description:
Update to FreeBSD-HEAD @232391

diffstat:

 head/sys/vm/swap_pager.c  |   10 ++--
 head/sys/vm/vm_kern.c     |   32 +------------
 head/sys/vm/vm_map.c      |  112 +++++++++++++++++++++++++++++++++++++--------
 head/sys/vm/vm_map.h      |    6 +-
 head/sys/vm/vm_mmap.c     |  111 ++++++++++++++++++++++++++++-----------------
 head/sys/vm/vm_object.h   |    3 +-
 head/sys/vm/vnode_pager.c |   87 +++++++++++++++++++++++++++++++++++-
 head/sys/vm/vnode_pager.h |   10 ++--
 8 files changed, 263 insertions(+), 108 deletions(-)

diffs (772 lines):

diff -r 4bd6486a01ce -r 8bf40f27aa20 head/sys/vm/swap_pager.c
--- a/head/sys/vm/swap_pager.c	Fri Mar 02 17:15:56 2012 +0200
+++ b/head/sys/vm/swap_pager.c	Fri Mar 02 17:16:20 2012 +0200
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/swap_pager.c 228432 2011-12-12 10:04:04Z kib $");
+__FBSDID("$FreeBSD: head/sys/vm/swap_pager.c 231378 2012-02-10 12:35:57Z ed $");
 
 #include "opt_swap.h"
 #include "opt_vm.h"
@@ -2320,7 +2320,7 @@
 	TAILQ_FOREACH_SAFE(sp, &swtailq, sw_list, spt) {
 		mtx_unlock(&sw_dev_mtx);
 		if (vn_isdisk(sp->sw_vp, NULL))
-			devname = sp->sw_vp->v_rdev->si_name;
+			devname = devtoname(sp->sw_vp->v_rdev);
 		else
 			devname = "[file]";
 		error = swapoff_one(sp, thread0.td_ucred);
@@ -2358,7 +2358,7 @@
 swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len)
 {
 	struct swdevt *sp;
-	char *tmp_devname;
+	const char *tmp_devname;
 	int error, n;
 
 	n = 0;
@@ -2376,7 +2376,7 @@
 		xs->xsw_used = sp->sw_used;
 		if (devname != NULL) {
 			if (vn_isdisk(sp->sw_vp, NULL))
-				tmp_devname = sp->sw_vp->v_rdev->si_name;
+				tmp_devname = devtoname(sp->sw_vp->v_rdev);
 			else
 				tmp_devname = "[file]";
 			strncpy(devname, tmp_devname, len);
@@ -2521,7 +2521,7 @@
 	mtx_lock(&sw_dev_mtx);
 	TAILQ_FOREACH(sp, &swtailq, sw_list)
 		if (sp->sw_id == cp)
-			sp->sw_id = NULL;
+			sp->sw_flags |= SW_CLOSING;
 	mtx_unlock(&sw_dev_mtx);
 }
 
diff -r 4bd6486a01ce -r 8bf40f27aa20 head/sys/vm/vm_kern.c
--- a/head/sys/vm/vm_kern.c	Fri Mar 02 17:15:56 2012 +0200
+++ b/head/sys/vm/vm_kern.c	Fri Mar 02 17:16:20 2012 +0200
@@ -63,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vm_kern.c 230623 2012-01-27 20:18:31Z kmacy $");
+__FBSDID("$FreeBSD: head/sys/vm/vm_kern.c 232288 2012-02-29 05:41:29Z alc $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -161,7 +161,6 @@
 {
 	vm_offset_t addr;
 	vm_offset_t offset;
-	vm_offset_t i;
 
 	size = round_page(size);
 
@@ -187,35 +186,6 @@
 	vm_map_unlock(map);
 
 	/*
-	 * Guarantee that there are pages already in this object before
-	 * calling vm_map_wire.  This is to prevent the following
-	 * scenario:
-	 *
-	 * 1) Threads have swapped out, so that there is a pager for the
-	 * kernel_object. 2) The kmsg zone is empty, and so we are
-	 * kmem_allocing a new page for it. 3) vm_map_wire calls vm_fault;
-	 * there is no page, but there is a pager, so we call
-	 * pager_data_request.  But the kmsg zone is empty, so we must
-	 * kmem_alloc. 4) goto 1 5) Even if the kmsg zone is not empty: when
-	 * we get the data back from the pager, it will be (very stale)
-	 * non-zero data.  kmem_alloc is defined to return zero-filled memory.
-	 *
-	 * We're intentionally not activating the pages we allocate to prevent a
-	 * race with page-out.  vm_map_wire will wire the pages.
-	 */
-	VM_OBJECT_LOCK(kernel_object);
-	for (i = 0; i < size; i += PAGE_SIZE) {
-		vm_page_t mem;
-
-		mem = vm_page_grab(kernel_object, OFF_TO_IDX(offset + i),
-		    VM_ALLOC_NOBUSY | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
-		mem->valid = VM_PAGE_BITS_ALL;
-		KASSERT((mem->oflags & VPO_UNMANAGED) != 0,
-		    ("kmem_alloc: page %p is managed", mem));
-	}
-	VM_OBJECT_UNLOCK(kernel_object);
-
-	/*
 	 * And finally, mark the data as non-pageable.
 	 */
 	(void) vm_map_wire(map, addr, addr + size,
diff -r 4bd6486a01ce -r 8bf40f27aa20 head/sys/vm/vm_map.c
--- a/head/sys/vm/vm_map.c	Fri Mar 02 17:15:56 2012 +0200
+++ b/head/sys/vm/vm_map.c	Fri Mar 02 17:16:20 2012 +0200
@@ -63,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vm_map.c 227788 2011-11-21 12:59:52Z attilio $");
+__FBSDID("$FreeBSD: head/sys/vm/vm_map.c 232160 2012-02-25 17:49:59Z alc $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -91,6 +91,7 @@
 #include <vm/vm_pager.h>
 #include <vm/vm_kern.h>
 #include <vm/vm_extern.h>
+#include <vm/vnode_pager.h>
 #include <vm/swap_pager.h>
 #include <vm/uma.h>
 
@@ -475,11 +476,23 @@
 {
 	struct thread *td;
 	vm_map_entry_t entry;
+	vm_object_t object;
 
 	td = curthread;
-
 	while ((entry = td->td_map_def_user) != NULL) {
 		td->td_map_def_user = entry->next;
+		if ((entry->eflags & MAP_ENTRY_VN_WRITECNT) != 0) {
+			/*
+			 * Decrement the object's writemappings and
+			 * possibly the vnode's v_writecount.
+			 */
+			KASSERT((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0,
+			    ("Submap with writecount"));
+			object = entry->object.vm_object;
+			KASSERT(object != NULL, ("No object for writecount"));
+			vnode_pager_release_writecount(object, entry->start,
+			    entry->end);
+		}
 		vm_map_entry_deallocate(entry, FALSE);
 	}
 }
@@ -1130,6 +1143,7 @@
 	vm_map_entry_t temp_entry;
 	vm_eflags_t protoeflags;
 	struct ucred *cred;
+	vm_inherit_t inheritance;
 	boolean_t charge_prev_obj;
 
 	VM_MAP_ASSERT_LOCKED(map);
@@ -1173,6 +1187,12 @@
 		protoeflags |= MAP_ENTRY_NOSYNC;
 	if (cow & MAP_DISABLE_COREDUMP)
 		protoeflags |= MAP_ENTRY_NOCOREDUMP;
+	if (cow & MAP_VN_WRITECOUNT)
+		protoeflags |= MAP_ENTRY_VN_WRITECNT;
+	if (cow & MAP_INHERIT_SHARE)
+		inheritance = VM_INHERIT_SHARE;
+	else
+		inheritance = VM_INHERIT_DEFAULT;
 
 	cred = NULL;
 	KASSERT((object != kmem_object && object != kernel_object) ||
@@ -1227,7 +1247,7 @@
 		 * can extend the previous map entry to include the
 		 * new range as well.
 		 */
-		if ((prev_entry->inheritance == VM_INHERIT_DEFAULT) &&
+		if ((prev_entry->inheritance == inheritance) &&
 		    (prev_entry->protection == prot) &&
 		    (prev_entry->max_protection == max)) {
 			map->size += (end - prev_entry->end);
@@ -1276,7 +1296,7 @@
 	new_entry->offset = offset;
 	new_entry->avail_ssize = 0;
 
-	new_entry->inheritance = VM_INHERIT_DEFAULT;
+	new_entry->inheritance = inheritance;
 	new_entry->protection = prot;
 	new_entry->max_protection = max;
 	new_entry->wired_count = 0;
@@ -1511,6 +1531,11 @@
 			 * references.  Thus, the map lock can be kept
 			 * without causing a lock-order reversal with
 			 * the vnode lock.
+			 *
+			 * Since we count the number of virtual page
+			 * mappings in object->un_pager.vnp.writemappings,
+			 * the writemappings value should not be adjusted
+			 * when the entry is disposed of.
 			 */
 			if (prev->object.vm_object)
 				vm_object_deallocate(prev->object.vm_object);
@@ -1622,6 +1647,13 @@
 
 	if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) {
 		vm_object_reference(new_entry->object.vm_object);
+		/*
+		 * The object->un_pager.vnp.writemappings for the
+		 * object of MAP_ENTRY_VN_WRITECNT type entry shall be
+		 * kept as is here.  The virtual pages are
+		 * re-distributed among the clipped entries, so the sum is
+		 * left the same.
+		 */
 	}
 }
 
@@ -2895,6 +2927,7 @@
 	vm_ooffset_t *fork_charge)
 {
 	vm_object_t src_object;
+	vm_map_entry_t fake_entry;
 	vm_offset_t size;
 	struct ucred *cred;
 	int charged;
@@ -2960,6 +2993,27 @@
 			src_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY);
 			dst_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY);
 			dst_entry->offset = src_entry->offset;
+			if (src_entry->eflags & MAP_ENTRY_VN_WRITECNT) {
+				/*
+				 * MAP_ENTRY_VN_WRITECNT cannot
+				 * indicate write reference from
+				 * src_entry, since the entry is
+				 * marked as needs copy.  Allocate a
+				 * fake entry that is used to
+				 * decrement object->un_pager.vnp.writecount
+				 * at the appropriate time.  Attach
+				 * fake_entry to the deferred list.
+				 */
+				fake_entry = vm_map_entry_create(dst_map);
+				fake_entry->eflags = MAP_ENTRY_VN_WRITECNT;
+				src_entry->eflags &= ~MAP_ENTRY_VN_WRITECNT;
+				vm_object_reference(src_object);
+				fake_entry->object.vm_object = src_object;
+				fake_entry->start = src_entry->start;
+				fake_entry->end = src_entry->end;
+				fake_entry->next = curthread->td_map_def_user;
+				curthread->td_map_def_user = fake_entry;
+			}
 		} else {
 			dst_entry->object.vm_object = NULL;
 			dst_entry->offset = 0;
@@ -3028,26 +3082,25 @@
 vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge)
 {
 	struct vmspace *vm2;
-	vm_map_t old_map = &vm1->vm_map;
-	vm_map_t new_map;
-	vm_map_entry_t old_entry;
-	vm_map_entry_t new_entry;
+	vm_map_t new_map, old_map;
+	vm_map_entry_t new_entry, old_entry;
 	vm_object_t object;
 	int locked;
 
+	old_map = &vm1->vm_map;
+	/* Copy immutable fields of vm1 to vm2. */
+	vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset);
+	if (vm2 == NULL)
+		return (NULL);
+	vm2->vm_taddr = vm1->vm_taddr;
+	vm2->vm_daddr = vm1->vm_daddr;
+	vm2->vm_maxsaddr = vm1->vm_maxsaddr;
 	vm_map_lock(old_map);
 	if (old_map->busy)
 		vm_map_wait_busy(old_map);
-	vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset);
-	if (vm2 == NULL)
-		goto unlock_and_return;
-	vm2->vm_taddr = vm1->vm_taddr;
-	vm2->vm_daddr = vm1->vm_daddr;
-	vm2->vm_maxsaddr = vm1->vm_maxsaddr;
-	new_map = &vm2->vm_map;	/* XXX */
+	new_map = &vm2->vm_map;
 	locked = vm_map_trylock(new_map); /* trylock to silence WITNESS */
 	KASSERT(locked, ("vmspace_fork: lock failed"));
-	new_map->timestamp = 1;
 
 	old_entry = old_map->header.next;
 
@@ -3117,6 +3170,16 @@
 			new_entry->eflags &= ~(MAP_ENTRY_USER_WIRED |
 			    MAP_ENTRY_IN_TRANSITION);
 			new_entry->wired_count = 0;
+			if (new_entry->eflags & MAP_ENTRY_VN_WRITECNT) {
+				object = new_entry->object.vm_object;
+				KASSERT(((struct vnode *)object->handle)->
+				    v_writecount > 0,
+				    ("vmspace_fork: v_writecount"));
+				KASSERT(object->un_pager.vnp.writemappings > 0,
+				    ("vmspace_fork: vnp.writecount"));
+				vnode_pager_update_writecount(object,
+				    new_entry->start, new_entry->end);
+			}
 
 			/*
 			 * Insert the entry into the new map -- we know we're
@@ -3141,8 +3204,11 @@
 			 */
 			new_entry = vm_map_entry_create(new_map);
 			*new_entry = *old_entry;
+			/*
+			 * Copied entry is COW over the old object.
+			 */
 			new_entry->eflags &= ~(MAP_ENTRY_USER_WIRED |
-			    MAP_ENTRY_IN_TRANSITION);
+			    MAP_ENTRY_IN_TRANSITION | MAP_ENTRY_VN_WRITECNT);
 			new_entry->wired_count = 0;
 			new_entry->object.vm_object = NULL;
 			new_entry->cred = NULL;
@@ -3155,10 +3221,14 @@
 		}
 		old_entry = old_entry->next;
 	}
-unlock_and_return:
-	vm_map_unlock(old_map);
-	if (vm2 != NULL)
-		vm_map_unlock(new_map);
+	/*
+	 * Use inlined vm_map_unlock() to postpone handling the deferred
+	 * map entries, which cannot be done until both old_map and
+	 * new_map locks are released.
+	 */
+	sx_xunlock(&old_map->lock);
+	sx_xunlock(&new_map->lock);
+	vm_map_process_deferred();
 
 	return (vm2);
 }
diff -r 4bd6486a01ce -r 8bf40f27aa20 head/sys/vm/vm_map.h
--- a/head/sys/vm/vm_map.h	Fri Mar 02 17:15:56 2012 +0200
+++ b/head/sys/vm/vm_map.h	Fri Mar 02 17:16:20 2012 +0200
@@ -57,7 +57,7 @@
  * any improvements or extensions that they make and grant Carnegie the
  * rights to redistribute these changes.
  *
- * $FreeBSD$
+ * $FreeBSD: head/sys/vm/vm_map.h 232071 2012-02-23 21:07:16Z kib $
  */
 
 /*
@@ -139,6 +139,7 @@
 #define	MAP_ENTRY_GROWS_UP		0x2000	/* Bottom-up stacks */
 
 #define	MAP_ENTRY_WIRE_SKIPPED		0x4000
+#define	MAP_ENTRY_VN_WRITECNT		0x8000	/* writeable vnode mapping */
 
 #ifdef	_KERNEL
 static __inline u_char
@@ -307,7 +308,7 @@
 /*
  * Copy-on-write flags for vm_map operations
  */
-#define MAP_UNUSED_01		0x0001
+#define MAP_INHERIT_SHARE	0x0001
 #define MAP_COPY_ON_WRITE	0x0002
 #define MAP_NOFAULT		0x0004
 #define MAP_PREFAULT		0x0008
@@ -315,6 +316,7 @@
 #define MAP_DISABLE_SYNCER	0x0020
 #define MAP_DISABLE_COREDUMP	0x0100
 #define MAP_PREFAULT_MADVISE	0x0200	/* from (user) madvise request */
+#define	MAP_VN_WRITECOUNT	0x0400
 #define	MAP_STACK_GROWS_DOWN	0x1000
 #define	MAP_STACK_GROWS_UP	0x2000
 #define	MAP_ACC_CHARGED		0x4000
diff -r 4bd6486a01ce -r 8bf40f27aa20 head/sys/vm/vm_mmap.c
--- a/head/sys/vm/vm_mmap.c	Fri Mar 02 17:15:56 2012 +0200
+++ b/head/sys/vm/vm_mmap.c	Fri Mar 02 17:16:20 2012 +0200
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vm_mmap.c 225617 2011-09-16 13:58:51Z kmacy $");
+__FBSDID("$FreeBSD: head/sys/vm/vm_mmap.c 232166 2012-02-25 21:06:39Z alc $");
 
 #include "opt_compat.h"
 #include "opt_hwpmc_hooks.h"
@@ -81,6 +81,7 @@
 #include <vm/vm_pageout.h>
 #include <vm/vm_extern.h>
 #include <vm/vm_page.h>
+#include <vm/vnode_pager.h>
 
 #ifdef HWPMC_HOOKS
 #include <sys/pmckern.h>
@@ -93,7 +94,7 @@
 #endif
 
 static int vm_mmap_vnode(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
-    int *, struct vnode *, vm_ooffset_t *, vm_object_t *);
+    int *, struct vnode *, vm_ooffset_t *, vm_object_t *, boolean_t *);
 static int vm_mmap_cdev(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
     int *, struct cdev *, vm_ooffset_t *, vm_object_t *);
 static int vm_mmap_shm(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
@@ -1218,28 +1219,33 @@
 /*
  * vm_mmap_vnode()
  *
- * MPSAFE
- *
  * Helper function for vm_mmap.  Perform sanity check specific for mmap
  * operations on vnodes.
+ *
+ * For VCHR vnodes, the vnode lock is held over the call to
+ * vm_mmap_cdev() to keep vp->v_rdev valid.
  */
 int
 vm_mmap_vnode(struct thread *td, vm_size_t objsize,
     vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp,
-    struct vnode *vp, vm_ooffset_t *foffp, vm_object_t *objp)
+    struct vnode *vp, vm_ooffset_t *foffp, vm_object_t *objp,
+    boolean_t *writecounted)
 {
 	struct vattr va;
 	vm_object_t obj;
 	vm_offset_t foff;
 	struct mount *mp;
 	struct ucred *cred;
-	int error, flags;
-	int vfslocked;
+	int error, flags, locktype, vfslocked;
 
 	mp = vp->v_mount;
 	cred = td->td_ucred;
+	if ((*maxprotp & VM_PROT_WRITE) && (*flagsp & MAP_SHARED))
+		locktype = LK_EXCLUSIVE;
+	else
+		locktype = LK_SHARED;
 	vfslocked = VFS_LOCK_GIANT(mp);
-	if ((error = vget(vp, LK_SHARED, td)) != 0) {
+	if ((error = vget(vp, locktype, td)) != 0) {
 		VFS_UNLOCK_GIANT(vfslocked);
 		return (error);
 	}
@@ -1256,8 +1262,20 @@
 		}
 		if (obj->handle != vp) {
 			vput(vp);
-			vp = (struct vnode*)obj->handle;
-			vget(vp, LK_SHARED, td);
+			vp = (struct vnode *)obj->handle;
+			/*
+			 * Bypass filesystems obey the mpsafety of the
+			 * underlying fs.
+			 */
+			error = vget(vp, locktype, td);
+			if (error != 0) {
+				VFS_UNLOCK_GIANT(vfslocked);
+				return (error);
+			}
+		}
+		if (locktype == LK_EXCLUSIVE) {
+			*writecounted = TRUE;
+			vnode_pager_update_writecount(obj, 0, objsize);
 		}
 	} else if (vp->v_type == VCHR) {
 		error = vm_mmap_cdev(td, objsize, prot, maxprotp, flagsp,
@@ -1293,7 +1311,7 @@
 	objsize = round_page(va.va_size);
 	if (va.va_nlink == 0)
 		flags |= MAP_NOSYNC;
-	obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff, td->td_ucred);
+	obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff, cred);
 	if (obj == NULL) {
 		error = ENOMEM;
 		goto done;
@@ -1429,27 +1447,27 @@
 {
 	boolean_t fitit;
 	vm_object_t object = NULL;
-	int rv = KERN_SUCCESS;
-	int docow, error;
 	struct thread *td = curthread;
+	int docow, error, rv;
+	boolean_t writecounted;
 
 	if (size == 0)
 		return (0);
 
 	size = round_page(size);
 
-	PROC_LOCK(td->td_proc);
-	if (td->td_proc->p_vmspace->vm_map.size + size >
-	    lim_cur(td->td_proc, RLIMIT_VMEM)) {
+	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);
+		}
 		PROC_UNLOCK(td->td_proc);
-		return (ENOMEM);
 	}
-	if (racct_set(td->td_proc, RACCT_VMEM,
-	    td->td_proc->p_vmspace->vm_map.size + size)) {
-		PROC_UNLOCK(td->td_proc);
-		return (ENOMEM);
-	}
-	PROC_UNLOCK(td->td_proc);
 
 	/*
 	 * We currently can only deal with page aligned file offsets.
@@ -1470,6 +1488,8 @@
 			return (EINVAL);
 		fitit = FALSE;
 	}
+	writecounted = FALSE;
+
 	/*
 	 * Lookup/allocate object.
 	 */
@@ -1480,7 +1500,7 @@
 		break;
 	case OBJT_VNODE:
 		error = vm_mmap_vnode(td, size, prot, &maxprot, &flags,
-		    handle, &foff, &object);
+		    handle, &foff, &object, &writecounted);
 		break;
 	case OBJT_SWAP:
 		error = vm_mmap_shm(td, size, prot, &maxprot, &flags,
@@ -1517,6 +1537,11 @@
 		docow |= MAP_DISABLE_SYNCER;
 	if (flags & MAP_NOCORE)
 		docow |= MAP_DISABLE_COREDUMP;
+	/* Shared memory is also shared with children. */
+	if (flags & MAP_SHARED)
+		docow |= MAP_INHERIT_SHARE;
+	if (writecounted)
+		docow |= MAP_VN_WRITECOUNT;
 
 	if (flags & MAP_STACK)
 		rv = vm_map_stack(map, *addr, size, prot, maxprot,
@@ -1529,33 +1554,35 @@
 		rv = vm_map_fixed(map, object, foff, *addr, size,
 				 prot, maxprot, docow);
 
-	if (rv != KERN_SUCCESS) {
+	if (rv == KERN_SUCCESS) {
 		/*
-		 * Lose the object reference. Will destroy the
+		 * If the process has requested that all future mappings
+		 * be wired, then heed this.
+		 */
+		if (map->flags & MAP_WIREFUTURE)
+			vm_map_wire(map, *addr, *addr + size,
+			    VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
+	} else {
+		/*
+		 * If this mapping was accounted for in the vnode's
+		 * writecount, then undo that now.
+		 */
+		if (writecounted)
+			vnode_pager_release_writecount(object, 0, size);
+		/*
+		 * Lose the object reference.  Will destroy the
 		 * object if it's an unnamed anonymous mapping
 		 * or named anonymous without other references.
 		 */
 		vm_object_deallocate(object);
-	} else if (flags & MAP_SHARED) {
-		/*
-		 * Shared memory is also shared with children.
-		 */
-		rv = vm_map_inherit(map, *addr, *addr + size, VM_INHERIT_SHARE);
-		if (rv != KERN_SUCCESS)
-			(void) vm_map_remove(map, *addr, *addr + size);
 	}
-
-	/*
-	 * If the process has requested that all future mappings
-	 * be wired, then heed this.
-	 */
-	if ((rv == KERN_SUCCESS) && (map->flags & MAP_WIREFUTURE))
-		vm_map_wire(map, *addr, *addr + size,
-		    VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
-
 	return (vm_mmap_to_errno(rv));
 }
 
+/*
+ * Translate a Mach VM return code to zero on success or the appropriate errno
+ * on failure.
+ */
 int
 vm_mmap_to_errno(int rv)
 {
diff -r 4bd6486a01ce -r 8bf40f27aa20 head/sys/vm/vm_object.h
--- a/head/sys/vm/vm_object.h	Fri Mar 02 17:15:56 2012 +0200
+++ b/head/sys/vm/vm_object.h	Fri Mar 02 17:16:20 2012 +0200
@@ -57,7 +57,7 @@
  * any improvements or extensions that they make and grant Carnegie the
  * rights to redistribute these changes.
  *
- * $FreeBSD: head/sys/vm/vm_object.h 229934 2012-01-10 18:05:44Z kib $
+ * $FreeBSD: head/sys/vm/vm_object.h 232071 2012-02-23 21:07:16Z kib $
  */
 
 /*
@@ -112,6 +112,7 @@
 		 */
 		struct {
 			off_t vnp_size;
+			vm_ooffset_t writemappings;
 		} vnp;
 
 		/*
diff -r 4bd6486a01ce -r 8bf40f27aa20 head/sys/vm/vnode_pager.c
--- a/head/sys/vm/vnode_pager.c	Fri Mar 02 17:15:56 2012 +0200
+++ b/head/sys/vm/vnode_pager.c	Fri Mar 02 17:16:20 2012 +0200
@@ -51,7 +51,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vnode_pager.c 228156 2011-11-30 17:39:00Z kib $");
+__FBSDID("$FreeBSD: head/sys/vm/vnode_pager.c 232071 2012-02-23 21:07:16Z kib $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -222,6 +222,7 @@
 		object = vm_object_allocate(OBJT_VNODE, OFF_TO_IDX(round_page(size)));
 
 		object->un_pager.vnp.vnp_size = size;
+		object->un_pager.vnp.writemappings = 0;
 
 		object->handle = handle;
 		VI_LOCK(vp);
@@ -268,10 +269,16 @@
 		wakeup(object);
 	}
 	ASSERT_VOP_ELOCKED(vp, "vnode_pager_dealloc");
+	if (object->un_pager.vnp.writemappings > 0) {
+		object->un_pager.vnp.writemappings = 0;
+		vp->v_writecount--;
+	}
 	vp->v_object = NULL;
 	vp->v_vflag &= ~VV_TEXT;
+	VM_OBJECT_UNLOCK(object);
 	while (refs-- > 0)
 		vunref(vp);
+	VM_OBJECT_LOCK(object);
 }
 
 static boolean_t
@@ -1215,3 +1222,81 @@
 	}
 	VM_OBJECT_UNLOCK(obj);
 }
+
+void
+vnode_pager_update_writecount(vm_object_t object, vm_offset_t start,
+    vm_offset_t end)
+{
+	struct vnode *vp;
+	vm_ooffset_t old_wm;
+
+	VM_OBJECT_LOCK(object);
+	if (object->type != OBJT_VNODE) {
+		VM_OBJECT_UNLOCK(object);
+		return;
+	}
+	old_wm = object->un_pager.vnp.writemappings;
+	object->un_pager.vnp.writemappings += (vm_ooffset_t)end - start;
+	vp = object->handle;
+	if (old_wm == 0 && object->un_pager.vnp.writemappings != 0) {
+		ASSERT_VOP_ELOCKED(vp, "v_writecount inc");
+		vp->v_writecount++;
+	} else if (old_wm != 0 && object->un_pager.vnp.writemappings == 0) {
+		ASSERT_VOP_ELOCKED(vp, "v_writecount dec");
+		vp->v_writecount--;
+	}
+	VM_OBJECT_UNLOCK(object);
+}
+
+void
+vnode_pager_release_writecount(vm_object_t object, vm_offset_t start,
+    vm_offset_t end)
+{
+	struct vnode *vp;
+	struct mount *mp;
+	vm_offset_t inc;
+	int vfslocked;
+
+	VM_OBJECT_LOCK(object);
+
+	/*
+	 * First, recheck the object type to account for the race when
+	 * the vnode is reclaimed.
+	 */
+	if (object->type != OBJT_VNODE) {
+		VM_OBJECT_UNLOCK(object);
+		return;
+	}
+
+	/*
+	 * Optimize for the case when writemappings is not going to
+	 * zero.
+	 */
+	inc = end - start;
+	if (object->un_pager.vnp.writemappings != inc) {
+		object->un_pager.vnp.writemappings -= inc;
+		VM_OBJECT_UNLOCK(object);
+		return;
+	}
+
+	vp = object->handle;
+	vhold(vp);
+	VM_OBJECT_UNLOCK(object);
+	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+	mp = NULL;
+	vn_start_write(vp, &mp, V_WAIT);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+
+	/*
+	 * Decrement the object's writemappings, by swapping the start
+	 * and end arguments for vnode_pager_update_writecount().  If
+	 * there was not a race with vnode reclaimation, then the
+	 * vnode's v_writecount is decremented.
+	 */
+	vnode_pager_update_writecount(object, end, start);
+	VOP_UNLOCK(vp, 0);
+	vdrop(vp);
+	if (mp != NULL)
+		vn_finished_write(mp);
+	VFS_UNLOCK_GIANT(vfslocked);
+}
diff -r 4bd6486a01ce -r 8bf40f27aa20 head/sys/vm/vnode_pager.h
--- a/head/sys/vm/vnode_pager.h	Fri Mar 02 17:15:56 2012 +0200
+++ b/head/sys/vm/vnode_pager.h	Fri Mar 02 17:16:20 2012 +0200
@@ -32,7 +32,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)vnode_pager.h	8.1 (Berkeley) 6/11/93
- * $FreeBSD: head/sys/vm/vnode_pager.h 222586 2011-06-01 21:00:28Z kib $
+ * $FreeBSD: head/sys/vm/vnode_pager.h 232071 2012-02-23 21:07:16Z kib $
  */
 
 #ifndef	_VNODE_PAGER_
@@ -40,17 +40,17 @@
 
 #ifdef _KERNEL
 
-/*
- * XXX Generic routines; currently called by badly written FS code; these
- * XXX should go away soon.
- */
 int vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m,
 					  int count, int reqpage);
 int vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *m,
 					  int count, boolean_t sync,
 					  int *rtvals);
 
+void vnode_pager_release_writecount(vm_object_t object, vm_offset_t start,
+    vm_offset_t end);
 void vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written);
+void vnode_pager_update_writecount(vm_object_t object, vm_offset_t start,
+    vm_offset_t end);
 
 #endif				/* _KERNEL */
 #endif				/* _VNODE_PAGER_ */


More information about the Zrouter-src-freebsd mailing list