drm/ttm: Avoid invoking the OOM killer when reading back swapped content

In situations where the system is very short on RAM, the shmem
readback from swap-space may invoke the OOM killer.

However, since this might be a recoverable situation where the caller
is indicating this by setting
struct ttm_operation_ctx::gfp_retry_mayfail to true, adjust the gfp
value used by the allocation accordingly.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Maarten Lankhorst <dev@lankhorst.se>
Acked-by: Christian König <christian.koening@amd.com>
Link: https://patch.msgid.link/20260317141856.237876-3-thomas.hellstrom@linux.intel.com
This commit is contained in:
Thomas Hellström 2026-03-17 15:18:55 +01:00
commit c6135f67aa
3 changed files with 9 additions and 4 deletions

View file

@ -44,18 +44,20 @@ void ttm_backup_drop(struct file *backup, pgoff_t handle)
* @dst: The struct page to copy into.
* @handle: The handle returned when the page was backed up.
* @intr: Try to perform waits interruptible or at least killable.
* @additional_gfp: GFP mask to add to the default GFP mask if any.
*
* Return: 0 on success, Negative error code on failure, notably
* -EINTR if @intr was set to true and a signal is pending.
*/
int ttm_backup_copy_page(struct file *backup, struct page *dst,
pgoff_t handle, bool intr)
pgoff_t handle, bool intr, gfp_t additional_gfp)
{
struct address_space *mapping = backup->f_mapping;
struct folio *from_folio;
pgoff_t idx = ttm_backup_handle_to_shmem_idx(handle);
from_folio = shmem_read_folio(mapping, idx);
from_folio = shmem_read_folio_gfp(mapping, idx, mapping_gfp_mask(mapping)
| additional_gfp);
if (IS_ERR(from_folio))
return PTR_ERR(from_folio);

View file

@ -530,6 +530,8 @@ static int ttm_pool_restore_commit(struct ttm_pool_tt_restore *restore,
p = first_page[i];
if (ttm_backup_page_ptr_is_handle(p)) {
unsigned long handle = ttm_backup_page_ptr_to_handle(p);
gfp_t additional_gfp = ctx->gfp_retry_mayfail ?
__GFP_RETRY_MAYFAIL | __GFP_NOWARN : 0;
if (IS_ENABLED(CONFIG_FAULT_INJECTION) && ctx->interruptible &&
should_fail(&backup_fault_inject, 1)) {
@ -543,7 +545,8 @@ static int ttm_pool_restore_commit(struct ttm_pool_tt_restore *restore,
}
ret = ttm_backup_copy_page(backup, restore->alloced_page + i,
handle, ctx->interruptible);
handle, ctx->interruptible,
additional_gfp);
if (ret)
break;

View file

@ -56,7 +56,7 @@ ttm_backup_page_ptr_to_handle(const struct page *page)
void ttm_backup_drop(struct file *backup, pgoff_t handle);
int ttm_backup_copy_page(struct file *backup, struct page *dst,
pgoff_t handle, bool intr);
pgoff_t handle, bool intr, gfp_t additional_gfp);
s64
ttm_backup_backup_page(struct file *backup, struct page *page,