On Wed, 22 Jul 2026 14:44:22 -0700 Stanislav Kinsburskii
<[email protected]> wrote:
> This series extends the HMM framework to support userfaultfd-backed memory
> by allowing the mmap read lock to be dropped during hmm_range_fault().
Thanks, I've updated mm.git's mm-unstable branch to this version.
Sashiko pointed at a few things, some pre-existing. The jiffies race
in [8/8] looks legit.
https://sashiko.dev/#/patchset/[email protected]
> Changes in v10:
> - Included contended mmap_lock acquisition in the
> hmm_range_fault_unlocked_timeout() retry budget.
> - Dropped the redundant top-level fatal_signal_pending() check in the HMM
> unlocked retry loop; mmap_read_lock_killable() now covers that path.
> - Restored the absolute outer timeout in drm_gpusvm_get_pages(), since it
> can
> run from GPU page-fault workers and must not rely on the worker task’s
> fatal
> signal state to stop invalidation retries.
Here's how v10 altered mm.git:
drivers/gpu/drm/drm_gpusvm.c | 11 +++++++++--
mm/hmm.c | 29 +++++++++++++----------------
2 files changed, 22 insertions(+), 18 deletions(-)
--- a/drivers/gpu/drm/drm_gpusvm.c~b
+++ a/drivers/gpu/drm/drm_gpusvm.c
@@ -1405,7 +1405,9 @@ int drm_gpusvm_get_pages(struct drm_gpus
.dev_private_owner = ctx->device_private_page_owner,
};
void *zdd;
- unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+ unsigned long timeout =
+ jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+ unsigned long remaining;
unsigned long i, j;
unsigned long npages = npages_in_range(pages_start, pages_end);
unsigned long num_dma_mapped;
@@ -1420,6 +1422,11 @@ int drm_gpusvm_get_pages(struct drm_gpus
struct dma_iova_state *state = &svm_pages->state;
retry:
+ if (time_after_eq(jiffies, timeout))
+ return -EBUSY;
+
+ remaining = timeout - jiffies;
+
hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
goto set_seqno;
@@ -1434,7 +1441,7 @@ retry:
}
hmm_range.hmm_pfns = pfns;
- err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
+ err = hmm_range_fault_unlocked_timeout(&hmm_range, remaining);
mmput(mm);
if (err)
goto err_free;
--- a/mm/hmm.c~b
+++ a/mm/hmm.c
@@ -790,22 +790,14 @@ int hmm_range_fault_unlocked_timeout(str
int ret;
do {
- if (fatal_signal_pending(current))
- return -EINTR;
-
- if (timeout) {
- /*
- * If the previous fault dropped mmap_lock, then the
fault
- * handler made progress. Restart the retry timeout in
that
- * case, but keep the existing deadline for ordinary
-EBUSY
- * retries.
- */
- if (!locked)
- deadline = jiffies + timeout;
-
- if (time_after(jiffies, deadline))
- return -EBUSY;
- }
+ /*
+ * If the previous fault dropped mmap_lock, then the fault
+ * handler made progress. Restart the retry timeout in that
+ * case, but keep the existing deadline for ordinary -EBUSY
+ * retries.
+ */
+ if (timeout && !locked)
+ deadline = jiffies + timeout;
range->notifier_seq =
mmu_interval_read_begin(range->notifier);
@@ -814,6 +806,11 @@ int hmm_range_fault_unlocked_timeout(str
if (ret)
return ret;
+ if (timeout && time_after(jiffies, deadline)) {
+ mmap_read_unlock(mm);
+ return -EBUSY;
+ }
+
locked = true;
ret = hmm_range_fault_locked(range, &locked);
if (locked)
_