On 2018年01月29日 16:31, Roger He wrote:
separate swapped memory account from zone->used_mem because swapped
ttm pages can be flushed into SWAP disk/file under high memory pressure.

add check conditon in ttm_mem_global_reserve to prevent triggering OOM.
because if SWAP disk/file is full, all swapped ttm page would stay in
system memory which can't be flushed into disk/file. At this time, any
memory request will trigger OOM killer.

v2: always get total system swap size rather than getting it once
at module init time

Signed-off-by: Roger He <hongbo...@amd.com>
---
  drivers/gpu/drm/ttm/ttm_memory.c | 24 ++++++++++++++++--------
  drivers/gpu/drm/ttm/ttm_tt.c     | 13 +++++++++++--
  include/drm/ttm/ttm_memory.h     |  2 ++
  3 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
index aa0c381..06024ba 100644
--- a/drivers/gpu/drm/ttm/ttm_memory.c
+++ b/drivers/gpu/drm/ttm/ttm_memory.c
@@ -36,6 +36,7 @@
  #include <linux/mm.h>
  #include <linux/module.h>
  #include <linux/slab.h>
+#include <linux/swap.h>
#define TTM_MEMORY_ALLOC_RETRIES 4 @@ -183,20 +184,20 @@ static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob,
  {
        unsigned int i;
        struct ttm_mem_zone *zone;
-       uint64_t target;
+       uint64_t target, limit;
Don't need limit variable.

for (i = 0; i < glob->num_zones; ++i) {
                zone = glob->zones[i];
+ limit = (capable(CAP_SYS_ADMIN)) ?
+                               zone->emer_mem : zone->max_mem;
directly target = ...
+
                if (from_wq)
                        target = zone->swap_limit;
-               else if (capable(CAP_SYS_ADMIN))
-                       target = zone->emer_mem;
                else
-                       target = zone->max_mem;
+                       target = limit;
Don't need `else` case.

target = (extra > target) ? 0ULL : target;
-
                if (zone->used_mem > target)
                        return true;
        }
@@ -373,6 +374,7 @@ int ttm_mem_global_init(struct ttm_mem_global *glob)
                return ret;
        }
+ atomic64_set(&glob->swap_glob_mem, 0);
        si_meminfo(&si);
ret = ttm_mem_init_kernel_zone(glob, &si);
@@ -473,10 +475,14 @@ static int ttm_mem_global_reserve(struct ttm_mem_global 
*glob,
                                  struct ttm_mem_zone *single_zone,
                                  uint64_t amount, bool reserve)
  {
-       uint64_t limit;
+       uint64_t swap_glob_mem, max_swap_cache;
+       uint64_t limit, total_used_mem;
+       struct ttm_mem_zone *zone;
        int ret = -ENOMEM;
        unsigned int i;
-       struct ttm_mem_zone *zone;
+
+       swap_glob_mem = atomic64_read(&glob->swap_glob_mem);
+       max_swap_cache = (get_total_swap_pages() >> 1) << PAGE_SHIFT;
spin_lock(&glob->lock);
        for (i = 0; i < glob->num_zones; ++i) {
@@ -487,7 +493,9 @@ static int ttm_mem_global_reserve(struct ttm_mem_global 
*glob,
                limit = (capable(CAP_SYS_ADMIN)) ?
                        zone->emer_mem : zone->max_mem;
- if (zone->used_mem > limit)
+               total_used_mem = zone->used_mem + swap_glob_mem;
Good catch for total used mem.

Regards,
David Zhou
+               limit += max_swap_cache;
+               if (total_used_mem > limit)
                        goto out_unlock;
        }
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 9e4d43d..395cac0 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -177,8 +177,11 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
                ttm_tt_unpopulate(ttm);
if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) &&
-           ttm->swap_storage)
+           ttm->swap_storage) {
                fput(ttm->swap_storage);
+               atomic64_sub_return(ttm->num_pages << PAGE_SHIFT,
+                                   &ttm->glob->mem_glob->swap_glob_mem);
+       }
ttm->swap_storage = NULL;
        ttm->func->destroy(ttm);
@@ -318,8 +321,11 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
                put_page(from_page);
        }
- if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP))
+       if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP)) {
                fput(swap_storage);
+               atomic64_sub_return(ttm->num_pages << PAGE_SHIFT,
+                                   &ttm->glob->mem_glob->swap_glob_mem);
+       }
        ttm->swap_storage = NULL;
        ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED;
@@ -378,6 +384,9 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
        ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
        if (persistent_swap_storage)
                ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;
+       else
+               atomic64_add_return(ttm->num_pages << PAGE_SHIFT,
+                           &ttm->glob->mem_glob->swap_glob_mem);
return 0;
  out_err:
diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h
index 8936285..a273581 100644
--- a/include/drm/ttm/ttm_memory.h
+++ b/include/drm/ttm/ttm_memory.h
@@ -49,6 +49,7 @@
   * @work: The workqueue callback for the shrink queue.
   * @lock: Lock to protect the @shrink - and the memory accounting members,
   * that is, essentially the whole structure with some exceptions.
+ * @swap_glob_mem: total size of ttm page which has been swapped out
   * @zones: Array of pointers to accounting zones.
   * @num_zones: Number of populated entries in the @zones array.
   * @zone_kernel: Pointer to the kernel zone.
@@ -67,6 +68,7 @@ struct ttm_mem_global {
        struct workqueue_struct *swap_queue;
        struct work_struct work;
        spinlock_t lock;
+       atomic64_t swap_glob_mem;
        struct ttm_mem_zone *zones[TTM_MEM_MAX_ZONES];
        unsigned int num_zones;
        struct ttm_mem_zone *zone_kernel;

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to