Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756111Ab0GVGOK (ORCPT ); Thu, 22 Jul 2010 02:14:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42745 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751883Ab0GVGOG (ORCPT ); Thu, 22 Jul 2010 02:14:06 -0400 Date: Thu, 22 Jul 2010 02:13:55 -0400 From: Amerigo Wang To: linux-kernel@vger.kernel.org Cc: nhorman@redhat.com, akpm@linux-foundation.org, Amerigo Wang , ebiederm@xmission.com Message-Id: <20100722061810.5659.87609.sendpatchset@localhost.localdomain> Subject: [Patch] kexec: increase max of kexec segments and use dynamic allocation Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3786 Lines: 128 Currently KEXEC_SEGMENT_MAX is only 16 which is too small for machine with many memory ranges. Increase this hard limit to 1024 which is reasonably large, and change ->segment from a static array to a dynamically allocated memory. Cc: nhorman@redhat.com Cc: ebiederm@xmission.com Signed-off-by: WANG Cong --- diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index ed31a29..f115585 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -131,10 +131,7 @@ static void copy_segments(unsigned long ind) void kexec_copy_flush(struct kimage *image) { long i, nr_segments = image->nr_segments; - struct kexec_segment ranges[KEXEC_SEGMENT_MAX]; - - /* save the ranges on the stack to efficiently flush the icache */ - memcpy(ranges, image->segment, sizeof(ranges)); + struct kexec_segment range; /* * After this call we may not use anything allocated in dynamic @@ -148,9 +145,11 @@ void kexec_copy_flush(struct kimage *image) * we need to clear the icache for all dest pages sometime, * including ones that were in place on the original copy */ - for (i = 0; i < nr_segments; i++) - flush_icache_range((unsigned long)__va(ranges[i].mem), - (unsigned long)__va(ranges[i].mem + ranges[i].memsz)); + for (i = 0; i < nr_segments; i++) { + memcpy(&range, &image->segment[i], sizeof(range)); + flush_icache_range((unsigned long)__va(range.mem), + (unsigned long)__va(range.mem + range.memsz)); + } } #ifdef CONFIG_SMP diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 03e8e8d..26b70ff 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -57,7 +57,7 @@ typedef unsigned long kimage_entry_t; #define IND_DONE 0x4 #define IND_SOURCE 0x8 -#define KEXEC_SEGMENT_MAX 16 +#define KEXEC_SEGMENT_MAX 1024 struct kexec_segment { void __user *buf; size_t bufsz; @@ -86,7 +86,7 @@ struct kimage { struct page *swap_page; unsigned long nr_segments; - struct kexec_segment segment[KEXEC_SEGMENT_MAX]; + struct kexec_segment *segment; struct list_head control_pages; struct list_head dest_pages; diff --git a/kernel/kexec.c b/kernel/kexec.c index 131b170..3f97309 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -131,6 +131,11 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, if (!image) goto out; + image->segment = kzalloc(nr_segments * sizeof(struct kexec_segment), + GFP_KERNEL); + if (!image->segment) + goto out; + image->head = 0; image->entry = &image->head; image->last_entry = &image->head; @@ -216,8 +221,10 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, out: if (result == 0) *rimage = image; - else + else if (image) { + kfree(image->segment); kfree(image); + } return result; @@ -261,8 +268,10 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, out: if (result == 0) *rimage = image; - else + else if (image) { + kfree(image->segment); kfree(image); + } return result; } @@ -330,8 +339,10 @@ static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry, out: if (result == 0) *rimage = image; - else + else if (image) { + kfree(image->segment); kfree(image); + } return result; } @@ -656,6 +667,7 @@ static void kimage_free(struct kimage *image) /* Free the kexec control pages... */ kimage_free_page_list(&image->control_pages); + kfree(image->segment); kfree(image); } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/