• Ulrich Obergfell's avatar
    watchdog: introduce watchdog_park_threads() and watchdog_unpark_threads() · 81a4beef
    Ulrich Obergfell authored
    Originally watchdog_nmi_enable(cpu) and watchdog_nmi_disable(cpu) were
    only called in watchdog thread context.  However, the following commits
    utilize these functions outside of watchdog thread context too.
    
      commit 9809b18f
      Author: Michal Hocko <mhocko@suse.cz>
      Date:   Tue Sep 24 15:27:30 2013 -0700
    
          watchdog: update watchdog_thresh properly
    
      commit b3738d29
      Author: Stephane Eranian <eranian@google.com>
      Date:   Mon Nov 17 20:07:03 2014 +0100
    
          watchdog: Add watchdog enable/disable all functions
    
    Hence, it is now possible that these functions execute concurrently with
    the same 'cpu' argument.  This concurrency is problematic because per-cpu
    'watchdog_ev' can be accessed/modified without adequate synchronization.
    
    The patch series aims to address the above problem.  However, instead of
    introducing locks to protect per-cpu 'watchdog_ev' a different approach is
    taken: Invoke these functions by parking and unparking the watchdog
    threads (to ensure they are always called in watchdog thread context).
    
      static struct smp_hotplug_thread watchdog_threads = {
               ...
              .park   = watchdog_disable, // calls watchdog_nmi_disable()
              .unpark = watchdog_enable,  // calls watchdog_nmi_enable()
      };
    
    Both previously mentioned commits call these functions in a similar way
    and thus in principle contain some duplicate code.  The patch series also
    avoids this duplication by providing a commonly usable mechanism.
    
    - Patch 1/4 introduces the watchdog_{park|unpark}_threads functions that
      park/unpark all watchdog threads specified in 'watchdog_cpumask'. They
      are intended to be called inside of kernel/watchdog.c only.
    
    - Patch 2/4 introduces the watchdog_{suspend|resume} functions which can
      be utilized by external callers to deactivate the hard and soft lockup
      detector temporarily.
    
    - Patch 3/4 utilizes watchdog_{park|unpark}_threads to replace some code
      that was introduced by commit 9809b18f.
    
    - Patch 4/4 utilizes watchdog_{suspend|resume} to replace some code that
      was introduced by commit b3738d29.
    
    A few corner cases should be mentioned here for completeness.
    
    - kthread_park() of watchdog/N could hang if cpu N is already locked up.
      However, if watchdog is enabled the lockup will be detected anyway.
    
    - kthread_unpark() of watchdog/N could hang if cpu N got locked up after
      kthread_park(). The occurrence of this scenario should be _very_ rare
      in practice, in particular because it is not expected that temporary
      deactivation will happen frequently, and if it happens at all it is
      expected that the duration of deactivation will be short.
    
    This patch (of 4): introduce watchdog_park_threads() and watchdog_unpark_threads()
    
    These functions are intended to be used only from inside kernel/watchdog.c
    to park/unpark all watchdog threads that are specified in
    watchdog_cpumask.
    Signed-off-by: default avatarUlrich Obergfell <uobergfe@redhat.com>
    Reviewed-by: default avatarAaron Tomlin <atomlin@redhat.com>
    Cc: Guenter Roeck <linux@roeck-us.net>
    Cc: Don Zickus <dzickus@redhat.com>
    Cc: Ulrich Obergfell <uobergfe@redhat.com>
    Cc: Jiri Olsa <jolsa@kernel.org>
    Cc: Michal Hocko <mhocko@suse.cz>
    Cc: Stephane Eranian <eranian@google.com>
    Cc: Chris Metcalf <cmetcalf@ezchip.com>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: Ingo Molnar <mingo@redhat.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    81a4beef
watchdog.c 26.4 KB