From: Don Zickus <dzickus@redhat.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Ingo Molnar <mingo@elte.hu>, LKML <linux-kernel@vger.kernel.org>,
uobergfe@redhat.com, Don Zickus <dzickus@redhat.com>
Subject: [PATCH 4/9] watchdog: introduce the proc_watchdog_common() function
Date: Tue, 4 Nov 2014 11:20:19 -0500 [thread overview]
Message-ID: <1415118024-194247-5-git-send-email-dzickus@redhat.com> (raw)
In-Reply-To: <1415118024-194247-1-git-send-email-dzickus@redhat.com>
From: Ulrich Obergfell <uobergfe@redhat.com>
Three of four handlers for the watchdog parameters in /proc/sys/kernel
essentially have to do the same thing.
if the parameter is being read {
return the state of the corresponding bit(s) in 'watchdog_enabled'
} else {
set/clear the state of the corresponding bit(s) in 'watchdog_enabled'
update the run state of the lockup detector(s)
}
Hence, introduce a common function that can be called by those handlers.
The callers pass a 'bit mask' to this function to indicate which bit(s)
should be set/cleared in 'watchdog_enabled'.
This function handles an uncommon race with watchdog_nmi_enable() where
a concurrent update of 'watchdog_enabled' is possible. We use 'cmpxchg'
to detect the concurrency. [This avoids introducing a new spinlock or a
mutex to synchronize updates of 'watchdog_enabled'. Using the same lock
or mutex in watchdog thread context and in system call context needs to
be considered carefully because it can make the code prone to deadlock
situations in connection with parking/unparking the watchdog threads.]
Signed-off-by: Ulrich Obergfell <uobergfe@redhat.com>
Signed-off-by: Don Zickus <dzickus@redhat.com>
---
kernel/watchdog.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index df4ef38..7626208 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -704,6 +704,71 @@ static int proc_watchdog_update(void)
static DEFINE_MUTEX(watchdog_proc_mutex);
/*
+ * common function for watchdog, nmi_watchdog and soft_watchdog parameter
+ *
+ * caller | table->data points to | 'which' contains the flag(s)
+ * -------------------|-----------------------|-----------------------------
+ * proc_watchdog | watchdog_user_enabled | NMI_WATCHDOG_ENABLED or'ed
+ * | | with SOFT_WATCHDOG_ENABLED
+ * -------------------|-----------------------|-----------------------------
+ * proc_nmi_watchdog | nmi_watchdog_enabled | NMI_WATCHDOG_ENABLED
+ * -------------------|-----------------------|-----------------------------
+ * proc_soft_watchdog | soft_watchdog_enabled | SOFT_WATCHDOG_ENABLED
+ */
+static int proc_watchdog_common(int which, struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int err, old, new;
+ int *watchdog_param = (int *)table->data;
+
+ mutex_lock(&watchdog_proc_mutex);
+
+ /*
+ * If the parameter is being read return the state of the corresponding
+ * bit(s) in 'watchdog_enabled', else update 'watchdog_enabled' and the
+ * run state of the lockup detectors.
+ */
+ if (!write) {
+ *watchdog_param = (watchdog_enabled & which) != 0;
+ err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ } else {
+ err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ if (err)
+ goto out;
+
+ /*
+ * There is a race window between fetching the current value
+ * from 'watchdog_enabled' and storing the new value. During
+ * this race window, watchdog_nmi_enable() can sneak in and
+ * clear the NMI_WATCHDOG_ENABLED bit in 'watchdog_enabled'.
+ * The 'cmpxchg' detects this race and the loop retries.
+ */
+ do {
+ old = watchdog_enabled;
+ /*
+ * If the parameter value is not zero set the
+ * corresponding bit(s), else clear it(them).
+ */
+ if (*watchdog_param)
+ new = old | which;
+ else
+ new = old & ~which;
+ } while (cmpxchg(&watchdog_enabled, old, new) != old);
+
+ /*
+ * Update the run state of the lockup detectors.
+ * Restore 'watchdog_enabled' on failure.
+ */
+ err = proc_watchdog_update();
+ if (err)
+ watchdog_enabled = old;
+ }
+out:
+ mutex_unlock(&watchdog_proc_mutex);
+ return err;
+}
+
+/*
* proc handler for /proc/sys/kernel/nmi_watchdog,watchdog_thresh
*/
--
1.7.1
next prev parent reply other threads:[~2014-11-04 16:20 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-04 16:20 [PATCH 0/9] watchdog: internally split softlockup and hardlockup Don Zickus
2014-11-04 16:20 ` [PATCH 1/9] watchdog: new definitions and variables, initialization Don Zickus
2014-11-04 16:20 ` [PATCH 2/9] watchdog: introduce the proc_watchdog_update() function Don Zickus
2014-11-04 16:20 ` [PATCH 3/9] watchdog: move definition of 'watchdog_proc_mutex' outside of proc_dowatchdog() Don Zickus
2014-11-04 16:20 ` Don Zickus [this message]
2014-11-04 16:20 ` [PATCH 5/9] watchdog: introduce separate handlers for parameters in /proc/sys/kernel Don Zickus
2014-11-04 16:20 ` [PATCH 6/9] watchdog: implement error handling for failure to set up hardware perf events Don Zickus
2014-11-04 16:20 ` [PATCH 7/9] watchdog: enable the new user interface of the watchdog mechanism Don Zickus
2014-11-04 16:20 ` [PATCH 8/9] watchdog: clean up some function names and arguments Don Zickus
2014-11-04 16:20 ` [PATCH 9/9] watchdog: introduce the hardlockup_detector_disable() function Don Zickus
2014-12-17 21:25 ` [PATCH 0/9] watchdog: internally split softlockup and hardlockup Don Zickus
2015-01-21 14:15 ` Don Zickus
2015-01-21 22:23 ` Andrew Morton
2015-02-05 20:40 Don Zickus
2015-02-05 20:40 ` [PATCH 4/9] watchdog: introduce the proc_watchdog_common() function Don Zickus
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=1415118024-194247-5-git-send-email-dzickus@redhat.com \
--to=dzickus@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=uobergfe@redhat.com \
/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
Powered by JetHome