The diff below (re)introduces the active/inactive page queue lock.
This will be necessary to make progress with remove the need for
grabbing the kernel lock in more parts of uvm, such as the pagedaemon
and the uvm_fault().

This was tried once before.  And subsequently backed out because:

  Revert pageqlock back from a mutex to a simple_lock, as it needs to be
  recursive in some cases (mostly involving swapping). A proper fix is in
  the works, but this will unbreak kernels for now.

Remember, simple_lock was really simple; it didn't do any locking at all!

I'm not sure the proper fix ever happened.  I've verified to my
satisfaction that there are no lock ordering problems with the free
page queue lock.  And some initial testing on sparc64 did not hit any
lock recursion in the swap code.  But I could use some help testing
that this is indeed safe.


Index: uvm.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm.h,v
retrieving revision 1.59
diff -u -p -r1.59 uvm.h
--- uvm.h       4 May 2015 10:21:15 -0000       1.59
+++ uvm.h       27 Sep 2015 18:47:00 -0000
@@ -54,6 +54,7 @@ struct uvm {
        struct pglist page_inactive_swp;/* pages inactive (reclaim or free) */
        struct pglist page_inactive_obj;/* pages inactive (reclaim or free) */
        /* Lock order: pageqlock, then fpageqlock. */
+       struct mutex pageqlock;         /* lock for active/inactive page q */
        struct mutex fpageqlock;        /* lock for free page q  + pdaemon */
        boolean_t page_init_done;       /* TRUE if uvm_page_init() finished */
        struct uvm_pmr_control pmr_control; /* pmemrange data */
Index: uvm_page.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_page.c,v
retrieving revision 1.142
diff -u -p -r1.142 uvm_page.c
--- uvm_page.c  21 Sep 2015 12:59:01 -0000      1.142
+++ uvm_page.c  27 Sep 2015 18:47:00 -0000
@@ -179,6 +179,7 @@ uvm_page_init(vaddr_t *kvm_startp, vaddr
        TAILQ_INIT(&uvm.page_active);
        TAILQ_INIT(&uvm.page_inactive_swp);
        TAILQ_INIT(&uvm.page_inactive_obj);
+       mtx_init(&uvm.pageqlock, IPL_NONE);
        mtx_init(&uvm.fpageqlock, IPL_VM);
        uvm_pmr_init();
 
Index: uvm_page.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_page.h,v
retrieving revision 1.59
diff -u -p -r1.59 uvm_page.h
--- uvm_page.h  21 Aug 2015 16:04:35 -0000      1.59
+++ uvm_page.h  27 Sep 2015 18:47:00 -0000
@@ -285,8 +285,8 @@ int         vm_physseg_find(paddr_t, int *);
  * macros
  */
 
-#define uvm_lock_pageq()       /* lock */
-#define uvm_unlock_pageq()     /* unlock */
+#define uvm_lock_pageq()       mtx_enter(&uvm.pageqlock)
+#define uvm_unlock_pageq()     mtx_leave(&uvm.pageqlock)
 #define uvm_lock_fpageq()      mtx_enter(&uvm.fpageqlock)
 #define uvm_unlock_fpageq()    mtx_leave(&uvm.fpageqlock)
 
Index: uvm_pdaemon.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_pdaemon.c,v
retrieving revision 1.76
diff -u -p -r1.76 uvm_pdaemon.c
--- uvm_pdaemon.c       21 Aug 2015 16:04:35 -0000      1.76
+++ uvm_pdaemon.c       27 Sep 2015 18:47:00 -0000
@@ -237,7 +237,9 @@ uvm_pageout(void *arg)
                if (uvmexp.free - BUFPAGES_DEFICIT < uvmexp.freetarg)
                        size += uvmexp.freetarg - (uvmexp.free -
                            BUFPAGES_DEFICIT);
+               uvm_unlock_pageq();
                (void) bufbackoff(&constraint, size * 2);
+               uvm_lock_pageq();
 
                /* Scan if needed to meet our targets. */
                if (pma != NULL ||

Reply via email to