[PATCH 5/5] drm/i915: Update process mm stats for Gen GFX memory

Nidhi Gupta nidhi1.gupta at intel.com
Tue Feb 6 13:20:22 UTC 2018


From: Sourab Gupta <sourab.gupta at intel.com>

The GFX memory consumed by a process is not accounted by kernel. This
leads to a scenario wherein the low memory killer is not able to
correctly identify the best process to be killed during OOM scenarios.
This case particularly manifests when an application has a large GFX
memory footprint but has a significantly smaller system mem consumption.
Low mem killer in such a case will not be able to identify this culprit
process, and lot of innocent process will be killed without freeing much
memory.

This patch utilizes the memtracker functions to add the accounting for
the processes' GFX memory consumption.
The internal kernel counters updated thus don't affect the output of
procrank, meminfo or smaps.
The kernel counters updated though would lead to better approximation
of process' memory consumption, leading to better low mem killer behavior.

The memtracker functions are called at asynchronous points during
shrinker invocation.
Thus, in times of memory stress, we ensure to update the processes' GFX
mem statistics, therefore leading to better low mem killer behavior

Signed-off-by: Sourab Gupta <sourab.gupta at intel.com>
Signed-off-by: Akash Goel <akash.goel at intel.com>
Signed-off-by: Nidhi Gupta <nidhi1.gupta at intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h          | 28 +++++++++++++++++++---------
 drivers/gpu/drm/i915/i915_gem.c          | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_shrinker.c | 19 +++++++++++++++++++
 drivers/gpu/drm/i915/i915_sysfs.c        | 25 +++++++++++++++++++------
 4 files changed, 82 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9a6b45d..a0a7bc7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -314,6 +314,24 @@ struct i915_hotplug {
 struct drm_i915_private;
 struct i915_mm_struct;
 struct i915_mmu_object;
+struct drm_i915_error_state_buf {
+	struct drm_i915_private *i915;
+	unsigned bytes;
+	unsigned size;
+	int err;
+	u8 *buf;
+	loff_t start;
+	loff_t pos;
+};
+
+
+struct i915_gem_file_attr_priv {
+	char tgid_str[16];
+	struct pid *tgid;
+	size_t rss_size;
+	struct mm_struct *mm;
+	struct drm_i915_error_state_buf buf;
+};
 
 struct drm_i915_file_private {
 	struct drm_i915_private *dev_priv;
@@ -1140,15 +1158,7 @@ struct i915_gem_mm {
 	size_t phys_mem_total;
 };
 
-struct drm_i915_error_state_buf {
-	struct drm_i915_private *i915;
-	unsigned bytes;
-	unsigned size;
-	int err;
-	u8 *buf;
-	loff_t start;
-	loff_t pos;
-};
+
 
 #define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index e8cf56d..dfe9074 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -87,6 +87,7 @@ struct pid_stat_entry {
 	struct drm_open_hash namelist;
 	struct per_file_obj_mem_info stats;
 	struct pid *tgid;
+	struct i915_gem_file_attr_priv *attr_priv;
 	int pid_num;
 };
 
@@ -6196,6 +6197,24 @@ static unsigned long i915_obj_get_shmem_pages_alloced
 	return 0;
 }
 
+static void i915_update_task_mm_stats(struct pid_stat_entry *pid_entry)
+{
+	long new_size, old_size;
+
+	new_size =
+		(pid_entry->stats.phys_space_shared_proportion +
+		 pid_entry->stats.phys_space_allocated_priv) / PAGE_SIZE;
+
+	old_size = pid_entry->attr_priv->rss_size;
+
+	/* Update task mm stats */
+	if (pid_entry->attr_priv->mm)
+		add_mm_counter(pid_entry->attr_priv->mm, MM_FILEPAGES,
+		new_size - old_size);
+
+	pid_entry->attr_priv->rss_size = new_size;
+}
+
 int i915_gem_obj_insert_pid(struct drm_i915_gem_object *obj)
 {
 	int found = 0;
@@ -6738,6 +6757,7 @@ __i915_get_drm_clients_info(struct drm_i915_error_state_buf *m,
 			list_add_tail(&new_entry->head, &per_pid_stats);
 			INIT_LIST_HEAD(&new_entry->namefree);
 			new_entry->stats.process_name = file_priv->process_name;
+			new_entry->attr_priv = file_priv->obj_attr->private;
 			pid_entry = new_entry;
 		}
 
@@ -6803,6 +6823,8 @@ __i915_get_drm_clients_info(struct drm_i915_error_state_buf *m,
 		else
 			err_puts(m, "\n");
 
+		i915_update_task_mm_stats(pid_entry);
+
 		total_shared_prop_space +=
 			pid_entry->stats.phys_space_shared_proportion/1024;
 		total_priv_space +=
@@ -6877,6 +6899,7 @@ __i915_gem_get_obj_info(struct drm_i915_error_state_buf *m,
 		if (file_priv->tgid != tgid)
 			continue;
 
+		pid_entry.attr_priv = file_priv->obj_attr->private;
 		file_priv_reqd = file_priv;
 		err_puts(m,
 			"\n Obj Identifier   Obj-Size Resident-Size Pin Tiling Dirty Shared Vmap Stolen Mappable  AllocState Global/PP  GttOffset (PID: handle count: user virt addrs)\n");
@@ -6891,6 +6914,8 @@ __i915_gem_get_obj_info(struct drm_i915_error_state_buf *m,
 	if (file_priv_reqd) {
 		int space_remaining;
 
+		i915_update_task_mm_stats(&pid_entry);
+
 		/* Reset the bytes counter to buffer beginning */
 		bytes_copy = m->bytes;
 		m->bytes = 0;
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 0e158f9..7e82ff0 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -304,6 +304,21 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
 	return freed;
 }
 
+/*
+*static void i915_gem_update_gfx_stats(struct drm_device *dev)
+*{
+*	if (!mutex_is_locked_by(&dev->struct_mutex, current) &&
+*		!mutex_is_locked_by(&drm_global_mutex, current)) {
+*		struct drm_i915_error_state_buf error_str;
+*
+*		error_str.bytes = 0;
+*		error_str.size = 0;
+*		error_str.err = -ENOSPC;
+*		i915_get_drm_clients_info(&error_str, dev);
+*	}
+*}
+*/
+
 static unsigned long
 i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
 {
@@ -341,6 +356,10 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
 			    128ul /* default SHRINK_BATCH */);
 	}
 
+	/*
+	*i915_gem_update_gfx_stats(dev);
+	*/
+
 	return count;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index f04ab69..0a3dc34 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -34,6 +34,16 @@
 #include "../drm_internal.h"
 #include <linux/firmware.h>
 #include "i915_pvinfo.h"
+#include "i915_pvinfo.h"
+#include <drm/drmP.h>
+#include <drm/i915_drm.h>
+#include "i915_trace.h"
+#include <linux/mmu_context.h>
+#include <linux/mmu_notifier.h>
+#include <linux/mempolicy.h>
+#include <linux/swap.h>
+#include <linux/sched/mm.h>
+
 static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
 {
 	struct drm_minor *minor = dev_get_drvdata(kdev);
@@ -581,12 +591,6 @@ static ssize_t i915_gem_clients_state_read(struct file *filp,
 #define GEM_OBJ_STAT_BUF_SIZE (4*1024) /* 4KB */
 #define GEM_OBJ_STAT_BUF_SIZE_MAX (1024*1024) /* 1MB */
 
-struct i915_gem_file_attr_priv {
-	char tgid_str[16];
-	struct pid *tgid;
-	struct drm_i915_error_state_buf buf;
-};
-
 static ssize_t i915_gem_read_objects(struct file *filp,
 				struct kobject *memtrack_kobj,
 				struct bin_attribute *attr,
@@ -751,6 +755,9 @@ int i915_gem_create_sysfs_file_entry(struct drm_device *dev,
 	obj_attr->read = i915_gem_read_objects;
 
 	attr_priv->tgid = file_priv->tgid;
+	attr_priv->rss_size = 0;
+	attr_priv->mm = current->mm;
+	atomic_inc(&current->mm->mm_count);
 	obj_attr->private = attr_priv;
 
 	ret = sysfs_create_bin_file(&dev_priv->memtrack_kobj,
@@ -807,6 +814,12 @@ void i915_gem_remove_sysfs_file_entry(struct drm_device *dev,
 			return;
 		attr_priv = file_priv->obj_attr->private;
 
+		if (attr_priv->mm) {
+			add_mm_counter(attr_priv->mm, MM_FILEPAGES,
+						-attr_priv->rss_size);
+			mmdrop(attr_priv->mm);
+		}
+
 		sysfs_remove_bin_file(&dev_priv->memtrack_kobj,
 				file_priv->obj_attr);
 
-- 
2.7.4



More information about the Intel-gfx-trybot mailing list