mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 00:28:52 +02:00 
			
		
		
		
	crash_core: fix and simplify the logic of crash_exclude_mem_range()
The purpose of crash_exclude_mem_range() is to remove all memory ranges
that overlap with [mstart-mend].  However, the current logic only removes
the first overlapping memory range.
Commit a2e9a95d21 ("kexec: Improve & fix crash_exclude_mem_range() to
handle overlapping ranges") attempted to address this issue, but it did
not fix all error cases.
Let's fix and simplify the logic of crash_exclude_mem_range().
Link: https://lkml.kernel.org/r/20240102144905.110047-4-ytcoode@gmail.com
Signed-off-by: Yuntao Wang <ytcoode@gmail.com>
Acked-by: Baoquan He <bhe@redhat.com>
Cc: Borislav Petkov (AMD) <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Sourabh Jain <sourabhjain@linux.ibm.com>
Cc: Takashi Iwai <tiwai@suse.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
			
			
This commit is contained in:
		
							parent
							
								
									61bb219f9d
								
							
						
					
					
						commit
						6dff315972
					
				
					 1 changed files with 29 additions and 51 deletions
				
			
		|  | @ -566,9 +566,8 @@ int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map, | |||
| int crash_exclude_mem_range(struct crash_mem *mem, | ||||
| 			    unsigned long long mstart, unsigned long long mend) | ||||
| { | ||||
| 	int i, j; | ||||
| 	int i; | ||||
| 	unsigned long long start, end, p_start, p_end; | ||||
| 	struct range temp_range = {0, 0}; | ||||
| 
 | ||||
| 	for (i = 0; i < mem->nr_ranges; i++) { | ||||
| 		start = mem->ranges[i].start; | ||||
|  | @ -576,72 +575,51 @@ int crash_exclude_mem_range(struct crash_mem *mem, | |||
| 		p_start = mstart; | ||||
| 		p_end = mend; | ||||
| 
 | ||||
| 		if (mstart > end || mend < start) | ||||
| 		if (p_start > end) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Because the memory ranges in mem->ranges are stored in | ||||
| 		 * ascending order, when we detect `p_end < start`, we can | ||||
| 		 * immediately exit the for loop, as the subsequent memory | ||||
| 		 * ranges will definitely be outside the range we are looking | ||||
| 		 * for. | ||||
| 		 */ | ||||
| 		if (p_end < start) | ||||
| 			break; | ||||
| 
 | ||||
| 		/* Truncate any area outside of range */ | ||||
| 		if (mstart < start) | ||||
| 		if (p_start < start) | ||||
| 			p_start = start; | ||||
| 		if (mend > end) | ||||
| 		if (p_end > end) | ||||
| 			p_end = end; | ||||
| 
 | ||||
| 		/* Found completely overlapping range */ | ||||
| 		if (p_start == start && p_end == end) { | ||||
| 			mem->ranges[i].start = 0; | ||||
| 			mem->ranges[i].end = 0; | ||||
| 			if (i < mem->nr_ranges - 1) { | ||||
| 				/* Shift rest of the ranges to left */ | ||||
| 				for (j = i; j < mem->nr_ranges - 1; j++) { | ||||
| 					mem->ranges[j].start = | ||||
| 						mem->ranges[j+1].start; | ||||
| 					mem->ranges[j].end = | ||||
| 							mem->ranges[j+1].end; | ||||
| 				} | ||||
| 
 | ||||
| 				/*
 | ||||
| 				 * Continue to check if there are another overlapping ranges | ||||
| 				 * from the current position because of shifting the above | ||||
| 				 * mem ranges. | ||||
| 				 */ | ||||
| 			memmove(&mem->ranges[i], &mem->ranges[i + 1], | ||||
| 				(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i])); | ||||
| 			i--; | ||||
| 			mem->nr_ranges--; | ||||
| 				continue; | ||||
| 			} | ||||
| 			mem->nr_ranges--; | ||||
| 			return 0; | ||||
| 		} | ||||
| 
 | ||||
| 		if (p_start > start && p_end < end) { | ||||
| 		} else if (p_start > start && p_end < end) { | ||||
| 			/* Split original range */ | ||||
| 			if (mem->nr_ranges >= mem->max_nr_ranges) | ||||
| 				return -ENOMEM; | ||||
| 
 | ||||
| 			memmove(&mem->ranges[i + 2], &mem->ranges[i + 1], | ||||
| 				(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i])); | ||||
| 
 | ||||
| 			mem->ranges[i].end = p_start - 1; | ||||
| 			temp_range.start = p_end + 1; | ||||
| 			temp_range.end = end; | ||||
| 			mem->ranges[i + 1].start = p_end + 1; | ||||
| 			mem->ranges[i + 1].end = end; | ||||
| 
 | ||||
| 			i++; | ||||
| 			mem->nr_ranges++; | ||||
| 		} else if (p_start != start) | ||||
| 			mem->ranges[i].end = p_start - 1; | ||||
| 		else | ||||
| 			mem->ranges[i].start = p_end + 1; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	/* If a split happened, add the split to array */ | ||||
| 	if (!temp_range.end) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* Split happened */ | ||||
| 	if (i == mem->max_nr_ranges - 1) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	/* Location where new range should go */ | ||||
| 	j = i + 1; | ||||
| 	if (j < mem->nr_ranges) { | ||||
| 		/* Move over all ranges one slot towards the end */ | ||||
| 		for (i = mem->nr_ranges - 1; i >= j; i--) | ||||
| 			mem->ranges[i + 1] = mem->ranges[i]; | ||||
| 	} | ||||
| 
 | ||||
| 	mem->ranges[j].start = temp_range.start; | ||||
| 	mem->ranges[j].end = temp_range.end; | ||||
| 	mem->nr_ranges++; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Yuntao Wang
						Yuntao Wang