mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +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, | int crash_exclude_mem_range(struct crash_mem *mem, | ||||||
| 			    unsigned long long mstart, unsigned long long mend) | 			    unsigned long long mstart, unsigned long long mend) | ||||||
| { | { | ||||||
| 	int i, j; | 	int i; | ||||||
| 	unsigned long long start, end, p_start, p_end; | 	unsigned long long start, end, p_start, p_end; | ||||||
| 	struct range temp_range = {0, 0}; |  | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < mem->nr_ranges; i++) { | 	for (i = 0; i < mem->nr_ranges; i++) { | ||||||
| 		start = mem->ranges[i].start; | 		start = mem->ranges[i].start; | ||||||
|  | @ -576,72 +575,51 @@ int crash_exclude_mem_range(struct crash_mem *mem, | ||||||
| 		p_start = mstart; | 		p_start = mstart; | ||||||
| 		p_end = mend; | 		p_end = mend; | ||||||
| 
 | 
 | ||||||
| 		if (mstart > end || mend < start) | 		if (p_start > end) | ||||||
| 			continue; | 			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 */ | 		/* Truncate any area outside of range */ | ||||||
| 		if (mstart < start) | 		if (p_start < start) | ||||||
| 			p_start = start; | 			p_start = start; | ||||||
| 		if (mend > end) | 		if (p_end > end) | ||||||
| 			p_end = end; | 			p_end = end; | ||||||
| 
 | 
 | ||||||
| 		/* Found completely overlapping range */ | 		/* Found completely overlapping range */ | ||||||
| 		if (p_start == start && p_end == end) { | 		if (p_start == start && p_end == end) { | ||||||
| 			mem->ranges[i].start = 0; | 			memmove(&mem->ranges[i], &mem->ranges[i + 1], | ||||||
| 			mem->ranges[i].end = 0; | 				(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i])); | ||||||
| 			if (i < mem->nr_ranges - 1) { | 			i--; | ||||||
| 				/* 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. |  | ||||||
| 				 */ |  | ||||||
| 				i--; |  | ||||||
| 				mem->nr_ranges--; |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 			mem->nr_ranges--; | 			mem->nr_ranges--; | ||||||
| 			return 0; | 		} else if (p_start > start && p_end < end) { | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (p_start > start && p_end < end) { |  | ||||||
| 			/* Split original range */ | 			/* 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; | 			mem->ranges[i].end = p_start - 1; | ||||||
| 			temp_range.start = p_end + 1; | 			mem->ranges[i + 1].start = p_end + 1; | ||||||
| 			temp_range.end = end; | 			mem->ranges[i + 1].end = end; | ||||||
|  | 
 | ||||||
|  | 			i++; | ||||||
|  | 			mem->nr_ranges++; | ||||||
| 		} else if (p_start != start) | 		} else if (p_start != start) | ||||||
| 			mem->ranges[i].end = p_start - 1; | 			mem->ranges[i].end = p_start - 1; | ||||||
| 		else | 		else | ||||||
| 			mem->ranges[i].start = p_end + 1; | 			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; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Yuntao Wang
						Yuntao Wang