Download raw body.
Introduce uvm_promote()
> Date: Wed, 18 Dec 2024 18:06:56 +0100
> From: Martin Pieuchot <mpi@grenadille.net>
>
> Diff below merges two code paths that allocate a new anon and copy the
> content of a page.
>
> ok?
I think you should move the flt_prcopy counter increment into the new function as well.
> Index: uvm/uvm_fault.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_fault.c,v
> diff -u -p -r1.154 uvm_fault.c
> --- uvm/uvm_fault.c 18 Dec 2024 16:41:27 -0000 1.154
> +++ uvm/uvm_fault.c 18 Dec 2024 17:00:56 -0000
> @@ -485,6 +485,68 @@ uvmfault_anonget(struct uvm_faultinfo *u
> }
>
> /*
> + * uvmfault_promote: promote data to a new anon. used for 1B and 2B.
> + *
> + * 1. allocate an anon and a page.
> + * 2. fill its contents.
> + *
> + * => if we fail (result != 0) we unlock everything.
> + * => on success, return a new locked anon via 'nanon'.
> + * => it's caller's responsibility to put the promoted nanon->an_page to the
> + * page queue.
> + */
> +int
> +uvmfault_promote(struct uvm_faultinfo *ufi,
> + struct vm_page *uobjpage,
> + struct vm_anon **nanon, /* OUT: allocated anon */
> + struct vm_page **npg)
> +{
> + struct vm_amap *amap = ufi->entry->aref.ar_amap;
> + struct vm_anon *anon;
> + struct vm_page *pg = NULL;
> +
> + anon = uvm_analloc();
> + if (anon) {
> + anon->an_lock = amap->am_lock;
> + pg = uvm_pagealloc(NULL, 0, anon,
> + (uobjpage == PGO_DONTCARE) ? UVM_PGA_ZERO : 0);
> + }
> +
> + /* check for out of RAM */
> + if (anon == NULL || pg == NULL) {
> + uvmfault_unlockall(ufi, amap, NULL);
> + if (anon == NULL)
> + counters_inc(uvmexp_counters, flt_noanon);
> + else {
> + anon->an_lock = NULL;
> + anon->an_ref--;
> + uvm_anfree(anon);
> + counters_inc(uvmexp_counters, flt_noram);
> + }
> +
> + if (uvm_swapisfull())
> + return ENOMEM;
> +
> + /* out of RAM, wait for more */
> + if (anon == NULL)
> + uvm_anwait();
> + else
> + uvm_wait("flt_noram3");
> + return ERESTART;
> + }
> +
> + /*
> + * copy the page [pg now dirty]
> + */
> + if (uobjpage != PGO_DONTCARE)
> + uvm_pagecopy(uobjpage, pg);
> +
> + *nanon = anon;
> + *npg = pg;
> + return 0;
> +}
> +
> +/*
> * Update statistics after fault resolution.
> * - maxrss
> */
> @@ -972,37 +1034,11 @@ uvm_fault_upper(struct uvm_faultinfo *uf
>
> counters_inc(uvmexp_counters, flt_acow);
> oanon = anon; /* oanon = old */
> - anon = uvm_analloc();
> - if (anon) {
> - anon->an_lock = amap->am_lock;
> - pg = uvm_pagealloc(NULL, 0, anon, 0);
> - }
> -
> - /* check for out of RAM */
> - if (anon == NULL || pg == NULL) {
> - uvmfault_unlockall(ufi, amap, NULL);
> - if (anon == NULL)
> - counters_inc(uvmexp_counters, flt_noanon);
> - else {
> - anon->an_lock = NULL;
> - anon->an_ref--;
> - uvm_anfree(anon);
> - counters_inc(uvmexp_counters, flt_noram);
> - }
>
> - if (uvm_swapisfull())
> - return ENOMEM;
> -
> - /* out of RAM, wait for more */
> - if (anon == NULL)
> - uvm_anwait();
> - else
> - uvm_wait("flt_noram3");
> - return ERESTART;
> - }
> + error = uvmfault_promote(ufi, oanon->an_page, &anon, &pg);
> + if (error)
> + return error;
>
> - /* got all resources, replace anon with nanon */
> - uvm_pagecopy(oanon->an_page, pg); /* pg now !PG_CLEAN */
> /* un-busy! new page */
> atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE);
> UVM_PAGE_OWN(pg, NULL);
> @@ -1314,53 +1350,15 @@ uvm_fault_lower(struct uvm_faultinfo *uf
> if (amap == NULL)
> panic("uvm_fault: want to promote data, but no anon");
> #endif
> -
> - anon = uvm_analloc();
> - if (anon) {
> - /*
> - * In `Fill in data...' below, if
> - * uobjpage == PGO_DONTCARE, we want
> - * a zero'd, dirty page, so have
> - * uvm_pagealloc() do that for us.
> - */
> - anon->an_lock = amap->am_lock;
> - pg = uvm_pagealloc(NULL, 0, anon,
> - (uobjpage == PGO_DONTCARE) ? UVM_PGA_ZERO : 0);
> - }
> -
> - /*
> - * out of memory resources?
> - */
> - if (anon == NULL || pg == NULL) {
> - /* unlock and fail ... */
> - uvmfault_unlockall(ufi, amap, uobj);
> - if (anon == NULL)
> - counters_inc(uvmexp_counters, flt_noanon);
> - else {
> - anon->an_lock = NULL;
> - anon->an_ref--;
> - uvm_anfree(anon);
> - counters_inc(uvmexp_counters, flt_noram);
> - }
> -
> - if (uvm_swapisfull())
> - return (ENOMEM);
> -
> - /* out of RAM, wait for more */
> - if (anon == NULL)
> - uvm_anwait();
> - else
> - uvm_wait("flt_noram5");
> - return ERESTART;
> - }
> + error = uvmfault_promote(ufi, uobjpage, &anon, &pg);
> + if (error)
> + return error;
>
> /*
> * fill in the data
> */
> if (uobjpage != PGO_DONTCARE) {
> counters_inc(uvmexp_counters, flt_prcopy);
> - /* copy page [pg now dirty] */
> - uvm_pagecopy(uobjpage, pg);
>
> /*
> * promote to shared amap? make sure all sharing
>
>
>
Introduce uvm_promote()