Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Do not mis-classify clean objects as purgeable

Whilst cleaning up the patches for submission, I mis-classified non-dirty
objects as purgeable. This was causing the backing pages for those
objects to be evicted under memory-pressure, discarding valid and
unreplaceable texture data.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

+26 -29
+26 -29
drivers/gpu/drm/i915/i915_gem.c
··· 1530 1530 obj_priv->last_rendering_seqno = 0; 1531 1531 } 1532 1532 1533 + /* Immediately discard the backing storage */ 1534 + static void 1535 + i915_gem_object_truncate(struct drm_gem_object *obj) 1536 + { 1537 + struct inode *inode; 1538 + 1539 + inode = obj->filp->f_path.dentry->d_inode; 1540 + if (inode->i_op->truncate) 1541 + inode->i_op->truncate (inode); 1542 + } 1543 + 1544 + static inline int 1545 + i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv) 1546 + { 1547 + return obj_priv->madv == I915_MADV_DONTNEED; 1548 + } 1549 + 1533 1550 static void 1534 1551 i915_gem_object_move_to_inactive(struct drm_gem_object *obj) 1535 1552 { ··· 2035 2018 if (!list_empty(&obj_priv->list)) 2036 2019 list_del_init(&obj_priv->list); 2037 2020 2021 + if (i915_gem_object_is_purgeable(obj_priv)) 2022 + i915_gem_object_truncate(obj); 2023 + 2038 2024 trace_i915_gem_object_unbind(obj); 2039 2025 2040 2026 return 0; 2041 - } 2042 - 2043 - static inline int 2044 - i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv) 2045 - { 2046 - return !obj_priv->dirty || obj_priv->madv == I915_MADV_DONTNEED; 2047 2027 } 2048 2028 2049 2029 static struct drm_gem_object * ··· 2055 2041 list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { 2056 2042 struct drm_gem_object *obj = obj_priv->obj; 2057 2043 if (obj->size >= min_size) { 2058 - if (i915_gem_object_is_purgeable(obj_priv) && 2044 + if ((!obj_priv->dirty || 2045 + i915_gem_object_is_purgeable(obj_priv)) && 2059 2046 (!best || obj->size < best->size)) { 2060 2047 best = obj; 2061 2048 if (best->size == min_size) ··· 4823 4808 mutex_unlock(&dev->struct_mutex); 4824 4809 } 4825 4810 4826 - /* Immediately discard the backing storage */ 4827 - static void 4828 - i915_gem_object_truncate(struct drm_gem_object *obj) 4829 - { 4830 - struct inode *inode; 4831 - 4832 - inode = obj->filp->f_path.dentry->d_inode; 4833 - 4834 - mutex_lock(&inode->i_mutex); 4835 - truncate_inode_pages(inode->i_mapping, 0); 4836 - mutex_unlock(&inode->i_mutex); 4837 - } 4838 - 4839 4811 static int 4840 4812 i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) 4841 4813 { ··· 4868 4866 &dev_priv->mm.inactive_list, 4869 4867 list) { 4870 4868 if (i915_gem_object_is_purgeable(obj_priv)) { 4871 - struct drm_gem_object *obj = obj_priv->obj; 4872 - i915_gem_object_unbind(obj); 4873 - i915_gem_object_truncate(obj); 4874 - 4869 + i915_gem_object_unbind(obj_priv->obj); 4875 4870 if (--nr_to_scan <= 0) 4876 4871 break; 4877 4872 } ··· 4876 4877 4877 4878 spin_lock(&shrink_list_lock); 4878 4879 mutex_unlock(&dev->struct_mutex); 4880 + 4881 + would_deadlock = 0; 4879 4882 4880 4883 if (nr_to_scan <= 0) 4881 4884 break; ··· 4897 4896 &dev_priv->mm.inactive_list, 4898 4897 list) { 4899 4898 if (nr_to_scan > 0) { 4900 - struct drm_gem_object *obj = obj_priv->obj; 4901 - i915_gem_object_unbind(obj); 4902 - if (i915_gem_object_is_purgeable(obj_priv)) 4903 - i915_gem_object_truncate(obj); 4904 - 4899 + i915_gem_object_unbind(obj_priv->obj); 4905 4900 nr_to_scan--; 4906 4901 } else 4907 4902 cnt++;