Пример #1
0
static int lcw_dispatch_main(void *data)
{
        int                 rc = 0;
        unsigned long       flags;
        struct lc_watchdog *lcw;
        CFS_LIST_HEAD      (zombies);

        ENTRY;

        cfs_daemonize("lc_watchdogd");

        SIGNAL_MASK_LOCK(current, flags);
        sigfillset(&current->blocked);
        RECALC_SIGPENDING;
        SIGNAL_MASK_UNLOCK(current, flags);

        cfs_complete(&lcw_start_completion);

        while (1) {
                int dumplog = 1;

                cfs_wait_event_interruptible(lcw_event_waitq,
                                             is_watchdog_fired(), rc);
                CDEBUG(D_INFO, "Watchdog got woken up...\n");
                if (cfs_test_bit(LCW_FLAG_STOP, &lcw_flags)) {
                        CDEBUG(D_INFO, "LCW_FLAG_STOP was set, shutting down...\n");

                        cfs_spin_lock_bh(&lcw_pending_timers_lock);
                        rc = !cfs_list_empty(&lcw_pending_timers);
                        cfs_spin_unlock_bh(&lcw_pending_timers_lock);
                        if (rc) {
                                CERROR("pending timers list was not empty at "
                                       "time of watchdog dispatch shutdown\n");
                        }
                        break;
                }

                cfs_spin_lock_bh(&lcw_pending_timers_lock);
                while (!cfs_list_empty(&lcw_pending_timers)) {
                        int is_dumplog;

                        lcw = cfs_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++;
                        cfs_spin_unlock_bh(&lcw_pending_timers_lock);

                        /* lock ordering */
                        cfs_spin_lock_bh(&lcw->lcw_lock);
                        cfs_spin_lock_bh(&lcw_pending_timers_lock);

                        if (cfs_list_empty(&lcw->lcw_list)) {
                                /* already removed from pending list */
                                lcw->lcw_refcount--; /* -1 ref for callback */
                                if (lcw->lcw_refcount == 0)
                                        cfs_list_add(&lcw->lcw_list, &zombies);
                                cfs_spin_unlock_bh(&lcw->lcw_lock);
                                /* still hold lcw_pending_timers_lock */
                                continue;
                        }

                        cfs_list_del_init(&lcw->lcw_list);
                        lcw->lcw_refcount--; /* -1 ref for pending list */

                        cfs_spin_unlock_bh(&lcw_pending_timers_lock);
                        cfs_spin_unlock_bh(&lcw->lcw_lock);

                        CDEBUG(D_INFO, "found lcw for pid " LPPID "\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)) {
                                lcw->lcw_callback(lcw->lcw_pid, lcw->lcw_data);
                                if (dumplog && is_dumplog)
                                        dumplog = 0;
                        }

                        cfs_spin_lock_bh(&lcw_pending_timers_lock);
                        lcw->lcw_refcount--; /* -1 ref for callback */
                        if (lcw->lcw_refcount == 0)
                                cfs_list_add(&lcw->lcw_list, &zombies);
                }
                cfs_spin_unlock_bh(&lcw_pending_timers_lock);

                while (!cfs_list_empty(&zombies)) {
                        lcw = cfs_list_entry(lcw_pending_timers.next,
                                         struct lc_watchdog, lcw_list);
                        cfs_list_del(&lcw->lcw_list);
                        LIBCFS_FREE(lcw, sizeof(*lcw));
                }
        }

        cfs_complete(&lcw_stop_completion);

        RETURN(rc);
}
Пример #2
0
static int lcw_dispatch_main(void *data)
{
        int                 rc = 0;
        struct lc_watchdog *lcw;
	struct list_head zombies = LIST_HEAD_INIT(zombies);

        ENTRY;

	complete(&lcw_start_completion);

        while (1) {
                int dumplog = 1;

		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 " LPPID "\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)) {
                                lcw->lcw_callback(lcw->lcw_pid, lcw->lcw_data);
                                if (dumplog && is_dumplog)
                                        dumplog = 0;
                        }

			spin_lock_bh(&lcw_pending_timers_lock);
			lcw->lcw_refcount--; /* -1 ref for callback */
			if (lcw->lcw_refcount == 0)
				list_add(&lcw->lcw_list, &zombies);
		}
		spin_unlock_bh(&lcw_pending_timers_lock);

		while (!list_empty(&zombies)) {
			lcw = list_entry(zombies.next,
					     struct lc_watchdog, lcw_list);
			list_del_init(&lcw->lcw_list);
			LIBCFS_FREE(lcw, sizeof(*lcw));
		}
	}

	complete(&lcw_stop_completion);

	RETURN(rc);
}