[PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global
Chunming Zhou
zhoucm1 at amd.com
Wed Jan 31 07:43:02 UTC 2018
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.He at 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;
More information about the dri-devel
mailing list