Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/rump/librump/rumpvfs tmpfs has two layers of uvm objects...



details:   https://anonhg.NetBSD.org/src/rev/c8dcf9c7eadc
branches:  trunk
changeset: 762758:c8dcf9c7eadc
user:      pooka <pooka%NetBSD.org@localhost>
date:      Sun Feb 27 13:37:39 2011 +0000

description:
tmpfs has two layers of uvm objects (vnode->uobj and the anon object
in tmpfs_node), so when playing with pages make sure we lock the
uvm object the pages belong to instead of the vnode's uvm object.

per test from Nicolas Joly (which I'm sure he will commit soon ;)

diffstat:

 sys/rump/librump/rumpvfs/vm_vfs.c |  32 ++++++++++++++++++++++++--------
 1 files changed, 24 insertions(+), 8 deletions(-)

diffs (111 lines):

diff -r 388290386545 -r c8dcf9c7eadc sys/rump/librump/rumpvfs/vm_vfs.c
--- a/sys/rump/librump/rumpvfs/vm_vfs.c Sun Feb 27 13:05:38 2011 +0000
+++ b/sys/rump/librump/rumpvfs/vm_vfs.c Sun Feb 27 13:37:39 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vm_vfs.c,v 1.25 2011/02/22 20:17:37 pooka Exp $        */
+/*     $NetBSD: vm_vfs.c,v 1.26 2011/02/27 13:37:39 pooka Exp $        */
 
 /*
  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.25 2011/02/22 20:17:37 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.26 2011/02/27 13:37:39 pooka Exp $");
 
 #include <sys/param.h>
 
@@ -109,6 +109,7 @@
 {
        struct uvm_object *uobj = &vp->v_uobj;
        struct vm_page **pgs;
+       struct uvm_object *pguobj;
        int maxpages = MIN(32, round_page(len) >> PAGE_SHIFT);
        int rv, npages, i;
 
@@ -125,7 +126,7 @@
                    0, PAGERFLAGS | PGO_PASTEOF);
                KASSERT(npages > 0);
 
-               for (i = 0; i < npages; i++) {
+               for (i = 0, pguobj = NULL; i < npages; i++) {
                        struct vm_page *pg;
                        uint8_t *start;
                        size_t chunkoff, chunklen;
@@ -133,6 +134,9 @@
                        pg = pgs[i];
                        if (pg == NULL)
                                break;
+                       if (pguobj == NULL)
+                               pguobj = pg->uobject;
+                       KASSERT(pguobj == pg->uobject);
 
                        chunkoff = off & PAGE_MASK;
                        chunklen = MIN(PAGE_SIZE - chunkoff, len);
@@ -144,8 +148,12 @@
                        off += chunklen;
                        len -= chunklen;
                }
-               mutex_enter(&uobj->vmobjlock);
+               mutex_enter(&pguobj->vmobjlock);
                uvm_page_unbusy(pgs, npages);
+               if (pguobj != uobj) {
+                       mutex_exit(&pguobj->vmobjlock);
+                       mutex_enter(&uobj->vmobjlock);
+               }
        }
        mutex_exit(&uobj->vmobjlock);
        kmem_free(pgs, maxpages * sizeof(pgs));
@@ -161,6 +169,7 @@
        int advice, int flags)
 {
        struct vm_page **pgs;
+       struct uvm_object *pguobj;
        int npages = len2npages(uio->uio_offset, todo);
        size_t pgalloc;
        int i, rv, pagerflags;
@@ -184,7 +193,7 @@
                if (rv)
                        goto out;
 
-               for (i = 0; i < npages; i++) {
+               for (i = 0, pguobj = NULL; i < npages; i++) {
                        struct vm_page *pg;
                        size_t xfersize;
                        off_t pageoff;
@@ -192,6 +201,9 @@
                        pg = pgs[i];
                        if (pg == NULL)
                                break;
+                       if (pguobj == NULL)
+                               pguobj = pg->uobject;
+                       KASSERT(pguobj == pg->uobject);
 
                        pageoff = uio->uio_offset & PAGE_MASK;
                        xfersize = MIN(MIN(todo, PAGE_SIZE), PAGE_SIZE-pageoff);
@@ -199,17 +211,21 @@
                        rv = uiomove((uint8_t *)pg->uanon + pageoff,
                            xfersize, uio);
                        if (rv) {
-                               mutex_enter(&uobj->vmobjlock);
+                               mutex_enter(&pguobj->vmobjlock);
                                uvm_page_unbusy(pgs, npages);
-                               mutex_exit(&uobj->vmobjlock);
+                               mutex_exit(&pguobj->vmobjlock);
                                goto out;
                        }
                        if (uio->uio_rw == UIO_WRITE)
                                pg->flags &= ~(PG_CLEAN | PG_FAKE);
                        todo -= xfersize;
                }
-               mutex_enter(&uobj->vmobjlock);
+               mutex_enter(&pguobj->vmobjlock);
                uvm_page_unbusy(pgs, npages);
+               if (pguobj != uobj) {
+                       mutex_exit(&pguobj->vmobjlock);
+                       mutex_enter(&uobj->vmobjlock);
+               }
        } while (todo);
        mutex_exit(&uobj->vmobjlock);
 



Home | Main Index | Thread Index | Old Index