mm_struct for exiting tasks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I'm Justin Vreeland, I'm currently and intern at Cray working with the OS/Kernel group. We use crash frequently to track down various problems and sometimes we need to get information about tasks that were exiting when the dump was taken. Because the mm_struct has been removed from the task struct. Crash doesn't let you use vtop or vm to do this so I added a way to specify mm_struct (with -M) for tasks whose stats is 'Exiting'.

Currently it's a bit hackish it modifies the tasks status and context to pass all the checks, and then restores both before returning. If this is something you're interested in it I'd be happy to bring it up to snuff. Modifications are attached.

--
-Justin

Index: memory.c
===================================================================
--- memory.c.orig
+++ memory.c
@@ -2819,7 +2819,7 @@ void
 cmd_vtop(void)
 {
 	int c;
-	ulong vaddr, context;
+	ulong vaddr, context, mm_struct_addr_new, mm_struct_addr_old;
 	int others;
 	ulong vtop_flags, loop_vtop_flags;
 	struct task_context *tc;
@@ -2827,7 +2827,7 @@ cmd_vtop(void)
 	vtop_flags = loop_vtop_flags = 0;
 	tc = NULL;
 
-        while ((c = getopt(argcnt, args, "ukc:")) != EOF) {
+	while ((c = getopt(argcnt, args, "ukc:M:")) != EOF) {
                 switch(c)
 		{
 		case 'c':
@@ -2853,6 +2853,11 @@ cmd_vtop(void)
 			vtop_flags |= KVADDR;
 			break;
 
+		case 'M':
+			vtop_flags |= MEMSTRUCTADDR;
+			mm_struct_addr_new = htol(optarg, FAULT_ON_ERROR, NULL);
+			break;
+
 		default:
 			argerrs++;
 			break;
@@ -2893,8 +2898,22 @@ cmd_vtop(void)
 		if (others++)
 			fprintf(fp, "\n");
 
+		if (vtop_flags & MEMSTRUCTADDR) {
+			if (!IS_EXITING(tc->task))
+				error(FATAL, "Provided task is not exiting\n");
+
+			mm_struct_addr_old = task_to_context(tc->task)->mm_struct;
+			task_to_context(tc->task)->mm_struct = mm_struct_addr_new;
+			ULONG(tt->task_struct + OFFSET(task_struct_flags)) &= !PF_EXITING;
+		}
+
 		do_vtop(vaddr, tc, vtop_flags | loop_vtop_flags);
 
+		if (vtop_flags & MEMSTRUCTADDR) {
+			task_to_context(tc->task)->mm_struct = mm_struct_addr_old;
+			ULONG(tt->task_struct + OFFSET(task_struct_flags)) |= PF_EXITING;
+		}
+
 		optind++;
 	}
 }
@@ -2957,6 +2976,8 @@ do_vtop(ulong vaddr, struct task_context
 			fprintf(fp, "%s  (not accessible)\n\n", 
 				mkstring(buf1, UVADDR_PRLEN, LJUST|LONG_HEX,
 				    MKSTR(vaddr)));
+			if (!(task_to_context(tc->mm_struct)))
+				fprintf(fp, "mm_struct is NULL\n");
 			return;
 		}
 		if (!uvtop(tc, vaddr, &paddr, 0)) {
@@ -2977,7 +2998,7 @@ do_vtop(ulong vaddr, struct task_context
 		}
 		uvtop(tc, vaddr, &paddr, VERBOSE);
 		fprintf(fp, "\n");
-		vma = vm_area_dump(tc->task, UVADDR, vaddr, 0);
+		vma = vm_area_dump(tc->task, UVADDR, vaddr, 0, 0);
 		if (!page_exists) { 
 			if (swap_location(paddr, buf1))
                        		fprintf(fp, "\nSWAP: %s\n", buf1);
@@ -3151,6 +3172,7 @@ cmd_vm(void)
 	ulong flag;
 	ulong value;
 	ulong single_vma;
+	ulong mm_provided;
 	ulonglong llvalue;
 	struct task_context *tc;
 	struct reference reference, *ref;
@@ -3159,11 +3181,12 @@ cmd_vm(void)
 
 	flag = 0;
 	single_vma = 0;
+	mm_provided = 0;
 	radix = 0;
 	ref = NULL;
 	BZERO(&reference, sizeof(struct reference));
 
-        while ((c = getopt(argcnt, args, "f:pmvR:P:xd")) != EOF) {
+	while ((c = getopt(argcnt, args, "f:pmvR:P:xdM:")) != EOF) {
                 switch(c)
 		{
 		case 'f':
@@ -3209,7 +3232,7 @@ cmd_vm(void)
 			break;
 
 		case 'P':
-			if (flag)
+			if (flag & PHYSADDR)
 				argerrs++;
 			else {
 				flag |= PRINT_SINGLE_VMA;
@@ -3231,6 +3254,13 @@ cmd_vm(void)
 			radix = 10;
 			break;
 
+		case 'M':
+			if (flag & PHYSADDR)
+				argerrs++;
+			else
+				mm_provided = htol(optarg, FAULT_ON_ERROR, NULL);
+			break;
+
 		default:
 			argerrs++;
 			break;
@@ -3248,7 +3278,15 @@ cmd_vm(void)
 	if (!args[optind]) {
 		if (!ref)
 			print_task_header(fp, CURRENT_CONTEXT(), 0);
-		vm_area_dump(CURRENT_TASK(), flag, single_vma, ref);
+		if (mm_provided) {
+			if (!IS_EXITING(CURRENT_CONTEXT()->task))
+				error(FATAL, "Provided task is not exiting\n");
+
+			ULONG(tt->task_struct + OFFSET(task_struct_flags)) &= !PF_EXITING;
+		}
+		vm_area_dump(CURRENT_TASK(), flag, single_vma, mm_provided, ref);
+		if (mm_provided)
+			ULONG(tt->task_struct + OFFSET(task_struct_flags)) |= PF_EXITING;
 		return;
 	}
 
@@ -3259,16 +3297,33 @@ cmd_vm(void)
 		{
 		case STR_PID:
 			for (tc = pid_to_context(value); tc; tc = tc->tc_next) {
-                                if (!ref)
-                                        print_task_header(fp, tc, subsequent++);
-                                vm_area_dump(tc->task, flag, single_vma, ref);
+				if (mm_provided) {
+					if (!IS_EXITING(tc->task))
+						error(FATAL, "Provided task is not exiting\n");
+					ULONG(tt->task_struct + OFFSET(task_struct_flags)) &= !PF_EXITING;
+				}
+
+				if (!ref)
+					print_task_header(fp, tc, subsequent++);
+
+				vm_area_dump(tc->task, flag, single_vma, mm_provided, ref);
+				if (mm_provided)
+					ULONG(tt->task_struct + OFFSET(task_struct_flags)) |= PF_EXITING;
                         }
 			break;
 
 		case STR_TASK:
 			if (!ref)
                                 print_task_header(fp, tc, subsequent++);
-                        vm_area_dump(tc->task, flag, single_vma, ref);
+			if (mm_provided) {
+				if (!IS_EXITING(tc->task))
+					error(FATAL, "Provided task is not exiting\n");
+				ULONG(tt->task_struct + OFFSET(task_struct_flags)) &= !PF_EXITING;
+			}
+                        vm_area_dump(tc->task, flag, single_vma, mm_provided, ref);
+			if (mm_provided) {
+				ULONG(tt->task_struct + OFFSET(task_struct_flags)) |= PF_EXITING;
+			}
 			break;
 
 		case STR_INVALID:
@@ -3523,13 +3578,14 @@ get_vm_flags(char *vma_buf)
 #define VM_REF_FOUND(X)    ((X) && ((X)->cmdflags & VM_REF_HEADER))
 
 ulong
-vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref)
+vm_area_dump(ulong task, ulong flag, ulong vaddr, ulong mm_addr, struct reference *ref)
 {
         struct task_context *tc;
 	ulong vma;
 	ulong vm_start;
 	ulong vm_end;
 	ulong vm_next, vm_mm;
+	ulong mm_struct_old;
 	char *dentry_buf, *vma_buf, *file_buf;
 	ulonglong vm_flags;
 	ulong vm_file, inode;
@@ -3547,6 +3603,10 @@ vm_area_dump(ulong task, ulong flag, ulo
 	char vma_header[BUFSIZE];
 
         tc = task_to_context(task);
+	if (mm_addr) {
+		mm_struct_old = tc->mm_struct;
+		tc->mm_struct = mm_addr;
+	}
 	tm = &task_mem_usage;
 	get_task_mem_usage(task, tm);
 
@@ -3580,6 +3640,8 @@ vm_area_dump(ulong task, ulong flag, ulo
         	print_task_header(fp, tc, 0);
 		PRINT_VM_DATA();
 		fprintf(fp, "\n");
+		if (mm_addr)
+			tc->mm_struct = mm_struct_old;
                 return (ulong)NULL;
         }
 
@@ -3587,11 +3649,16 @@ vm_area_dump(ulong task, ulong flag, ulo
 	    !DO_REF_SEARCH(ref)) 
 		PRINT_VM_DATA();
 
-        if (!tm->mm_struct_addr)
-                return (ulong)NULL;
+	if (!tm->mm_struct_addr) {
+		if (mm_addr)
+			tc->mm_struct = mm_struct_old;
+		return (ulong)NULL;
+	}
 
 	if (flag & PRINT_MM_STRUCT) {
 		dump_struct("mm_struct", tm->mm_struct_addr, radix);
+		if (mm_addr)
+			tc->mm_struct = mm_struct_old;
                 return (ulong)NULL;
 	}
 
@@ -3664,8 +3731,11 @@ vm_area_dump(ulong task, ulong flag, ulo
 		    ((vaddr >= vm_start) && (vaddr < vm_end)))) {
 			found = TRUE;
 
-			if (flag & VERIFY_ADDR)
+			if (flag & VERIFY_ADDR) {
+				if (mm_addr)
+					tc->mm_struct = mm_struct_old;
 				return vma;
+			}
 
 			if (DO_REF_SEARCH(ref)) {
 				if (VM_REF_CHECK_HEXVAL(ref, vma) ||
@@ -3726,11 +3796,17 @@ vm_area_dump(ulong task, ulong flag, ulo
 						vm_start, vm_end, vm_mm, ref);
 			}
 
-			if (flag & UVADDR)
+			if (flag & UVADDR) {
+				if (mm_addr)
+					tc->mm_struct = mm_struct_old;
 				return vma;
+			}
 		} 
 	}
 
+	if (mm_addr)
+		tc->mm_struct = mm_struct_old;
+
 	if (flag & VERIFY_ADDR)
 		return (ulong)NULL;
 
@@ -3940,7 +4016,7 @@ in_user_stack(ulong task, ulong vaddr)
 	ulonglong vm_flags;
 	char *vma_buf;
 
-	if ((vma = vm_area_dump(task, UVADDR|VERIFY_ADDR, vaddr, 0))) {
+	if ((vma = vm_area_dump(task, UVADDR|VERIFY_ADDR, vaddr, 0, 0))) {
 		vma_buf = fill_vma_cache(vma);
 		vm_flags = get_vm_flags(vma_buf);
 
Index: task.c
===================================================================
--- task.c.orig
+++ task.c
@@ -5870,19 +5870,19 @@ foreach(struct foreach_data *fd)
 					cmdflags = PRINT_RADIX_10;
 				if (fd->flags & FOREACH_i_FLAG)
 					vm_area_dump(tc->task, 
-					    PRINT_INODES, 0, NULL);
+					    PRINT_INODES, 0, 0, NULL);
 				else if (fd->flags & FOREACH_p_FLAG)
 					vm_area_dump(tc->task, 
-					    PHYSADDR, 0, 
+					    PHYSADDR, 0, 0,
 					    fd->reference ? ref : NULL);
 				else if (fd->flags & FOREACH_m_FLAG)
 					vm_area_dump(tc->task, 
-					    PRINT_MM_STRUCT|cmdflags, 0, NULL);
+					    PRINT_MM_STRUCT|cmdflags, 0, 0, NULL);
 				else if (fd->flags & FOREACH_v_FLAG)
 					vm_area_dump(tc->task, 
-					    PRINT_VMA_STRUCTS|cmdflags, 0, NULL);
+					    PRINT_VMA_STRUCTS|cmdflags, 0, 0, NULL);
 				else
-					vm_area_dump(tc->task, 0, 0, 
+					vm_area_dump(tc->task, 0, 0, 0,
 					    fd->reference ? ref : NULL);
 				break;
 
Index: defs.h
===================================================================
--- defs.h.orig
+++ defs.h
@@ -2501,6 +2501,7 @@ struct load_module {
 #define PHYSADDR           (0x4)
 #define XENMACHADDR        (0x8)
 #define FILEADDR          (0x10)
+#define MEMSTRUCTADDR     (0x20)
 #define AMBIGUOUS          (~0)
 
 #define USE_USER_PGD       (UVADDR << 2)
@@ -4449,8 +4450,8 @@ void do_vtop(ulong, struct task_context
 void raw_stack_dump(ulong, ulong);
 void raw_data_dump(ulong, long, int);
 int accessible(ulong);
-ulong vm_area_dump(ulong, ulong, ulong, struct reference *);
-#define IN_TASK_VMA(TASK,VA) (vm_area_dump((TASK), UVADDR|VERIFY_ADDR, (VA), 0))
+ulong vm_area_dump(ulong, ulong, ulong, ulong, struct reference *);
+#define IN_TASK_VMA(TASK,VA) (vm_area_dump((TASK), UVADDR|VERIFY_ADDR, (VA), 0, 0))
 char *fill_vma_cache(ulong);
 void clear_vma_cache(void);
 void dump_vma_cache(ulong);
Index: help.c
===================================================================
--- help.c.orig
+++ help.c
@@ -3490,7 +3490,7 @@ NULL
 char *help_vtop[] = {
 "vtop",
 "virtual to physical",
-"[-c [pid | taskp]] [-u|-k] address ...",
+"[-c [pid | taskp]] [-u|-k] [-M mm_addr] address ...",
 "  This command translates a user or kernel virtual address to its physical",
 "  address.  Also displayed is the PTE translation, the vm_area_struct data",
 "  for user virtual addresses, the mem_map page data associated with the",
@@ -3514,6 +3514,7 @@ char *help_vtop[] = {
 "                      the pid or taskp argument should NOT be entered; the",
 "                      address will be translated using the page directory of",
 "                      each task specified by \"foreach\".",
+"   -M mm_addr         Use mm_struct located at mm_addr.",
 "   address            A hexadecimal user or kernel virtual address.",
 "\nEXAMPLES",
 "  Translate user virtual address 80b4000:\n",
@@ -3595,7 +3596,7 @@ NULL
 char *help_vm[] = { 
 "vm",
 "virtual memory",
-"[-p | -P vmaddr | -v | -m | -x | -d | [-R reference] | [-f vm_flags]]"
+"[-p | -P vmaddr | -v | -m | [-M mm_addr] | -x | -d | [-R reference] | [-f vm_flags]]"
 "\n     [pid | taskp] ... ",
 "  This command displays basic virtual memory information of a context,",
 "  consisting of a pointer to its mm_struct and page dirctory, its RSS and ",
@@ -3616,6 +3617,7 @@ char *help_vm[] = {
 "                specified VM area of a context.",
 "  -R reference  search for references to this number or filename.",
 "            -m  dump the mm_struct assocated with the task.",
+"    -M mm_addr  use mm_struct located at mm_addr.",
 "            -v  dump all of the vm_area_structs associated with the task.",
 "            -x  override the default output format for the -m or -v options",
 "                with hexadecimal format.",
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux