Merge: Apply select fixes to drivers/watchdog

MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8388

JIRA: https://issues.redhat.com/browse/RHEL-192487

These commits fix potential bugs in RHEL.

Signed-off-by: David Arcari <darcari@redhat.com>

Approved-by: Tony Camuso <tcamuso@redhat.com>
Approved-by: Ricardo Robaina <rrobaina@redhat.com>
Approved-by: Steve Best <sbest@redhat.com>
Approved-by: Rafael Aquini <raquini@redhat.com>
Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com>

Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
CKI KWF Bot
2026-08-04 08:11:42 +00:00
2 changed files with 31 additions and 18 deletions
+2 -3
View File
@@ -1034,6 +1034,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
/* Fill in the data structures */
cdev_init(&wd_data->cdev, &watchdog_fops);
wd_data->cdev.owner = wdd->ops->owner;
/* Add the device */
err = cdev_device_add(&wd_data->cdev, &wd_data->dev);
@@ -1043,13 +1044,11 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
if (wdd->id == 0) {
misc_deregister(&watchdog_miscdev);
old_wd_data = NULL;
put_device(&wd_data->dev);
}
put_device(&wd_data->dev);
return err;
}
wd_data->cdev.owner = wdd->ops->owner;
/* Record time of most recent heartbeat as 'just before now'. */
wd_data->last_hw_keepalive = ktime_sub(ktime_get(), 1);
watchdog_set_open_deadline(wd_data);
+29 -15
View File
@@ -40,6 +40,7 @@ int __read_mostly watchdog_user_enabled = 1;
static int __read_mostly watchdog_hardlockup_user_enabled = WATCHDOG_HARDLOCKUP_DEFAULT;
static int __read_mostly watchdog_softlockup_user_enabled = 1;
int __read_mostly watchdog_thresh = 10;
static int __read_mostly watchdog_thresh_next;
static int __read_mostly watchdog_hardlockup_available;
struct cpumask watchdog_cpumask __read_mostly;
@@ -684,12 +685,20 @@ int lockup_detector_offline_cpu(unsigned int cpu)
return 0;
}
static void __lockup_detector_reconfigure(void)
static void __lockup_detector_reconfigure(bool thresh_changed)
{
cpus_read_lock();
watchdog_hardlockup_stop();
softlockup_stop_all();
/*
* To prevent watchdog_timer_fn from using the old interval and
* the new watchdog_thresh at the same time, which could lead to
* false softlockup reports, it is necessary to update the
* watchdog_thresh after the softlockup is completed.
*/
if (thresh_changed)
watchdog_thresh = READ_ONCE(watchdog_thresh_next);
set_sample_period();
lockup_detector_update_enable();
if (watchdog_enabled && watchdog_thresh)
@@ -707,7 +716,7 @@ static void __lockup_detector_reconfigure(void)
void lockup_detector_reconfigure(void)
{
mutex_lock(&watchdog_mutex);
__lockup_detector_reconfigure();
__lockup_detector_reconfigure(false);
mutex_unlock(&watchdog_mutex);
}
@@ -727,27 +736,29 @@ static __init void lockup_detector_setup(void)
return;
mutex_lock(&watchdog_mutex);
__lockup_detector_reconfigure();
__lockup_detector_reconfigure(false);
softlockup_initialized = true;
mutex_unlock(&watchdog_mutex);
}
#else /* CONFIG_SOFTLOCKUP_DETECTOR */
static void __lockup_detector_reconfigure(void)
static void __lockup_detector_reconfigure(bool thresh_changed)
{
cpus_read_lock();
watchdog_hardlockup_stop();
if (thresh_changed)
watchdog_thresh = READ_ONCE(watchdog_thresh_next);
lockup_detector_update_enable();
watchdog_hardlockup_start();
cpus_read_unlock();
}
void lockup_detector_reconfigure(void)
{
__lockup_detector_reconfigure();
__lockup_detector_reconfigure(false);
}
static inline void lockup_detector_setup(void)
{
__lockup_detector_reconfigure();
__lockup_detector_reconfigure(false);
}
#endif /* !CONFIG_SOFTLOCKUP_DETECTOR */
@@ -783,11 +794,11 @@ void lockup_detector_soft_poweroff(void)
#ifdef CONFIG_SYSCTL
/* Propagate any changes to the watchdog infrastructure */
static void proc_watchdog_update(void)
static void proc_watchdog_update(bool thresh_changed)
{
/* Remove impossible cpus to keep sysctl output clean. */
cpumask_and(&watchdog_cpumask, &watchdog_cpumask, cpu_possible_mask);
__lockup_detector_reconfigure();
__lockup_detector_reconfigure(thresh_changed);
}
/*
@@ -809,6 +820,7 @@ static int proc_watchdog_common(int which, struct ctl_table *table, int write,
mutex_lock(&watchdog_mutex);
old = *param;
if (!write) {
/*
* On read synchronize the userspace interface. This is a
@@ -816,11 +828,11 @@ static int proc_watchdog_common(int which, struct ctl_table *table, int write,
*/
*param = (watchdog_enabled & which) != 0;
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
*param = old;
} else {
old = READ_ONCE(*param);
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
if (!err && old != READ_ONCE(*param))
proc_watchdog_update();
proc_watchdog_update(false);
}
mutex_unlock(&watchdog_mutex);
return err;
@@ -869,11 +881,13 @@ int proc_watchdog_thresh(struct ctl_table *table, int write,
mutex_lock(&watchdog_mutex);
old = READ_ONCE(watchdog_thresh);
watchdog_thresh_next = READ_ONCE(watchdog_thresh);
old = watchdog_thresh_next;
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
if (!err && write && old != READ_ONCE(watchdog_thresh))
proc_watchdog_update();
if (!err && write && old != READ_ONCE(watchdog_thresh_next))
proc_watchdog_update(true);
mutex_unlock(&watchdog_mutex);
return err;
@@ -894,7 +908,7 @@ int proc_watchdog_cpumask(struct ctl_table *table, int write,
err = proc_do_large_bitmap(table, write, buffer, lenp, ppos);
if (!err && write)
proc_watchdog_update();
proc_watchdog_update(false);
mutex_unlock(&watchdog_mutex);
return err;
@@ -914,7 +928,7 @@ static struct ctl_table watchdog_sysctls[] = {
},
{
.procname = "watchdog_thresh",
.data = &watchdog_thresh,
.data = &watchdog_thresh_next,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_watchdog_thresh,