rcu: Provide more diagnostics for stalled GP kthread
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Tue, 19 May 2015 21:16:52 +0000 (14:16 -0700)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Wed, 15 Jul 2015 21:45:10 +0000 (14:45 -0700)
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
kernel/rcu/tree.c
kernel/rcu/tree.h

index 65137bc28b2b363536a04c26049b6bace2b4b936..1c58cbd03922ac4323c273853c1e47e114c40bdd 100644 (file)
@@ -1178,9 +1178,11 @@ static void rcu_check_gp_kthread_starvation(struct rcu_state *rsp)
        j = jiffies;
        gpa = READ_ONCE(rsp->gp_activity);
        if (j - gpa > 2 * HZ)
-               pr_err("%s kthread starved for %ld jiffies! g%lu c%lu f%#x\n",
+               pr_err("%s kthread starved for %ld jiffies! g%lu c%lu f%#x s%d ->state=%#lx\n",
                       rsp->name, j - gpa,
-                      rsp->gpnum, rsp->completed, rsp->gp_flags);
+                      rsp->gpnum, rsp->completed,
+                      rsp->gp_flags, rsp->gp_state,
+                      rsp->gp_kthread ? rsp->gp_kthread->state : 0);
 }
 
 /*
@@ -2041,6 +2043,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
                        wait_event_interruptible(rsp->gp_wq,
                                                 READ_ONCE(rsp->gp_flags) &
                                                 RCU_GP_FLAG_INIT);
+                       rsp->gp_state = RCU_GP_DONE_GPS;
                        /* Locking provides needed memory barrier. */
                        if (rcu_gp_init(rsp))
                                break;
@@ -2073,6 +2076,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
                                        (!READ_ONCE(rnp->qsmask) &&
                                         !rcu_preempt_blocked_readers_cgp(rnp)),
                                        j);
+                       rsp->gp_state = RCU_GP_DONE_FQS;
                        /* Locking provides needed memory barriers. */
                        /* If grace period done, leave loop. */
                        if (!READ_ONCE(rnp->qsmask) &&
@@ -2110,7 +2114,9 @@ static int __noreturn rcu_gp_kthread(void *arg)
                }
 
                /* Handle grace-period end. */
+               rsp->gp_state = RCU_GP_CLEANUP;
                rcu_gp_cleanup(rsp);
+               rsp->gp_state = RCU_GP_CLEANED;
        }
 }
 
index 4adb7ca0bf47a209067c66205ace8b6f0dbebb61..f1f4784f91074d239a8578398f98b47cdf18e9e6 100644 (file)
@@ -527,7 +527,11 @@ struct rcu_state {
 /* Values for rcu_state structure's gp_flags field. */
 #define RCU_GP_WAIT_INIT 0     /* Initial state. */
 #define RCU_GP_WAIT_GPS  1     /* Wait for grace-period start. */
-#define RCU_GP_WAIT_FQS  2     /* Wait for force-quiescent-state time. */
+#define RCU_GP_DONE_GPS  2     /* Wait done for grace-period start. */
+#define RCU_GP_WAIT_FQS  3     /* Wait for force-quiescent-state time. */
+#define RCU_GP_DONE_FQS  4     /* Wait done for force-quiescent-state time. */
+#define RCU_GP_CLEANUP   5     /* Grace-period cleanup started. */
+#define RCU_GP_CLEANED   6     /* Grace-period cleanup complete. */
 
 extern struct list_head rcu_struct_flavors;