From: Jason Gunthorpe <jgg@nvidia.com>
To: sooraj <sooraj20636@gmail.com>
Cc: linux-mm@kvack.org
Subject: Re: [PATCH] mm/hmm: Prevent infinite loop in hmm_range_fault during EBUSY retries
Date: Tue, 28 Jan 2025 14:04:22 -0400 [thread overview]
Message-ID: <20250128180422.GA1862569@nvidia.com> (raw)
In-Reply-To: <20250128063422.7604-1-sooraj20636@gmail.com>
On Tue, Jan 28, 2025 at 01:34:22AM -0500, sooraj wrote:
> When hmm_vma_walk_test() skips a VMA (e.g., unsupported VM_IO/PFNMAP range),
> it must update hmm_vma_walk->last to the end of the skipped VMA. Failing to
> do so causes hmm_range_fault() to restart from the same address during
> -EBUSY retries, reprocessing the skipped VMA indefinitely. This results in
> an infinite loop if the VMA remains non-processable.
This needs alot more explanation.
The only place last is read is here:
ret = walk_page_range(mm, hmm_vma_walk.last, range->end,
&hmm_walk_ops, &hmm_vma_walk);
/*
* When -EBUSY is returned the loop restarts with
* hmm_vma_walk.last set to an address that has not been stored
* in pfns. All entries < last in the pfn array are set to their
* output, and all >= are still at their input values.
*/
} while (ret == -EBUSY);
The idea being that when a lower function returns -EBUSY last tells
this loop where to restart the iteration.
> @@ -547,6 +547,8 @@ static int hmm_vma_walk_test(unsigned long start, unsigned long end,
>
> hmm_pfns_fill(start, end, range, HMM_PFN_ERROR);
>
> + /* Update last to the end of the skipped VMA to prevent reprocessing */
> + hmm_vma_walk->last = end;
This does not return EBUSY, so it does not need to set last.
I just checked against and all the places that return EBUSY, do set last:
static int hmm_vma_fault(unsigned long addr, unsigned long end,
unsigned int required_fault, struct mm_walk *walk)
{
hmm_vma_walk->last = addr;
..
return -EBUSY;
static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
unsigned long end, pmd_t *pmdp, pte_t *ptep,
unsigned long *hmm_pfn)
{
...
hmm_vma_walk->last = addr;
migration_entry_wait(walk->mm, pmdp, addr);
return -EBUSY;
static int hmm_vma_walk_pmd(pmd_t *pmdp,
unsigned long start,
unsigned long end,
struct mm_walk *walk)
{
...
hmm_vma_walk->last = addr;
pmd_migration_entry_wait(walk->mm, pmdp);
return -EBUSY;
}
Thats it. If an -EBUSY case has been missed it should be fixed at the
-EBUSY return point, anything else is wrong.
If you are seeing an infinite loop that this actually fixes please
explain in the commit message exactly how it arises, and where the
-EBUSY came from to miss the last update.
If there is a loop due to a missed -EBUSY, then this is not the
correct way to fix it.
Jason
prev parent reply other threads:[~2025-01-28 18:04 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-28 6:34 sooraj
2025-01-28 1:00 ` Andrew Morton
2025-01-28 1:16 ` Alistair Popple
2025-01-28 18:04 ` Jason Gunthorpe [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250128180422.GA1862569@nvidia.com \
--to=jgg@nvidia.com \
--cc=linux-mm@kvack.org \
--cc=sooraj20636@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox