On 17/02/21(Wed) 11:56, Martin Pieuchot wrote:
> Diff below adds anon locking to the page daemon. It will become
> necessary to guarantee exclusive access to an anon as soon as the
> KERNEL_LOCK() is removed from the fault handler.
Anyone? This should have been part of the already committed anon
locking.
> Index: uvm/uvm_pdaemon.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_pdaemon.c,v
> retrieving revision 1.88
> diff -u -p -r1.88 uvm_pdaemon.c
> --- uvm/uvm_pdaemon.c 24 Nov 2020 13:49:09 -0000 1.88
> +++ uvm/uvm_pdaemon.c 17 Feb 2021 10:05:43 -0000
> @@ -460,7 +460,13 @@ uvmpd_scan_inactive(struct pglist *pglst
> if (p->pg_flags & PQ_ANON) {
> anon = p->uanon;
> KASSERT(anon != NULL);
> + if (rw_enter(anon->an_lock,
> + RW_WRITE|RW_NOSLEEP)) {
> + /* lock failed, skip this page */
> + continue;
> + }
> if (p->pg_flags & PG_BUSY) {
> + rw_exit(anon->an_lock);
> uvmexp.pdbusy++;
> /* someone else owns page, skip it */
> continue;
> @@ -504,6 +510,7 @@ uvmpd_scan_inactive(struct pglist *pglst
>
> /* remove from object */
> anon->an_page = NULL;
> + rw_exit(anon->an_lock);
> }
> continue;
> }
> @@ -513,6 +520,9 @@ uvmpd_scan_inactive(struct pglist *pglst
> * free target when all the current pageouts complete.
> */
> if (free + uvmexp.paging > uvmexp.freetarg << 2) {
> + if (anon) {
> + rw_exit(anon->an_lock);
> + }
> continue;
> }
>
> @@ -525,6 +535,9 @@ uvmpd_scan_inactive(struct pglist *pglst
> if ((p->pg_flags & PQ_SWAPBACKED) && uvm_swapisfull()) {
> dirtyreacts++;
> uvm_pageactivate(p);
> + if (anon) {
> + rw_exit(anon->an_lock);
> + }
> continue;
> }
>
> @@ -591,6 +604,8 @@ uvmpd_scan_inactive(struct pglist *pglst
> &p->pg_flags,
> PG_BUSY);
> UVM_PAGE_OWN(p, NULL);
> + if (anon)
> + rw_exit(anon->an_lock);
> continue;
> }
> swcpages = 0; /* cluster is empty */
> @@ -622,6 +637,9 @@ uvmpd_scan_inactive(struct pglist *pglst
> */
> if (swap_backed) {
> if (p) { /* if we just added a page to cluster */
> + if (anon)
> + rw_exit(anon->an_lock);
> +
> /* cluster not full yet? */
> if (swcpages < swnpages)
> continue;
> @@ -730,6 +748,12 @@ uvmpd_scan_inactive(struct pglist *pglst
> /* relock p's object: page queues not lock yet, so
> * no need for "try" */
>
> + /* !swap_backed case: already locked... */
> + if (swap_backed) {
> + if (anon)
> + rw_enter(anon->an_lock, RW_WRITE);
> + }
> +
> #ifdef DIAGNOSTIC
> if (result == VM_PAGER_UNLOCK)
> panic("pagedaemon: pageout returned "
> @@ -754,6 +778,7 @@ uvmpd_scan_inactive(struct pglist *pglst
> anon->an_page = NULL;
> p->uanon = NULL;
>
> + rw_exit(anon->an_lock);
> uvm_anfree(anon); /* kills anon */
> pmap_page_protect(p, PROT_NONE);
> anon = NULL;
> @@ -787,6 +812,8 @@ uvmpd_scan_inactive(struct pglist *pglst
> * the inactive queue can't be re-queued [note: not
> * true for active queue]).
> */
> + if (anon)
> + rw_exit(anon->an_lock);
>
> if (nextpg && (nextpg->pg_flags & PQ_INACTIVE) == 0) {
> nextpg = TAILQ_FIRST(pglst); /* reload! */
> @@ -893,9 +920,11 @@ uvmpd_scan(void)
> if (p->pg_flags & PG_BUSY)
> continue;
>
> - if (p->pg_flags & PQ_ANON)
> + if (p->pg_flags & PQ_ANON) {
> KASSERT(p->uanon != NULL);
> - else
> + if (rw_enter(p->uanon->an_lock, RW_WRITE|RW_NOSLEEP))
> + continue;
> + } else
> KASSERT(p->uobject != NULL);
>
> /*
> @@ -932,6 +961,8 @@ uvmpd_scan(void)
> uvmexp.pddeact++;
> inactive_shortage--;
> }
> + if (p->pg_flags & PQ_ANON)
> + rw_exit(p->uanon->an_lock);
> }
> }
>
>