From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Johannes Berg <johannes.berg@intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH AUTOSEL 5.15 07/10] debugfs: annotate debugfs handlers vs. removal with lockdep
Date: Mon, 4 Dec 2023 15:36:04 -0500 [thread overview]
Message-ID: <20231204203616.2094529-7-sashal@kernel.org> (raw)
In-Reply-To: <20231204203616.2094529-1-sashal@kernel.org>
From: Johannes Berg <johannes.berg@intel.com>
[ Upstream commit f4acfcd4deb158b96595250cc332901b282d15b0 ]
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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/debugfs/file.c | 10 ++++++++++
fs/debugfs/inode.c | 12 ++++++++++++
fs/debugfs/internal.h | 6 ++++++
3 files changed, 28 insertions(+)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index df5c2162e7297..a1aea4d1637c7 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);
}
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 5290a721a703f..014ff204548d9 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -219,6 +219,14 @@ static void debugfs_release_dentry(struct dentry *dentry)
if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
return;
+ /* check it wasn't a dir (no fsdata) or automount (no real_fops) */
+ if (fsd && fsd->real_fops) {
+#ifdef CONFIG_LOCKDEP
+ lockdep_unregister_key(&fsd->key);
+ kfree(fsd->lock_name);
+#endif
+ }
+
kfree(fsd);
}
@@ -712,6 +720,10 @@ static void __debugfs_file_removed(struct dentry *dentry)
fsd = READ_ONCE(dentry->d_fsdata);
if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
return;
+
+ lock_map_acquire(&fsd->lockdep_map);
+ lock_map_release(&fsd->lockdep_map);
+
if (!refcount_dec_and_test(&fsd->active_users))
wait_for_completion(&fsd->active_users_drained);
}
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index f7c489b5a368c..c7d61cfc97d26 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -7,6 +7,7 @@
#ifndef _DEBUGFS_INTERNAL_H_
#define _DEBUGFS_INTERNAL_H_
+#include <linux/lockdep.h>
struct file_operations;
@@ -23,6 +24,11 @@ struct debugfs_fsdata {
struct {
refcount_t active_users;
struct completion active_users_drained;
+#ifdef CONFIG_LOCKDEP
+ struct lockdep_map lockdep_map;
+ struct lock_class_key key;
+ char *lock_name;
+#endif
};
};
};
--
2.42.0
next prev parent reply other threads:[~2023-12-04 20:39 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-04 20:35 [PATCH AUTOSEL 5.15 01/10] pinctrl: lochnagar: Don't build on MIPS Sasha Levin
2023-12-04 20:35 ` [PATCH AUTOSEL 5.15 02/10] ALSA: hda - Fix speaker and headset mic pin config for CHUWI CoreBook XPro Sasha Levin
2023-12-04 20:36 ` [PATCH AUTOSEL 5.15 03/10] ksmbd: don't update ->op_state as OPLOCK_STATE_NONE on error Sasha Levin
2023-12-04 20:36 ` [PATCH AUTOSEL 5.15 04/10] mptcp: fix uninit-value in mptcp_incoming_options Sasha Levin
2023-12-04 20:36 ` [PATCH AUTOSEL 5.15 05/10] wifi: cfg80211: lock wiphy mutex for rfkill poll Sasha Levin
2023-12-04 20:36 ` [PATCH AUTOSEL 5.15 06/10] debugfs: fix automount d_fsdata usage Sasha Levin
2023-12-04 20:36 ` Sasha Levin [this message]
2023-12-04 20:36 ` [PATCH AUTOSEL 5.15 08/10] debugfs: add API to allow debugfs operations cancellation Sasha Levin
2023-12-04 20:36 ` [PATCH AUTOSEL 5.15 09/10] drm/amdgpu: Fix cat debugfs amdgpu_regs_didt causes kernel null pointer Sasha Levin
2023-12-04 20:36 ` [PATCH AUTOSEL 5.15 10/10] nvme-core: check for too small lba shift Sasha Levin
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=20231204203616.2094529-7-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=johannes.berg@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
/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