From: Dave Anderson <anderson@redhat.com>
Subject: Display tasks on a priority array of a CPU's RT runqueue
References: bnc#826507

Fix for the "runq" command for kernels that have the CFS scheduler.
Without the patch, tasks queued on a priority array of a cpu's RT
runqueue may not be displayed.

Signed-off-by: Dave Anderson <anderson@redhat.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>

---
 defs.h    |    4 ++++
 symbols.c |   10 ++++++++++
 task.c    |   19 ++++++++++++++-----
 3 files changed, 28 insertions(+), 5 deletions(-)

--- a/task.c
+++ b/task.c
@@ -7576,6 +7576,10 @@ dump_CFS_runqueues(void)
 		MEMBER_OFFSET_INIT(task_struct_on_rq, "task_struct", "on_rq");
                 MEMBER_OFFSET_INIT(task_struct_prio, "task_struct",
                         "prio");
+		MEMBER_OFFSET_INIT(task_struct_rt, "task_struct", "rt");
+		MEMBER_OFFSET_INIT(sched_rt_entity_run_list, "sched_rt_entity", 
+			"run_list");
+		MEMBER_OFFSET_INIT(rt_prio_array_queue, "rt_prio_array", "queue");
 	}
 
 	if (!(rq_sp = per_cpu_symbol_search("per_cpu__runqueues")))
@@ -7671,19 +7675,19 @@ dump_RT_prio_array(int active, ulong k_p
 		return;
 	}
 
-        qheads = (i = ARRAY_LENGTH(prio_array_queue)) ?
-                i : get_array_length("prio_array.queue", NULL, SIZE(list_head));
+        qheads = (i = ARRAY_LENGTH(rt_prio_array_queue)) ?
+                i : get_array_length("rt_prio_array.queue", NULL, SIZE(list_head));
 
 	ld = &list_data;
 
 	for (i = tot = 0; i < qheads; i++) {
-		offset =  OFFSET(prio_array_queue) + (i * SIZE(list_head));
+		offset =  OFFSET(rt_prio_array_queue) + (i * SIZE(list_head));
 		kvaddr = k_prio_array + offset;
 		uvaddr = (ulong)u_prio_array + offset;
 		BCOPY((char *)uvaddr, (char *)&list_head[0], sizeof(ulong)*2);
 
 		if (CRASHDEBUG(1))
-			fprintf(fp, "prio_array[%d] @ %lx => %lx/%lx\n", 
+			fprintf(fp, "rt_prio_array[%d] @ %lx => %lx/%lx\n", 
 				i, kvaddr, list_head[0], list_head[1]);
 
 		if ((list_head[0] == kvaddr) && (list_head[1] == kvaddr))
@@ -7693,7 +7697,12 @@ dump_RT_prio_array(int active, ulong k_p
 
 		BZERO(ld, sizeof(struct list_data));
 		ld->start = list_head[0];
-		ld->list_head_offset = OFFSET(task_struct_run_list);
+		if (VALID_MEMBER(task_struct_rt) &&
+		    VALID_MEMBER(sched_rt_entity_run_list))
+			ld->list_head_offset = OFFSET(task_struct_rt) + 
+				OFFSET(sched_rt_entity_run_list);
+		else
+			ld->list_head_offset = OFFSET(task_struct_run_list);
 		ld->end = kvaddr;
 		hq_open();
 		cnt = do_list(ld);
--- a/symbols.c
+++ b/symbols.c
@@ -7237,6 +7237,8 @@ builtin_array_length(char *s, int len, i
 		lenptr = &array_table.kmem_cache_node;
 	else if (STREQ(s, "kmem_cache.cpu_slab"))
 		lenptr = &array_table.kmem_cache_cpu_slab;
+	else if (STREQ(s, "rt_prio_array.queue"))
+		lenptr = &array_table.rt_prio_array_queue;
 
 	if (!lenptr)                /* not stored */
 		return(len);        
@@ -7374,6 +7376,10 @@ dump_offset_table(char *spec, ulong make
                 OFFSET(task_struct_timestamp));
         fprintf(fp, "        task_struct_sched_info: %ld\n",
                 OFFSET(task_struct_sched_info));
+        fprintf(fp, "                task_struct_rt: %ld\n",
+                OFFSET(task_struct_rt));
+        fprintf(fp, "      sched_rt_entity_run_list: %ld\n",
+                OFFSET(sched_rt_entity_run_list));
 	fprintf(fp, "       sched_info_last_arrival: %ld\n",
                 OFFSET(sched_info_last_arrival));
         fprintf(fp, "       task_struct_thread_info: %ld\n",
@@ -8423,6 +8429,8 @@ dump_offset_table(char *spec, ulong make
 		OFFSET(cpu_s_curr));
 	fprintf(fp, "              prio_array_queue: %ld\n",
 		OFFSET(prio_array_queue));
+	fprintf(fp, "           rt_prio_array_queue: %ld\n",
+		OFFSET(rt_prio_array_queue));
 	fprintf(fp, "          prio_array_nr_active: %ld\n",
 		OFFSET(prio_array_nr_active));
 	fprintf(fp, "          user_regs_struct_ebp: %ld\n",
@@ -9040,6 +9048,8 @@ dump_offset_table(char *spec, ulong make
 		ARRAY_LENGTH(kmem_cache_node));
 	fprintf(fp, "           kmem_cache_cpu_slab: %d\n",
 		ARRAY_LENGTH(kmem_cache_cpu_slab));
+        fprintf(fp, "           rt_prio_array_queue: %d\n",
+                ARRAY_LENGTH(rt_prio_array_queue));
 
 	if (spec) {
 		int in_size_table, in_array_table, arrays, offsets, sizes;
--- a/defs.h
+++ b/defs.h
@@ -1759,6 +1759,9 @@ struct offset_table {
 	long msg_queue_q_qnum;
 	long super_block_s_fs_info;
 	long rq_timestamp;
+	long rt_prio_array_queue;
+	long task_struct_rt;
+	long sched_rt_entity_run_list;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
@@ -1920,6 +1923,7 @@ struct array_table {
 	int pid_hash;
 	int kmem_cache_node;
 	int kmem_cache_cpu_slab;
+	int rt_prio_array_queue;
 };
 
 /*
