summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDesmond Cheong Zhi Xi <desmondcheongzx@gmail.com>2021-07-12 07:35:05 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-09-18 14:40:19 +0300
commit54e51d288b38377e8cd645a83e1ad08cc9d20ccc (patch)
tree49c4a919fa5afff454d9bcbc4638da3aef74441b
parentdf19d95141d18231952153e03f578f078f0be384 (diff)
downloadlinux-54e51d288b38377e8cd645a83e1ad08cc9d20ccc.tar.xz
drm: avoid blocking in drm_clients_info's rcu section
[ Upstream commit 5eff9585de220cdd131237f5665db5e6c6bdf590 ] Inside drm_clients_info, the rcu_read_lock is held to lock pid_task()->comm. However, within this protected section, a call to drm_is_current_master is made, which involves a mutex lock in a future patch. However, this is illegal because the mutex lock might block while in the RCU read-side critical section. Since drm_is_current_master isn't protected by rcu_read_lock, we avoid this by moving it out of the RCU critical section. The following report came from intel-gfx ci's igt@debugfs_test@read_all_entries testcase: ============================= [ BUG: Invalid wait context ] 5.13.0-CI-Patchwork_20515+ #1 Tainted: G W ----------------------------- debugfs_test/1101 is trying to lock: ffff888132d901a8 (&dev->master_mutex){+.+.}-{3:3}, at: drm_is_current_master+0x1e/0x50 other info that might help us debug this: context-{4:4} 3 locks held by debugfs_test/1101: #0: ffff88810fdffc90 (&p->lock){+.+.}-{3:3}, at: seq_read_iter+0x53/0x3b0 #1: ffff888132d90240 (&dev->filelist_mutex){+.+.}-{3:3}, at: drm_clients_info+0x63/0x2a0 #2: ffffffff82734220 (rcu_read_lock){....}-{1:2}, at: drm_clients_info+0x1b1/0x2a0 stack backtrace: CPU: 8 PID: 1101 Comm: debugfs_test Tainted: G W 5.13.0-CI-Patchwork_20515+ #1 Hardware name: Intel Corporation CometLake Client Platform/CometLake S UDIMM (ERB/CRB), BIOS CMLSFWR1.R00.1263.D00.1906260926 06/26/2019 Call Trace: dump_stack+0x7f/0xad __lock_acquire.cold.78+0x2af/0x2ca lock_acquire+0xd3/0x300 ? drm_is_current_master+0x1e/0x50 ? __mutex_lock+0x76/0x970 ? lockdep_hardirqs_on+0xbf/0x130 __mutex_lock+0xab/0x970 ? drm_is_current_master+0x1e/0x50 ? drm_is_current_master+0x1e/0x50 ? drm_is_current_master+0x1e/0x50 drm_is_current_master+0x1e/0x50 drm_clients_info+0x107/0x2a0 seq_read_iter+0x178/0x3b0 seq_read+0x104/0x150 full_proxy_read+0x4e/0x80 vfs_read+0xa5/0x1b0 ksys_read+0x5a/0xd0 do_syscall_64+0x39/0xb0 entry_SYSCALL_64_after_hwframe+0x44/0xae Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20210712043508.11584-3-desmondcheongzx@gmail.com Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/gpu/drm/drm_debugfs.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 3d7182001004..b0a826489488 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -91,6 +91,7 @@ static int drm_clients_info(struct seq_file *m, void *data)
mutex_lock(&dev->filelist_mutex);
list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
struct task_struct *task;
+ bool is_current_master = drm_is_current_master(priv);
rcu_read_lock(); /* locks pid_task()->comm */
task = pid_task(priv->pid, PIDTYPE_PID);
@@ -99,7 +100,7 @@ static int drm_clients_info(struct seq_file *m, void *data)
task ? task->comm : "<unknown>",
pid_vnr(priv->pid),
priv->minor->index,
- drm_is_current_master(priv) ? 'y' : 'n',
+ is_current_master ? 'y' : 'n',
priv->authenticated ? 'y' : 'n',
from_kuid_munged(seq_user_ns(m), uid),
priv->magic);