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

Praveen Paneri praveen.paneri at intel.com
Wed Mar 21 20:05:03 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>
Signed-off-by: Praveen Paneri <praveen.paneri at intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h          |  8 ++++++++
 drivers/gpu/drm/i915/i915_gem.c          | 32 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_shrinker.c | 16 ++++++++++++++++
 drivers/gpu/drm/i915/i915_sysfs.c        | 16 ++++++++++------
 4 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c9462f7..ed343a8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -316,6 +316,14 @@ struct i915_hotplug {
 struct i915_mm_struct;
 struct i915_mmu_object;
 
+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;
 	struct drm_file *file;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0109e65..7795260 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -86,6 +86,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;
 };
 
@@ -6293,6 +6294,24 @@ static int i915_get_pid_cmdline(struct task_struct *task, char *buffer)
 	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;
+}
+
 static int i915_gem_obj_insert_pid(struct drm_i915_gem_object *obj)
 {
 	int found = 0;
@@ -6833,6 +6852,8 @@ static int i915_gem_object_pid_order(int id, void *ptr, void *data)
 		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 +=
@@ -6876,10 +6897,12 @@ static int i915_gem_object_pid_order(int id, void *ptr, void *data)
 __i915_gem_get_obj_info(struct drm_i915_error_state_buf *m,
 			struct drm_device *dev, struct pid *tgid)
 {
+	struct drm_i915_private *i915 = to_i915(dev);
 	struct drm_file *file;
 	int bytes_copy, ret = 0;
 	struct pid_stat_entry pid_entry;
 	struct name_entry *entry, *next;
+	struct drm_i915_gem_client_pid *client_pid;
 
 	pid_entry.stats.phys_space_shared_proportion = 0;
 	pid_entry.stats.phys_space_allocated_priv = 0;
@@ -6899,6 +6922,13 @@ static int i915_gem_object_pid_order(int id, void *ptr, void *data)
 
 	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");
+	list_for_each_entry(client_pid, &i915->mm.gem_client_pids, head) {
+		if (client_pid->tgid == pid_entry.pid_num) {
+		
+		pid_entry.attr_priv = client_pid->obj_attr.private;
+		break;
+		}
+	}
 
 	list_for_each_entry(file, &dev->filelist, lhead) {
 		struct get_obj_stats_buf obj_stat_buf;
@@ -6914,6 +6944,8 @@ static int i915_gem_object_pid_order(int id, void *ptr, void *data)
 			break;
 	}
 
+	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 5757fb7..a29c32e 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -304,6 +304,20 @@ 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_trylock(&dev->struct_mutex)
+		/* && !mutex_trylock(&drm_global_mutex)*/ )
+	{
+		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 +355,8 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
 			    128ul /* default SHRINK_BATCH */);
 	}
 
+	i915_gem_update_gfx_stats(&i915->drm);
+
 	return count;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index a4089e0..be55f9e 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -33,6 +33,7 @@
 #include "i915_drv.h"
 #include "../drm_internal.h"
 #include <linux/firmware.h>
+#include <linux/sched/mm.h>
 #include "i915_pvinfo.h"
 static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
 {
@@ -587,12 +588,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,
@@ -729,6 +724,9 @@ int i915_gem_create_sysfs_file_entry(struct drm_device *dev,
 	obj_attr->size = 0;
 	obj_attr->read = i915_gem_read_objects;
 
+	attr_priv->rss_size = 0;
+	attr_priv->mm = current->mm;
+	atomic_inc(&current->mm->mm_count);
 	attr_priv->tgid = tgid;
 	obj_attr->private = attr_priv;
 
@@ -763,6 +761,12 @@ void i915_gem_remove_sysfs_file_entry(struct drm_device *dev,
 
 	attr_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, obj_attr);
 
 	i915_error_state_buf_release(&attr_priv->buf);
-- 
1.9.1



More information about the Intel-gfx-trybot mailing list