diff options
author | Johannes Berg <johannes.berg@intel.com> | 2023-11-24 17:25:25 +0100 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2023-11-27 11:24:50 +0100 |
commit | f4acfcd4deb158b96595250cc332901b282d15b0 (patch) | |
tree | bc06b650955d9bbc41bd889f8f497ecb92e1416b /fs/debugfs/file.c | |
parent | debugfs: fix automount d_fsdata usage (diff) | |
download | linux-f4acfcd4deb158b96595250cc332901b282d15b0.tar.xz linux-f4acfcd4deb158b96595250cc332901b282d15b0.zip |
debugfs: annotate debugfs handlers vs. removal with lockdep
When you take a lock in a debugfs handler but also try
to remove the debugfs file under that lock, things can
deadlock since the removal has to wait for all users
to finish.
Add lockdep annotations in debugfs_file_get()/_put()
to catch such issues.
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'fs/debugfs/file.c')
-rw-r--r-- | fs/debugfs/file.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index e00189aebbf4..3eff92450fd5 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -108,6 +108,12 @@ int debugfs_file_get(struct dentry *dentry) kfree(fsd); fsd = READ_ONCE(dentry->d_fsdata); } +#ifdef CONFIG_LOCKDEP + fsd->lock_name = kasprintf(GFP_KERNEL, "debugfs:%pd", dentry); + lockdep_register_key(&fsd->key); + lockdep_init_map(&fsd->lockdep_map, fsd->lock_name ?: "debugfs", + &fsd->key, 0); +#endif } /* @@ -124,6 +130,8 @@ int debugfs_file_get(struct dentry *dentry) if (!refcount_inc_not_zero(&fsd->active_users)) return -EIO; + lock_map_acquire_read(&fsd->lockdep_map); + return 0; } EXPORT_SYMBOL_GPL(debugfs_file_get); @@ -141,6 +149,8 @@ void debugfs_file_put(struct dentry *dentry) { struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata); + lock_map_release(&fsd->lockdep_map); + if (refcount_dec_and_test(&fsd->active_users)) complete(&fsd->active_users_drained); } |