+ rc = wait_event_interruptible(lcw_event_waitq,
+ is_watchdog_fired());
+ CDEBUG(D_INFO, "Watchdog got woken up...\n");
+ if (test_bit(LCW_FLAG_STOP, &lcw_flags)) {
+ CDEBUG(D_INFO, "LCW_FLAG_STOP set, shutting down...\n");
+
+ spin_lock_bh(&lcw_pending_timers_lock);
+ rc = !list_empty(&lcw_pending_timers);
+ spin_unlock_bh(&lcw_pending_timers_lock);
+ if (rc) {
+ CERROR("pending timers list was not empty at "
+ "time of watchdog dispatch shutdown\n");
+ }
+ break;
+ }
+
+ spin_lock_bh(&lcw_pending_timers_lock);
+ while (!list_empty(&lcw_pending_timers)) {
+ int is_dumplog;
+
+ lcw = list_entry(lcw_pending_timers.next,
+ struct lc_watchdog, lcw_list);
+ /* +1 ref for callback to make sure lwc wouldn't be
+ * deleted after releasing lcw_pending_timers_lock */
+ lcw->lcw_refcount++;
+ spin_unlock_bh(&lcw_pending_timers_lock);
+
+ /* lock ordering */
+ spin_lock_bh(&lcw->lcw_lock);
+ spin_lock_bh(&lcw_pending_timers_lock);
+
+ if (list_empty(&lcw->lcw_list)) {
+ /* already removed from pending list */
+ lcw->lcw_refcount--; /* -1 ref for callback */
+ if (lcw->lcw_refcount == 0)
+ list_add(&lcw->lcw_list, &zombies);
+ spin_unlock_bh(&lcw->lcw_lock);
+ /* still hold lcw_pending_timers_lock */
+ continue;
+ }
+
+ list_del_init(&lcw->lcw_list);
+ lcw->lcw_refcount--; /* -1 ref for pending list */
+
+ spin_unlock_bh(&lcw_pending_timers_lock);
+ spin_unlock_bh(&lcw->lcw_lock);
+
+ CDEBUG(D_INFO, "found lcw for pid %d\n",
+ lcw->lcw_pid);
+ lcw_dump_stack(lcw);
+
+ is_dumplog = lcw->lcw_callback == lc_watchdog_dumplog;
+ if (lcw->lcw_state != LC_WATCHDOG_DISABLED &&
+ (dumplog || !is_dumplog)) {