]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/ttm: Avoid invoking the OOM killer when reading back swapped content
authorThomas Hellström <thomas.hellstrom@linux.intel.com>
Tue, 17 Mar 2026 14:18:55 +0000 (15:18 +0100)
committerThomas Hellström <thomas.hellstrom@linux.intel.com>
Fri, 20 Mar 2026 09:38:10 +0000 (10:38 +0100)
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
drivers/gpu/drm/ttm/ttm_backup.c
drivers/gpu/drm/ttm/ttm_pool.c
include/drm/ttm/ttm_backup.h

index 6bd4c123d94cdc7235a180d297577ede9406244b..81df4cb5606b48d3e1c44140d850b5e1142cd780 100644 (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);
 
index 8fa9e09f6ee593b414bf1b3e6471e27acb0dfdad..aa41099c5ecfc7843cbde7943825bfdde08c52d4 100644 (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;
 
index c33cba111171fba90518edd04d2f24e1e35c2e3a..29b9c855af779097122ff7f4768f1b8f9ec97fca 100644 (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,