diff options
author | Reinette Chatre <reinette.chatre@intel.com> | 2018-07-11 16:06:07 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2018-07-12 15:33:43 -0400 |
commit | 2989360d9c6669d8ae64edc933088e640481b48b (patch) | |
tree | f4f80842199f6ba68a23558524b49482a2a4028f | |
parent | 33dc3e410a0d99f394905143b26d34f1fd64c962 (diff) |
x86/intel_rdt: Fix possible circular lock dependency
Lockdep is reporting a possible circular locking dependency:
======================================================
WARNING: possible circular locking dependency detected
4.18.0-rc1-test-test+ #4 Not tainted
------------------------------------------------------
user_example/766 is trying to acquire lock:
0000000073479a0f (rdtgroup_mutex){+.+.}, at: pseudo_lock_dev_mmap
but task is already holding lock:
000000001ef7a35b (&mm->mmap_sem){++++}, at: vm_mmap_pgoff+0x9f/0x
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (&mm->mmap_sem){++++}:
_copy_to_user+0x1e/0x70
filldir+0x91/0x100
dcache_readdir+0x54/0x160
iterate_dir+0x142/0x190
__x64_sys_getdents+0xb9/0x170
do_syscall_64+0x86/0x200
entry_SYSCALL_64_after_hwframe+0x49/0xbe
-> #1 (&sb->s_type->i_mutex_key#3){++++}:
start_creating+0x60/0x100
debugfs_create_dir+0xc/0xc0
rdtgroup_pseudo_lock_create+0x217/0x4d0
rdtgroup_schemata_write+0x313/0x3d0
kernfs_fop_write+0xf0/0x1a0
__vfs_write+0x36/0x190
vfs_write+0xb7/0x190
ksys_write+0x52/0xc0
do_syscall_64+0x86/0x200
entry_SYSCALL_64_after_hwframe+0x49/0xbe
-> #0 (rdtgroup_mutex){+.+.}:
__mutex_lock+0x80/0x9b0
pseudo_lock_dev_mmap+0x2f/0x170
mmap_region+0x3d6/0x610
do_mmap+0x387/0x580
vm_mmap_pgoff+0xcf/0x110
ksys_mmap_pgoff+0x170/0x1f0
do_syscall_64+0x86/0x200
entry_SYSCALL_64_after_hwframe+0x49/0xbe
other info that might help us debug this:
Chain exists of:
rdtgroup_mutex --> &sb->s_type->i_mutex_key#3 --> &mm->mmap_sem
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&mm->mmap_sem);
lock(&sb->s_type->i_mutex_key#3);
lock(&mm->mmap_sem);
lock(rdtgroup_mutex);
*** DEADLOCK ***
1 lock held by user_example/766:
#0: 000000001ef7a35b (&mm->mmap_sem){++++}, at: vm_mmap_pgoff+0x9f/0x110
rdtgroup_mutex is already being released temporarily during pseudo-lock
region creation to prevent the potential deadlock between rdtgroup_mutex
and mm->mmap_sem that is obtained during device_create(). Move the
debugfs creation into this area to avoid the same circular dependency.
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: fenghua.yu@intel.com
Cc: tony.luck@intel.com
Cc: vikas.shivappa@linux.intel.com
Cc: gavin.hindman@intel.com
Cc: jithu.joseph@intel.com
Cc: hpa@zytor.com
Link: https://lkml.kernel.org/r/fffb57f9c6b8285904c9a60cc91ce21591af17fe.1531332480.git.reinette.chatre@intel.com
-rw-r--r-- | arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c | 29 |
1 files changed, 14 insertions, 15 deletions
diff --git a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c index 751c78f9992f..f80c58f8adc3 100644 --- a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +++ b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c | |||
@@ -1254,19 +1254,10 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp) | |||
1254 | goto out_cstates; | 1254 | goto out_cstates; |
1255 | } | 1255 | } |
1256 | 1256 | ||
1257 | if (!IS_ERR_OR_NULL(debugfs_resctrl)) { | ||
1258 | plr->debugfs_dir = debugfs_create_dir(rdtgrp->kn->name, | ||
1259 | debugfs_resctrl); | ||
1260 | if (!IS_ERR_OR_NULL(plr->debugfs_dir)) | ||
1261 | debugfs_create_file("pseudo_lock_measure", 0200, | ||
1262 | plr->debugfs_dir, rdtgrp, | ||
1263 | &pseudo_measure_fops); | ||
1264 | } | ||
1265 | |||
1266 | ret = pseudo_lock_minor_get(&new_minor); | 1257 | ret = pseudo_lock_minor_get(&new_minor); |
1267 | if (ret < 0) { | 1258 | if (ret < 0) { |
1268 | rdt_last_cmd_puts("unable to obtain a new minor number\n"); | 1259 | rdt_last_cmd_puts("unable to obtain a new minor number\n"); |
1269 | goto out_debugfs; | 1260 | goto out_cstates; |
1270 | } | 1261 | } |
1271 | 1262 | ||
1272 | /* | 1263 | /* |
@@ -1275,11 +1266,20 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp) | |||
1275 | * | 1266 | * |
1276 | * The mutex has to be released temporarily to avoid a potential | 1267 | * The mutex has to be released temporarily to avoid a potential |
1277 | * deadlock with the mm->mmap_sem semaphore which is obtained in | 1268 | * deadlock with the mm->mmap_sem semaphore which is obtained in |
1278 | * the device_create() callpath below as well as before the mmap() | 1269 | * the device_create() and debugfs_create_dir() callpath below |
1279 | * callback is called. | 1270 | * as well as before the mmap() callback is called. |
1280 | */ | 1271 | */ |
1281 | mutex_unlock(&rdtgroup_mutex); | 1272 | mutex_unlock(&rdtgroup_mutex); |
1282 | 1273 | ||
1274 | if (!IS_ERR_OR_NULL(debugfs_resctrl)) { | ||
1275 | plr->debugfs_dir = debugfs_create_dir(rdtgrp->kn->name, | ||
1276 | debugfs_resctrl); | ||
1277 | if (!IS_ERR_OR_NULL(plr->debugfs_dir)) | ||
1278 | debugfs_create_file("pseudo_lock_measure", 0200, | ||
1279 | plr->debugfs_dir, rdtgrp, | ||
1280 | &pseudo_measure_fops); | ||
1281 | } | ||
1282 | |||
1283 | dev = device_create(pseudo_lock_class, NULL, | 1283 | dev = device_create(pseudo_lock_class, NULL, |
1284 | MKDEV(pseudo_lock_major, new_minor), | 1284 | MKDEV(pseudo_lock_major, new_minor), |
1285 | rdtgrp, "%s", rdtgrp->kn->name); | 1285 | rdtgrp, "%s", rdtgrp->kn->name); |
@@ -1290,7 +1290,7 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp) | |||
1290 | ret = PTR_ERR(dev); | 1290 | ret = PTR_ERR(dev); |
1291 | rdt_last_cmd_printf("failed to create character device: %d\n", | 1291 | rdt_last_cmd_printf("failed to create character device: %d\n", |
1292 | ret); | 1292 | ret); |
1293 | goto out_minor; | 1293 | goto out_debugfs; |
1294 | } | 1294 | } |
1295 | 1295 | ||
1296 | /* We released the mutex - check if group was removed while we did so */ | 1296 | /* We released the mutex - check if group was removed while we did so */ |
@@ -1311,10 +1311,9 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp) | |||
1311 | 1311 | ||
1312 | out_device: | 1312 | out_device: |
1313 | device_destroy(pseudo_lock_class, MKDEV(pseudo_lock_major, new_minor)); | 1313 | device_destroy(pseudo_lock_class, MKDEV(pseudo_lock_major, new_minor)); |
1314 | out_minor: | ||
1315 | pseudo_lock_minor_release(new_minor); | ||
1316 | out_debugfs: | 1314 | out_debugfs: |
1317 | debugfs_remove_recursive(plr->debugfs_dir); | 1315 | debugfs_remove_recursive(plr->debugfs_dir); |
1316 | pseudo_lock_minor_release(new_minor); | ||
1318 | out_cstates: | 1317 | out_cstates: |
1319 | pseudo_lock_cstates_relax(plr); | 1318 | pseudo_lock_cstates_relax(plr); |
1320 | out_region: | 1319 | out_region: |