mirror of https://gitee.com/openkylin/linux.git
s390/debug: Fix s390dbf lockdep problem in debug_(un)register_view()
The debug_register/unregister_view() functions call debugfs_remove() while holding the debug_info spinlock. Because debugfs_remove() takes a mutex and therefore can sleep this is not allowed. To fix the problem we give up the debug_info lock before calling debugfs_remove(). The following shows the lockdep message: [ INFO: possible circular locking dependency detected ] ------------------------------------------------------- rmmod/4379 is trying to acquire lock: (&sb->s_type->i_mutex_key#2){+.+.+.}, at: [<00000000003acae2>] debugfs_remove+0x5e/0xa but task is already holding lock: (&(&rc->lock)->rlock){-.-...}, at: [<000000000010a5ae>] debug_unregister_view+0x3a/0xd which lock already depends on the new lock. -> #0 (&sb->s_type->i_mutex_key#2){+.+.+.}: [<00000000001b1644>] validate_chain+0x880/0x1154 [<00000000001b4d6c>] __lock_acquire+0x414/0xc44 [<00000000001b5c16>] lock_acquire+0xbe/0x178 [<0000000000614016>] mutex_lock_nested+0x66/0x36c [<00000000003acae2>] debugfs_remove+0x5e/0xac [<000000000010a620>] debug_unregister_view+0xac/0xd0 [<000003ff8002f140>] qeth_core_exit+0x48/0xf08 [qeth] [<00000000001c35a4>] SyS_delete_module+0x1a4/0x260 [<0000000000618134>] sysc_noemu+0x22/0x28 [<000003fffd4704da>] 0x3fffd4704da Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
2a893f91f5
commit
5a334c082f
|
@ -1127,13 +1127,14 @@ debug_register_view(debug_info_t * id, struct debug_view *view)
|
||||||
if (i == DEBUG_MAX_VIEWS) {
|
if (i == DEBUG_MAX_VIEWS) {
|
||||||
pr_err("Registering view %s/%s would exceed the maximum "
|
pr_err("Registering view %s/%s would exceed the maximum "
|
||||||
"number of views %i\n", id->name, view->name, i);
|
"number of views %i\n", id->name, view->name, i);
|
||||||
debugfs_remove(pde);
|
|
||||||
rc = -1;
|
rc = -1;
|
||||||
} else {
|
} else {
|
||||||
id->views[i] = view;
|
id->views[i] = view;
|
||||||
id->debugfs_entries[i] = pde;
|
id->debugfs_entries[i] = pde;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&id->lock, flags);
|
spin_unlock_irqrestore(&id->lock, flags);
|
||||||
|
if (rc)
|
||||||
|
debugfs_remove(pde);
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1146,9 +1147,9 @@ EXPORT_SYMBOL(debug_register_view);
|
||||||
int
|
int
|
||||||
debug_unregister_view(debug_info_t * id, struct debug_view *view)
|
debug_unregister_view(debug_info_t * id, struct debug_view *view)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
struct dentry *dentry = NULL;
|
||||||
int i;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int i, rc = 0;
|
||||||
|
|
||||||
if (!id)
|
if (!id)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1160,10 +1161,12 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view)
|
||||||
if (i == DEBUG_MAX_VIEWS)
|
if (i == DEBUG_MAX_VIEWS)
|
||||||
rc = -1;
|
rc = -1;
|
||||||
else {
|
else {
|
||||||
debugfs_remove(id->debugfs_entries[i]);
|
dentry = id->debugfs_entries[i];
|
||||||
id->views[i] = NULL;
|
id->views[i] = NULL;
|
||||||
|
id->debugfs_entries[i] = NULL;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&id->lock, flags);
|
spin_unlock_irqrestore(&id->lock, flags);
|
||||||
|
debugfs_remove(dentry);
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue