@@ -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;
@@ -82,6 +82,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;
};
@@ -6289,6 +6290,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;
@@ -6810,6 +6829,7 @@ static int i915_gem_object_pid_order(int id, void *ptr, void *data)
&sorted_pid_stats, head) {
struct task_struct *task = get_pid_task(pid_entry->tgid,
PIDTYPE_PID);
+ struct drm_i915_gem_client_pid *client_pid;
err_printf(m,
"%5d %6d %6d %6d %9d %8d %14zdK %14zdK %14zdK %14zdK %s",
pid_entry->pid_num,
@@ -6829,6 +6849,16 @@ static int i915_gem_object_pid_order(int id, void *ptr, void *data)
else
err_puts(m, "\n");
+ list_for_each_entry(client_pid,
+ &dev_priv->mm.gem_client_pids, head) {
+ if (client_pid->tgid == pid_entry->pid_num) {
+ pid_entry->attr_priv =
+ client_pid->obj_attr.private;
+ i915_update_task_mm_stats(pid_entry);
+ break;
+ }
+ }
+
total_shared_prop_space +=
pid_entry->stats.phys_space_shared_proportion/1024;
total_priv_space +=
@@ -6872,10 +6902,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;
@@ -6910,6 +6942,14 @@ static int i915_gem_object_pid_order(int id, void *ptr, void *data)
break;
}
+ 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;
+ i915_update_task_mm_stats(&pid_entry);
+ break;
+ }
+ }
+
/* Reset the bytes counter to buffer beginning */
bytes_copy = m->bytes;
m->bytes = 0;
@@ -6947,15 +6987,8 @@ int i915_get_drm_clients_info(struct drm_i915_error_state_buf *m,
* XXX: drm_global_mutex is undefined currently
*/
/* mutex_lock(&drm_global_mutex); */
- ret = i915_mutex_lock_interruptible(dev);
- if (ret) {
- /* mutex_unlock(&drm_global_mutex); */
- return ret;
- }
-
ret = __i915_get_drm_clients_info(m, dev);
- mutex_unlock(&dev->struct_mutex);
/* mutex_unlock(&drm_global_mutex); */
return ret;
@@ -304,6 +304,22 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
return freed;
}
+static void i915_gem_update_gfx_stats(struct drm_device *dev)
+{
+ struct drm_i915_private *i915 = to_i915(dev);
+ struct drm_i915_error_state_buf error_str;
+ bool unlock;
+
+ if (!shrinker_lock(i915, &unlock))
+ return;
+
+ error_str.bytes = 0;
+ error_str.size = 0;
+ error_str.err = -ENOSPC;
+ i915_get_drm_clients_info(&error_str, dev);
+ shrinker_unlock(i915, unlock);
+}
+
static unsigned long
i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
{
@@ -341,6 +357,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;
}
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/stat.h>
#include <linux/sysfs.h>
+#include <linux/sched/mm.h>
#include "intel_drv.h"
#include "i915_drv.h"
@@ -570,7 +571,13 @@ static ssize_t i915_gem_clients_state_read(struct file *filp,
if (ret)
return ret;
+ ret = i915_mutex_lock_interruptible(dev);
+ if (ret)
+ goto out;
+
ret = i915_get_drm_clients_info(&error_str, dev);
+
+ mutex_unlock(&dev->struct_mutex);
if (ret)
goto out;
@@ -585,12 +592,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,
@@ -727,6 +728,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(¤t->mm->mm_count);
attr_priv->tgid = tgid;
obj_attr->private = attr_priv;
@@ -761,6 +765,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);