From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Intel-gfx@lists.freedesktop.org
Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org,
"Tejun Heo" <tj@kernel.org>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Zefan Li" <lizefan.x@bytedance.com>,
"Dave Airlie" <airlied@redhat.com>,
"Daniel Vetter" <daniel.vetter@ffwll.ch>,
"Rob Clark" <robdclark@chromium.org>,
"Stéphane Marchesin" <marcheu@chromium.org>,
"T . J . Mercier" <tjmercier@google.com>,
Kenny.Ho@amd.com, "Christian König" <christian.koenig@amd.com>,
"Brian Welty" <brian.welty@intel.com>,
"Tvrtko Ursulin" <tvrtko.ursulin@intel.com>
Subject: [RFC 05/13] drm/cgroup: Track clients per owning process
Date: Wed, 9 Nov 2022 16:11:33 +0000 [thread overview]
Message-ID: <20221109161141.2987173-6-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20221109161141.2987173-1-tvrtko.ursulin@linux.intel.com>
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
To enable propagation of settings from the cgroup drm controller to drm we
need to start tracking which processes own which drm clients.
Implement that by tracking the struct pid pointer of the owning process in
a new XArray, pointing to a structure containing a list of associated
struct drm_file pointers.
Clients are added and removed under the filelist mutex and RCU list
operations are used below it to allow for lockless lookup.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
drivers/gpu/drm/Makefile | 1 +
drivers/gpu/drm/drm_cgroup.c | 123 +++++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_file.c | 21 ++++--
include/drm/drm_clients.h | 44 +++++++++++++
include/drm/drm_file.h | 4 ++
5 files changed, 189 insertions(+), 4 deletions(-)
create mode 100644 drivers/gpu/drm/drm_cgroup.c
create mode 100644 include/drm/drm_clients.h
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index c44a54cadb61..4495dda2a720 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -59,6 +59,7 @@ drm-$(CONFIG_DRM_LEGACY) += \
drm_scatter.o \
drm_vm.o
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
+drm-$(CONFIG_CGROUP_DRM) += drm_cgroup.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
drm-$(CONFIG_OF) += drm_of.o
diff --git a/drivers/gpu/drm/drm_cgroup.c b/drivers/gpu/drm/drm_cgroup.c
new file mode 100644
index 000000000000..56aa8303974a
--- /dev/null
+++ b/drivers/gpu/drm/drm_cgroup.c
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#include <drm/drm_drv.h>
+#include <drm/drm_clients.h>
+
+static DEFINE_XARRAY(drm_pid_clients);
+
+static void
+__del_clients(struct drm_pid_clients *clients,
+ struct drm_file *file_priv,
+ unsigned long pid)
+{
+ list_del_rcu(&file_priv->clink);
+ if (atomic_dec_and_test(&clients->num)) {
+ xa_erase(&drm_pid_clients, pid);
+ kfree_rcu(clients, rcu);
+ }
+}
+
+void drm_clients_close(struct drm_file *file_priv)
+{
+ struct drm_device *dev = file_priv->minor->dev;
+ struct drm_pid_clients *clients;
+ struct pid *pid;
+
+ lockdep_assert_held(&dev->filelist_mutex);
+
+ pid = rcu_access_pointer(file_priv->pid);
+ clients = xa_load(&drm_pid_clients, (unsigned long)pid);
+ if (WARN_ON_ONCE(!clients))
+ return;
+
+ __del_clients(clients, file_priv, (unsigned long)pid);
+}
+
+static struct drm_pid_clients *__alloc_clients(void)
+{
+ struct drm_pid_clients *clients;
+
+ clients = kmalloc(sizeof(*clients), GFP_KERNEL);
+ if (clients) {
+ atomic_set(&clients->num, 0);
+ INIT_LIST_HEAD(&clients->file_list);
+ init_rcu_head(&clients->rcu);
+ }
+
+ return clients;
+}
+
+int drm_clients_open(struct drm_file *file_priv)
+{
+ struct drm_device *dev = file_priv->minor->dev;
+ struct drm_pid_clients *clients;
+ bool new_client = false;
+ unsigned long pid;
+
+ lockdep_assert_held(&dev->filelist_mutex);
+
+ pid = (unsigned long)rcu_access_pointer(file_priv->pid);
+ clients = xa_load(&drm_pid_clients, pid);
+ if (!clients) {
+ clients = __alloc_clients();
+ if (!clients)
+ return -ENOMEM;
+ new_client = true;
+ }
+ atomic_inc(&clients->num);
+ list_add_tail_rcu(&file_priv->clink, &clients->file_list);
+ if (new_client) {
+ void *xret;
+
+ xret = xa_store(&drm_pid_clients, pid, clients, GFP_KERNEL);
+ if (xa_err(xret)) {
+ list_del_init(&file_priv->clink);
+ kfree(clients);
+ return PTR_ERR(clients);
+ }
+ }
+
+ return 0;
+}
+
+void
+drm_clients_migrate(struct drm_file *file_priv,
+ unsigned long old,
+ unsigned long new)
+{
+ struct drm_device *dev = file_priv->minor->dev;
+ struct drm_pid_clients *existing_clients;
+ struct drm_pid_clients *clients;
+
+ lockdep_assert_held(&dev->filelist_mutex);
+
+ existing_clients = xa_load(&drm_pid_clients, new);
+ clients = xa_load(&drm_pid_clients, old);
+
+ if (WARN_ON_ONCE(!clients))
+ return;
+ else if (WARN_ON_ONCE(clients == existing_clients))
+ return;
+
+ __del_clients(clients, file_priv, old);
+
+ if (!existing_clients) {
+ void *xret;
+
+ clients = __alloc_clients();
+ if (WARN_ON(!clients))
+ return;
+
+ xret = xa_store(&drm_pid_clients, new, clients, GFP_KERNEL);
+ if (WARN_ON(xa_err(xret)))
+ return;
+ } else {
+ clients = existing_clients;
+ }
+
+ atomic_inc(&clients->num);
+ list_add_tail_rcu(&file_priv->clink, &clients->file_list);
+}
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index 4f5cff5c0bea..16ca5b88f414 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -40,6 +40,7 @@
#include <linux/slab.h>
#include <drm/drm_client.h>
+#include <drm/drm_clients.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_print.h>
@@ -298,6 +299,7 @@ static void drm_close_helper(struct file *filp)
mutex_lock(&dev->filelist_mutex);
list_del(&file_priv->lhead);
+ drm_clients_close(file_priv);
mutex_unlock(&dev->filelist_mutex);
drm_file_free(file_priv);
@@ -349,10 +351,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
if (drm_is_primary_client(priv)) {
ret = drm_master_open(priv);
- if (ret) {
- drm_file_free(priv);
- return ret;
- }
+ if (ret)
+ goto err_free;
}
filp->private_data = priv;
@@ -360,6 +360,9 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
priv->filp = filp;
mutex_lock(&dev->filelist_mutex);
+ ret = drm_clients_open(priv);
+ if (ret)
+ goto err_unlock;
list_add(&priv->lhead, &dev->filelist);
mutex_unlock(&dev->filelist_mutex);
@@ -387,6 +390,13 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
#endif
return 0;
+
+err_unlock:
+ mutex_unlock(&dev->filelist_mutex);
+err_free:
+ drm_file_free(priv);
+
+ return ret;
}
/**
@@ -523,6 +533,9 @@ void drm_file_update_pid(struct drm_file *filp)
dev = filp->minor->dev;
mutex_lock(&dev->filelist_mutex);
old = rcu_replace_pointer(filp->pid, pid, 1);
+ if (pid != old)
+ drm_clients_migrate(filp,
+ (unsigned long)old, (unsigned long)pid);
mutex_unlock(&dev->filelist_mutex);
if (pid != old) {
diff --git a/include/drm/drm_clients.h b/include/drm/drm_clients.h
new file mode 100644
index 000000000000..fbb8cffdf7a9
--- /dev/null
+++ b/include/drm/drm_clients.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef _DRM_CLIENTS_H_
+#define _DRM_CLIENTS_H_
+
+#include <drm/drm_file.h>
+
+struct drm_pid_clients {
+ atomic_t num;
+ struct list_head file_list;
+ struct rcu_head rcu;
+};
+
+#if IS_ENABLED(CONFIG_CGROUP_DRM)
+void drm_clients_close(struct drm_file *file_priv);
+int drm_clients_open(struct drm_file *file_priv);
+
+void
+drm_clients_migrate(struct drm_file *file_priv,
+ unsigned long old,
+ unsigned long new);
+#else
+static inline void drm_clients_close(struct drm_file *file_priv)
+{
+}
+
+static inline int drm_clients_open(struct drm_file *file_priv)
+{
+ return 0;
+}
+
+static void
+drm_clients_migrate(struct drm_file *file_priv,
+ unsigned long old,
+ unsigned long new)
+{
+
+}
+#endif
+
+#endif
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index b8be69b551af..ad20aaad40f5 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -275,6 +275,10 @@ struct drm_file {
/** @minor: &struct drm_minor for this file. */
struct drm_minor *minor;
+#if IS_ENABLED(CONFIG_CGROUP_DRM)
+ struct list_head clink;
+#endif
+
/**
* @object_idr:
*
--
2.34.1
next prev parent reply other threads:[~2022-11-09 16:12 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-09 16:11 [RFC v2 00/13] DRM scheduling cgroup controller Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 01/13] drm: Replace DRM_DEBUG with drm_dbg_core in file and ioctl handling Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 02/13] drm: Track clients by tgid and not tid Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 03/13] drm: Update file owner during use Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 04/13] cgroup: Add the DRM cgroup controller Tvrtko Ursulin
2022-11-09 16:11 ` Tvrtko Ursulin [this message]
2022-11-09 16:11 ` [RFC 06/13] drm/cgroup: Allow safe external access to file_priv Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 07/13] drm/cgroup: Add ability to query drm cgroup GPU time Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 08/13] drm/cgroup: Add over budget signalling callback Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 09/13] drm/cgroup: Only track clients which are providing drm_cgroup_ops Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 10/13] cgroup/drm: Client exit hook Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 11/13] cgroup/drm: Introduce weight based drm cgroup control Tvrtko Ursulin
2022-11-22 21:29 ` Tejun Heo
2022-11-24 14:32 ` Tvrtko Ursulin
2022-11-28 19:50 ` Tejun Heo
2022-11-09 16:11 ` [RFC 12/13] drm/i915: Wire up with drm controller GPU time query Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 13/13] drm/i915: Implement cgroup controller over budget throttling Tvrtko Ursulin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221109161141.2987173-6-tvrtko.ursulin@linux.intel.com \
--to=tvrtko.ursulin@linux.intel.com \
--cc=Intel-gfx@lists.freedesktop.org \
--cc=Kenny.Ho@amd.com \
--cc=airlied@redhat.com \
--cc=brian.welty@intel.com \
--cc=cgroups@vger.kernel.org \
--cc=christian.koenig@amd.com \
--cc=daniel.vetter@ffwll.ch \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizefan.x@bytedance.com \
--cc=marcheu@chromium.org \
--cc=robdclark@chromium.org \
--cc=tj@kernel.org \
--cc=tjmercier@google.com \
--cc=tvrtko.ursulin@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®