Author: kib
Date: Thu Jul 11 05:47:26 2013
New Revision: 253189
URL: http://svnweb.freebsd.org/changeset/base/253189

Log:
  Never remove user-wired pages from an object when doing
  msync(MS_INVALIDATE).  The vm_fault_copy_entry() requires that object
  range which corresponds to the user-wired vm_map_entry, is always
  fully populated.
  
  Add OBJPR_NOTWIRED flag for vm_object_page_remove() to request the
  preserving behaviour, use it when calling vm_object_page_remove() from
  vm_object_sync().
  
  Reported and tested by:       pho
  Reviewed by:  alc
  Sponsored by: The FreeBSD Foundation
  MFC after:    2 weeks

Modified:
  head/sys/vm/vm_object.c
  head/sys/vm/vm_object.h

Modified: head/sys/vm/vm_object.c
==============================================================================
--- head/sys/vm/vm_object.c     Thu Jul 11 05:38:39 2013        (r253188)
+++ head/sys/vm/vm_object.c     Thu Jul 11 05:47:26 2013        (r253189)
@@ -1054,9 +1054,9 @@ vm_object_sync(vm_object_t object, vm_oo
                         */
                        flags = OBJPR_NOTMAPPED;
                else if (old_msync)
-                       flags = 0;
+                       flags = OBJPR_NOTWIRED;
                else
-                       flags = OBJPR_CLEANONLY;
+                       flags = OBJPR_CLEANONLY | OBJPR_NOTWIRED;
                vm_object_page_remove(object, OFF_TO_IDX(offset),
                    OFF_TO_IDX(offset + size + PAGE_MASK), flags);
        }
@@ -1892,7 +1892,8 @@ again:
                vm_page_lock(p);
                if ((wirings = p->wire_count) != 0 &&
                    (wirings = pmap_page_wired_mappings(p)) != p->wire_count) {
-                       if ((options & OBJPR_NOTMAPPED) == 0) {
+                       if ((options & (OBJPR_NOTWIRED | OBJPR_NOTMAPPED)) ==
+                           0) {
                                pmap_remove_all(p);
                                /* Account for removal of wired mappings. */
                                if (wirings != 0)
@@ -1902,8 +1903,7 @@ again:
                                p->valid = 0;
                                vm_page_undirty(p);
                        }
-                       vm_page_unlock(p);
-                       continue;
+                       goto next;
                }
                if (vm_page_sleep_if_busy(p, TRUE, "vmopar"))
                        goto again;
@@ -1912,12 +1912,12 @@ again:
                if ((options & OBJPR_CLEANONLY) != 0 && p->valid != 0) {
                        if ((options & OBJPR_NOTMAPPED) == 0)
                                pmap_remove_write(p);
-                       if (p->dirty) {
-                               vm_page_unlock(p);
-                               continue;
-                       }
+                       if (p->dirty)
+                               goto next;
                }
                if ((options & OBJPR_NOTMAPPED) == 0) {
+                       if ((options & OBJPR_NOTWIRED) != 0 && wirings != 0)
+                               goto next;
                        pmap_remove_all(p);
                        /* Account for removal of wired mappings. */
                        if (wirings != 0) {
@@ -1929,6 +1929,7 @@ again:
                        }
                }
                vm_page_free(p);
+next:
                vm_page_unlock(p);
        }
        vm_object_pip_wakeup(object);

Modified: head/sys/vm/vm_object.h
==============================================================================
--- head/sys/vm/vm_object.h     Thu Jul 11 05:38:39 2013        (r253188)
+++ head/sys/vm/vm_object.h     Thu Jul 11 05:47:26 2013        (r253189)
@@ -205,6 +205,7 @@ struct vm_object {
  */
 #define        OBJPR_CLEANONLY 0x1             /* Don't remove dirty pages. */
 #define        OBJPR_NOTMAPPED 0x2             /* Don't unmap pages. */
+#define        OBJPR_NOTWIRED  0x4             /* Don't remove wired pages. */
 
 TAILQ_HEAD(object_q, vm_object);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to