[PATCH 2/5] drm/ttm: add swap_glob_mem in ttm_mem_global

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 space is full, all swapped ttm pages would stay in
system memory which can't be flushed into swap space.

Signed-off-by: Roger He <Hongbo.He@xxxxxxx>
---
 drivers/gpu/drm/ttm/ttm_memory.c | 12 ++++++++----
 drivers/gpu/drm/ttm/ttm_tt.c     | 13 +++++++++++--
 include/drm/ttm/ttm_memory.h     |  2 ++
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
index b48931d..598b14b 100644
--- a/drivers/gpu/drm/ttm/ttm_memory.c
+++ b/drivers/gpu/drm/ttm/ttm_memory.c
@@ -197,7 +197,6 @@ static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob,
 			target = zone->max_mem;
 
 		target = (extra > target) ? 0ULL : target;
-
 		if (zone->used_mem > target)
 			return true;
 	}
@@ -375,6 +374,7 @@ int ttm_mem_global_init(struct ttm_mem_global *glob)
 	}
 	/* set it as 1/2 * swap free space we can get at that time */
 	glob->max_swap_mem = get_nr_swap_pages() << (PAGE_SHIFT - 1);
+	atomic64_set(&glob->swap_glob_mem, 0);
 	si_meminfo(&si);
 	ret = ttm_mem_init_kernel_zone(glob, &si);
 	if (unlikely(ret != 0))
@@ -475,10 +475,12 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
 				  uint64_t amount, bool reserve)
 {
 	uint64_t free_swap_mem = get_nr_swap_pages() << (PAGE_SHIFT - 1);
-	uint64_t limit;
+	uint64_t swap_glob_mem, 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);
 
 	spin_lock(&glob->lock);
 	/* adjust the max_swap_mem to cover the new inserted swap space */
@@ -493,7 +495,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;
+		limit += glob->max_swap_mem;
+		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 95a77da..5d441e0 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -183,8 +183,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);
@@ -322,8 +325,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;
 
@@ -383,6 +389,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 ad5a557..6282b50 100644
--- a/include/drm/ttm/ttm_memory.h
+++ b/include/drm/ttm/ttm_memory.h
@@ -50,6 +50,7 @@
  * @lock: Lock to protect the @shrink - and the memory accounting members,
  * that is, essentially the whole structure with some exceptions.
  * @max_swap_mem: upper limit of swap space TTM can use
+ * @swap_glob_mem: total size of ttm pages which have 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.
@@ -69,6 +70,7 @@ struct ttm_mem_global {
 	struct work_struct work;
 	spinlock_t lock;
 	uint64_t max_swap_mem;
+	atomic64_t swap_glob_mem;
 	struct ttm_mem_zone *zones[TTM_MEM_MAX_ZONES];
 	unsigned int num_zones;
 	struct ttm_mem_zone *zone_kernel;
-- 
2.7.4

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




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux