Skip to content

Commit 6dff315

Browse files
ytcoodeakpm00
authored andcommitted
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 a2e9a95 ("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>
1 parent 61bb219 commit 6dff315

File tree

1 file changed

+29
-51
lines changed

1 file changed

+29
-51
lines changed

kernel/crash_core.c

Lines changed: 29 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -566,82 +566,60 @@ int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map,
566566
int crash_exclude_mem_range(struct crash_mem *mem,
567567
unsigned long long mstart, unsigned long long mend)
568568
{
569-
int i, j;
569+
int i;
570570
unsigned long long start, end, p_start, p_end;
571-
struct range temp_range = {0, 0};
572571

573572
for (i = 0; i < mem->nr_ranges; i++) {
574573
start = mem->ranges[i].start;
575574
end = mem->ranges[i].end;
576575
p_start = mstart;
577576
p_end = mend;
578577

579-
if (mstart > end || mend < start)
578+
if (p_start > end)
580579
continue;
581580

581+
/*
582+
* Because the memory ranges in mem->ranges are stored in
583+
* ascending order, when we detect `p_end < start`, we can
584+
* immediately exit the for loop, as the subsequent memory
585+
* ranges will definitely be outside the range we are looking
586+
* for.
587+
*/
588+
if (p_end < start)
589+
break;
590+
582591
/* Truncate any area outside of range */
583-
if (mstart < start)
592+
if (p_start < start)
584593
p_start = start;
585-
if (mend > end)
594+
if (p_end > end)
586595
p_end = end;
587596

588597
/* Found completely overlapping range */
589598
if (p_start == start && p_end == end) {
590-
mem->ranges[i].start = 0;
591-
mem->ranges[i].end = 0;
592-
if (i < mem->nr_ranges - 1) {
593-
/* Shift rest of the ranges to left */
594-
for (j = i; j < mem->nr_ranges - 1; j++) {
595-
mem->ranges[j].start =
596-
mem->ranges[j+1].start;
597-
mem->ranges[j].end =
598-
mem->ranges[j+1].end;
599-
}
600-
601-
/*
602-
* Continue to check if there are another overlapping ranges
603-
* from the current position because of shifting the above
604-
* mem ranges.
605-
*/
606-
i--;
607-
mem->nr_ranges--;
608-
continue;
609-
}
599+
memmove(&mem->ranges[i], &mem->ranges[i + 1],
600+
(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i]));
601+
i--;
610602
mem->nr_ranges--;
611-
return 0;
612-
}
613-
614-
if (p_start > start && p_end < end) {
603+
} else if (p_start > start && p_end < end) {
615604
/* Split original range */
605+
if (mem->nr_ranges >= mem->max_nr_ranges)
606+
return -ENOMEM;
607+
608+
memmove(&mem->ranges[i + 2], &mem->ranges[i + 1],
609+
(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i]));
610+
616611
mem->ranges[i].end = p_start - 1;
617-
temp_range.start = p_end + 1;
618-
temp_range.end = end;
612+
mem->ranges[i + 1].start = p_end + 1;
613+
mem->ranges[i + 1].end = end;
614+
615+
i++;
616+
mem->nr_ranges++;
619617
} else if (p_start != start)
620618
mem->ranges[i].end = p_start - 1;
621619
else
622620
mem->ranges[i].start = p_end + 1;
623-
break;
624-
}
625-
626-
/* If a split happened, add the split to array */
627-
if (!temp_range.end)
628-
return 0;
629-
630-
/* Split happened */
631-
if (i == mem->max_nr_ranges - 1)
632-
return -ENOMEM;
633-
634-
/* Location where new range should go */
635-
j = i + 1;
636-
if (j < mem->nr_ranges) {
637-
/* Move over all ranges one slot towards the end */
638-
for (i = mem->nr_ranges - 1; i >= j; i--)
639-
mem->ranges[i + 1] = mem->ranges[i];
640621
}
641622

642-
mem->ranges[j].start = temp_range.start;
643-
mem->ranges[j].end = temp_range.end;
644-
mem->nr_ranges++;
645623
return 0;
646624
}
647625

0 commit comments

Comments
 (0)