Author: kib
Date: Sun Sep  8 17:51:22 2013
New Revision: 255396
URL: http://svnweb.freebsd.org/changeset/base/255396

Log:
  Drain for the xbusy state for two places which potentially do
  pmap_remove_all(). Not doing the drain allows the pmap_enter() to
  proceed in parallel, making the pmap_remove_all() effects void.
  
  The race results in an invalidated page mapped wired by usermode.
  
  Reported and tested by:       pho
  Reviewed by:  alc
  Sponsored by: The FreeBSD Foundation
  Approved by:  re (glebius)

Modified:
  head/sys/kern/vfs_bio.c
  head/sys/vm/vm_object.c

Modified: head/sys/kern/vfs_bio.c
==============================================================================
--- head/sys/kern/vfs_bio.c     Sun Sep  8 17:47:14 2013        (r255395)
+++ head/sys/kern/vfs_bio.c     Sun Sep  8 17:51:22 2013        (r255396)
@@ -1693,6 +1693,12 @@ brelse(struct buf *bp)
 
                                KASSERT(presid >= 0, ("brelse: extra page"));
                                VM_OBJECT_WLOCK(obj);
+                               while (vm_page_xbusied(m)) {
+                                       vm_page_lock(m);
+                                       VM_OBJECT_WUNLOCK(obj);
+                                       vm_page_busy_sleep(m, "mbncsh");
+                                       VM_OBJECT_WLOCK(obj);
+                               }
                                if (pmap_page_wired_mappings(m) == 0)
                                        vm_page_set_invalid(m, poffset, presid);
                                VM_OBJECT_WUNLOCK(obj);

Modified: head/sys/vm/vm_object.c
==============================================================================
--- head/sys/vm/vm_object.c     Sun Sep  8 17:47:14 2013        (r255395)
+++ head/sys/vm/vm_object.c     Sun Sep  8 17:51:22 2013        (r255396)
@@ -1910,6 +1910,12 @@ again:
                 * not specified.
                 */
                vm_page_lock(p);
+               if (vm_page_xbusied(p)) {
+                       VM_OBJECT_WUNLOCK(object);
+                       vm_page_busy_sleep(p, "vmopax");
+                       VM_OBJECT_WLOCK(object);
+                       goto again;
+               }
                if ((wirings = p->wire_count) != 0 &&
                    (wirings = pmap_page_wired_mappings(p)) != p->wire_count) {
                        if ((options & (OBJPR_NOTWIRED | OBJPR_NOTMAPPED)) ==
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to