mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
mshv: use hmm_range_fault_unlocked_timeout() for region faults
MSHV currently faults movable memory regions by taking mmap_read_lock() around hmm_range_fault(). That prevents the fault path from handling VMAs whose fault handlers need to drop mmap_lock, such as userfaultfd-backed mappings. Use hmm_range_fault_unlocked_timeout() instead. Passing a timeout of 0 preserves MSHV's existing unbounded retry behavior while letting the HMM helper own mmap_lock acquisition and refresh range->notifier_seq internally before walking the range. After the fault succeeds, MSHV still takes mreg_mutex and checks mmu_interval_read_retry() before installing the pages into the region, so the existing invalidation synchronization is preserved. Fold the small fault-and-lock helper into mshv_region_range_fault(), since the remaining retry path is just the standard "fault, take the driver lock, check the interval notifier sequence" pattern. Link: https://lore.kernel.org/20260723-hmm-v10-v11-4-c55b003a4b61@gmail.com Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Cc: Danilo Krummrich <dakr@kernel.org> Cc: Dave Airlie <airlied@gmail.com> Cc: David Hildenbrand <david@kernel.org> Cc: Dexuan Cui <decui@microsoft.com> Cc: Haiyang Zhang <haiyangz@microsoft.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: K. Y. Srinivasan <kys@microsoft.com> Cc: Leon Romanovsky <leon@kernel.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lizhi Hou <lizhi.hou@amd.com> Cc: Long Li <longli@microsoft.com> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Lyude <lyude@redhat.com> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <mripard@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Oded Gabbay <ogabbay@kernel.org> Cc: Shuah Khan <shuah@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Thomas Zimemrmann <tzimmermann@suse.de> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Wei Liu <wei.liu@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
9365813cad
commit
39899823ad
|
|
@ -381,46 +381,6 @@ int mshv_region_get(struct mshv_mem_region *region)
|
|||
return kref_get_unless_zero(®ion->mreg_refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* mshv_region_hmm_fault_and_lock - Handle HMM faults and lock the memory region
|
||||
* @region: Pointer to the memory region structure
|
||||
* @range: Pointer to the HMM range structure
|
||||
*
|
||||
* This function performs the following steps:
|
||||
* 1. Reads the notifier sequence for the HMM range.
|
||||
* 2. Acquires a read lock on the memory map.
|
||||
* 3. Handles HMM faults for the specified range.
|
||||
* 4. Releases the read lock on the memory map.
|
||||
* 5. If successful, locks the memory region mutex.
|
||||
* 6. Verifies if the notifier sequence has changed during the operation.
|
||||
* If it has, releases the mutex and returns -EBUSY to match with
|
||||
* hmm_range_fault() return code for repeating.
|
||||
*
|
||||
* Return: 0 on success, a negative error code otherwise.
|
||||
*/
|
||||
static int mshv_region_hmm_fault_and_lock(struct mshv_mem_region *region,
|
||||
struct hmm_range *range)
|
||||
{
|
||||
int ret;
|
||||
|
||||
range->notifier_seq = mmu_interval_read_begin(range->notifier);
|
||||
mmap_read_lock(region->mreg_mni.mm);
|
||||
ret = hmm_range_fault(range);
|
||||
mmap_read_unlock(region->mreg_mni.mm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(®ion->mreg_mutex);
|
||||
|
||||
if (mmu_interval_read_retry(range->notifier, range->notifier_seq)) {
|
||||
mutex_unlock(®ion->mreg_mutex);
|
||||
cond_resched();
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mshv_region_range_fault - Handle memory range faults for a given region.
|
||||
* @region: Pointer to the memory region structure.
|
||||
|
|
@ -452,13 +412,19 @@ static int mshv_region_range_fault(struct mshv_mem_region *region,
|
|||
range.start = region->start_uaddr + page_offset * HV_HYP_PAGE_SIZE;
|
||||
range.end = range.start + page_count * HV_HYP_PAGE_SIZE;
|
||||
|
||||
do {
|
||||
ret = mshv_region_hmm_fault_and_lock(region, &range);
|
||||
} while (ret == -EBUSY);
|
||||
|
||||
again:
|
||||
ret = hmm_range_fault_unlocked_timeout(&range, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mutex_lock(®ion->mreg_mutex);
|
||||
|
||||
if (mmu_interval_read_retry(range.notifier, range.notifier_seq)) {
|
||||
mutex_unlock(®ion->mreg_mutex);
|
||||
cond_resched();
|
||||
goto again;
|
||||
}
|
||||
|
||||
for (i = 0; i < page_count; i++)
|
||||
region->mreg_pages[page_offset + i] = hmm_pfn_to_page(pfns[i]);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user