From e9718201c6ed785c61077797a74ffda7e0438fb9 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 22 Jun 2015 15:30:02 -0400 Subject: [PATCH] lockdep: do not automatically collect all backtraces It is expensive to collect backtraces every time a lock is checked in order to provide cycle backtraces. The backtraces can be forced on for specific locks or globally via the new config option "lockdep_force_backtrace". Signed-off-by: Jason Dillaman (cherry picked from commit 7354d25f56c5e004f288febdee2b6961c069163b) --- src/common/Mutex.h | 2 +- src/common/config_opts.h | 1 + src/common/lockdep.cc | 16 +++++++++++++--- src/common/lockdep.h | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/common/Mutex.h b/src/common/Mutex.h index fb91d612a8b9..6a4e6b385eea 100644 --- a/src/common/Mutex.h +++ b/src/common/Mutex.h @@ -53,7 +53,7 @@ private: id = lockdep_register(name.c_str()); } void _will_lock() { // about to lock - id = lockdep_will_lock(name.c_str(), id); + id = lockdep_will_lock(name.c_str(), id, backtrace); } void _locked() { // just locked id = lockdep_locked(name.c_str(), id, backtrace); diff --git a/src/common/config_opts.h b/src/common/config_opts.h index 85a602221f2f..2c6bb038bb6d 100644 --- a/src/common/config_opts.h +++ b/src/common/config_opts.h @@ -23,6 +23,7 @@ OPTION(num_client, OPT_INT, 1) OPTION(monmap, OPT_STR, "") OPTION(mon_host, OPT_STR, "") OPTION(lockdep, OPT_BOOL, false) +OPTION(lockdep_force_backtrace, OPT_BOOL, false) // always gather current backtrace at every lock OPTION(run_dir, OPT_STR, "/var/run/ceph") // the "/var/run/ceph" dir, created on daemon startup OPTION(admin_socket, OPT_STR, "$run_dir/$cluster-$name.asok") // default changed by common_preinit() diff --git a/src/common/lockdep.cc b/src/common/lockdep.cc index e0b69e137249..ea3f6d55d17b 100644 --- a/src/common/lockdep.cc +++ b/src/common/lockdep.cc @@ -56,6 +56,12 @@ static list free_ids; static ceph::unordered_map > held; static BackTrace *follows[MAX_LOCKS][MAX_LOCKS]; // follows[a][b] means b taken after a +static bool lockdep_force_backtrace() +{ + return (g_lockdep_ceph_ctx != NULL && + g_lockdep_ceph_ctx->_conf->lockdep_force_backtrace); +} + /******* Functions **********/ void lockdep_register_ceph_context(CephContext *cct) { @@ -204,7 +210,7 @@ static bool does_follow(int a, int b) return false; } -int lockdep_will_lock(const char *name, int id) +int lockdep_will_lock(const char *name, int id, bool force_backtrace) { pthread_t p = pthread_self(); if (id < 0) id = lockdep_register(name); @@ -234,8 +240,8 @@ int lockdep_will_lock(const char *name, int id) // new dependency // did we just create a cycle? - BackTrace *bt = new BackTrace(BACKTRACE_SKIP); if (does_follow(id, p->first)) { + BackTrace *bt = new BackTrace(BACKTRACE_SKIP); lockdep_dout(0) << "new dependency " << lock_names[p->first] << " (" << p->first << ") -> " << name << " (" << id << ")" << " creates a cycle at\n"; @@ -261,6 +267,10 @@ int lockdep_will_lock(const char *name, int id) assert(0); // actually, we should just die here. } else { + BackTrace *bt = NULL; + if (force_backtrace || lockdep_force_backtrace()) { + bt = new BackTrace(BACKTRACE_SKIP); + } follows[p->first][id] = bt; lockdep_dout(10) << lock_names[p->first] << " -> " << name << " at" << dendl; //bt->print(*_dout); @@ -280,7 +290,7 @@ int lockdep_locked(const char *name, int id, bool force_backtrace) pthread_mutex_lock(&lockdep_mutex); lockdep_dout(20) << "_locked " << name << dendl; - if (g_lockdep >= 2 || force_backtrace) + if (force_backtrace || lockdep_force_backtrace()) held[p][id] = new BackTrace(BACKTRACE_SKIP); else held[p][id] = 0; diff --git a/src/common/lockdep.h b/src/common/lockdep.h index e9949fd76fa1..63d2f0dd68e1 100644 --- a/src/common/lockdep.h +++ b/src/common/lockdep.h @@ -23,7 +23,7 @@ extern void lockdep_register_ceph_context(CephContext *cct); extern void lockdep_unregister_ceph_context(CephContext *cct); extern int lockdep_register(const char *n); extern void lockdep_unregister(int id); -extern int lockdep_will_lock(const char *n, int id); +extern int lockdep_will_lock(const char *n, int id, bool force_backtrace=false); extern int lockdep_locked(const char *n, int id, bool force_backtrace=false); extern int lockdep_will_unlock(const char *n, int id); extern int lockdep_dump_locks(); -- 2.47.3