Re: [RFC] drm/i915: Start writeback from the shrinker

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

 



[CC linux-mm and some mm guys]

On Tue 06-06-17 10:56:34, Chris Wilson wrote:
> When we are called to relieve mempressue via the shrinker, the only way
> we can make progress is either by discarding unwanted pages (those
> objects that userspace has marked MADV_DONTNEED) or by reclaiming the
> dirty objects via swap. As we know that is the only way to make further
> progress, we can initiate the writeback as we invalidate the objects.
> This means the objects we put onto the inactive anon lru list are
> already marked for reclaim+writeback and so will trigger a wait upon the
> writeback inside direct reclaim, greatly improving the success rate of
> direct reclaim on i915 objects.
> 
> The corollary is that we may start a slow swap on opportunistic
> mempressure from the likes of the compaction + migration kthreads. This
> is limited by those threads only being allowed to shrink idle pages, but
> also that if we reactivate the page before it is swapped out by gpu
> activity, we only page the cost of repinning the page. The cost is most
> felt when an object is reused after mempressure, which hopefully
> excludes the latency sensitive tasks (as we are just extending the
> impact of swap thrashing to them).
> 
> Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Cc: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxx>
> Cc: Matthew Auld <matthew.auld@xxxxxxxxx>
> Cc: Daniel Vetter <daniel.vetter@xxxxxxxx>
> Cc: Michal Hocko <mhocko@xxxxxxxx>
> ---
>  drivers/gpu/drm/i915/i915_drv.h          |  2 +-
>  drivers/gpu/drm/i915/i915_gem.c          | 27 ++--------------
>  drivers/gpu/drm/i915/i915_gem_shrinker.c | 55 +++++++++++++++++++++++++++++++-
>  3 files changed, 57 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index c31c0cfe5c20..33ffec1e6c90 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -3321,7 +3321,7 @@ enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock */
>  
>  void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
>  				 enum i915_mm_subclass subclass);
> -void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj);
> +void __i915_gem_object_truncate(struct drm_i915_gem_object *obj);
>  
>  enum i915_map_type {
>  	I915_MAP_WB = 0,
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 845df6067e90..8cb811519db1 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2176,8 +2176,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
>  }
>  
>  /* Immediately discard the backing storage */
> -static void
> -i915_gem_object_truncate(struct drm_i915_gem_object *obj)
> +void __i915_gem_object_truncate(struct drm_i915_gem_object *obj)
>  {
>  	i915_gem_object_free_mmap_offset(obj);
>  
> @@ -2194,28 +2193,6 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)
>  	obj->mm.pages = ERR_PTR(-EFAULT);
>  }
>  
> -/* Try to discard unwanted pages */
> -void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
> -{
> -	struct address_space *mapping;
> -
> -	lockdep_assert_held(&obj->mm.lock);
> -	GEM_BUG_ON(obj->mm.pages);
> -
> -	switch (obj->mm.madv) {
> -	case I915_MADV_DONTNEED:
> -		i915_gem_object_truncate(obj);
> -	case __I915_MADV_PURGED:
> -		return;
> -	}
> -
> -	if (obj->base.filp == NULL)
> -		return;
> -
> -	mapping = obj->base.filp->f_mapping,
> -	invalidate_mapping_pages(mapping, 0, (loff_t)-1);
> -}
> -
>  static void
>  i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj,
>  			      struct sg_table *pages)
> @@ -4215,7 +4192,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
>  
>  	/* if the object is no longer attached, discard its backing storage */
>  	if (obj->mm.madv == I915_MADV_DONTNEED && !obj->mm.pages)
> -		i915_gem_object_truncate(obj);
> +		__i915_gem_object_truncate(obj);
>  
>  	args->retained = obj->mm.madv != __I915_MADV_PURGED;
>  	mutex_unlock(&obj->mm.lock);
> diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
> index 58f27369183c..026500ad6d35 100644
> --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
> +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
> @@ -122,6 +122,59 @@ static bool unsafe_drop_pages(struct drm_i915_gem_object *obj)
>  	return !READ_ONCE(obj->mm.pages);
>  }
>  
> +static void __start_writeback(struct drm_i915_gem_object *obj)
> +{
> +	struct address_space *mapping;
> +	struct writeback_control wbc = {
> +		.sync_mode = WB_SYNC_NONE,
> +		.nr_to_write = SWAP_CLUSTER_MAX,
> +		.range_start = 0,
> +		.range_end = LLONG_MAX,
> +		.for_reclaim = 1,
> +	};
> +	unsigned long i;
> +
> +	lockdep_assert_held(&obj->mm.lock);
> +	GEM_BUG_ON(obj->mm.pages);
> +
> +	switch (obj->mm.madv) {
> +	case I915_MADV_DONTNEED:
> +		__i915_gem_object_truncate(obj);
> +	case __I915_MADV_PURGED:
> +		return;
> +	}
> +
> +	if (!obj->base.filp)
> +		return;
> +
> +	/* Force any other users of this object to refault */
> +	mapping = obj->base.filp->f_mapping;
> +	unmap_mapping_range(mapping, 0, (loff_t)-1, 0);
> +
> +	/* Begin writeback on each dirty page */
> +	for (i = 0; i < obj->base.size >> PAGE_SHIFT; i++) {
> +		struct page *page;
> +
> +		page = find_lock_entry(mapping, i);
> +		if (radix_tree_exceptional_entry(page))
> +			continue;
> +
> +		if (!page_mapped(page) && clear_page_dirty_for_io(page)) {
> +			int ret;
> +
> +			SetPageReclaim(page);
> +			ret = mapping->a_ops->writepage(page, &wbc);
> +			if (!PageWriteback(page))
> +				ClearPageReclaim(page);
> +			if (!ret)
> +				goto put;
> +		}
> +		unlock_page(page);
> +put:
> +		put_page(page);
> +	}
> +}
> +
>  /**
>   * i915_gem_shrink - Shrink buffer object caches
>   * @dev_priv: i915 device
> @@ -234,7 +287,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
>  				mutex_lock_nested(&obj->mm.lock,
>  						  I915_MM_SHRINKER);
>  				if (!obj->mm.pages) {
> -					__i915_gem_object_invalidate(obj);
> +					__start_writeback(obj);
>  					list_del_init(&obj->global_link);
>  					count += obj->base.size >> PAGE_SHIFT;
>  				}
> -- 
> 2.11.0
> 

-- 
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxx.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]
  Powered by Linux