kexec: use common function for kimage_normal_alloc() and kimage_crash_alloc()
kimage_normal_alloc() and kimage_crash_alloc() are doing lot of similar things and differ only little. So instead of having two separate functions create a common function kimage_alloc_init() and pass it the "flags" argument which tells whether it is normal kexec or kexec_on_panic. And this function should be able to deal with both the cases. This consolidation also helps later where we can use a common function kimage_file_alloc_init() to handle normal and crash cases for new file based kexec syscall. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Cc: Borislav Petkov <bp@suse.de> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Eric Biederman <ebiederm@xmission.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Cc: Greg Kroah-Hartman <greg@kroah.com> Cc: Dave Young <dyoung@redhat.com> Cc: WANG Chao <chaowang@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
dabe78628d
commit
255aedd90e
105
kernel/kexec.c
105
kernel/kexec.c
|
@ -261,12 +261,20 @@ static struct kimage *do_kimage_alloc_init(void)
|
|||
|
||||
static void kimage_free_page_list(struct list_head *list);
|
||||
|
||||
static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
|
||||
unsigned long nr_segments,
|
||||
struct kexec_segment __user *segments)
|
||||
static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
|
||||
unsigned long nr_segments,
|
||||
struct kexec_segment __user *segments,
|
||||
unsigned long flags)
|
||||
{
|
||||
int result;
|
||||
int ret;
|
||||
struct kimage *image;
|
||||
bool kexec_on_panic = flags & KEXEC_ON_CRASH;
|
||||
|
||||
if (kexec_on_panic) {
|
||||
/* Verify we have a valid entry point */
|
||||
if ((entry < crashk_res.start) || (entry > crashk_res.end))
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
/* Allocate and initialize a controlling structure */
|
||||
image = do_kimage_alloc_init();
|
||||
|
@ -275,20 +283,26 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
|
|||
|
||||
image->start = entry;
|
||||
|
||||
result = copy_user_segment_list(image, nr_segments, segments);
|
||||
if (result)
|
||||
ret = copy_user_segment_list(image, nr_segments, segments);
|
||||
if (ret)
|
||||
goto out_free_image;
|
||||
|
||||
result = sanity_check_segment_list(image);
|
||||
if (result)
|
||||
ret = sanity_check_segment_list(image);
|
||||
if (ret)
|
||||
goto out_free_image;
|
||||
|
||||
/* Enable the special crash kernel control page allocation policy. */
|
||||
if (kexec_on_panic) {
|
||||
image->control_page = crashk_res.start;
|
||||
image->type = KEXEC_TYPE_CRASH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a location for the control code buffer, and add it
|
||||
* the vector of segments so that it's pages will also be
|
||||
* counted as destination pages.
|
||||
*/
|
||||
result = -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
image->control_code_page = kimage_alloc_control_pages(image,
|
||||
get_order(KEXEC_CONTROL_PAGE_SIZE));
|
||||
if (!image->control_code_page) {
|
||||
|
@ -296,10 +310,12 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
|
|||
goto out_free_image;
|
||||
}
|
||||
|
||||
image->swap_page = kimage_alloc_control_pages(image, 0);
|
||||
if (!image->swap_page) {
|
||||
pr_err("Could not allocate swap buffer\n");
|
||||
goto out_free_control_pages;
|
||||
if (!kexec_on_panic) {
|
||||
image->swap_page = kimage_alloc_control_pages(image, 0);
|
||||
if (!image->swap_page) {
|
||||
pr_err("Could not allocate swap buffer\n");
|
||||
goto out_free_control_pages;
|
||||
}
|
||||
}
|
||||
|
||||
*rimage = image;
|
||||
|
@ -308,60 +324,7 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
|
|||
kimage_free_page_list(&image->control_pages);
|
||||
out_free_image:
|
||||
kfree(image);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry,
|
||||
unsigned long nr_segments,
|
||||
struct kexec_segment __user *segments)
|
||||
{
|
||||
int result;
|
||||
struct kimage *image;
|
||||
|
||||
/* Verify we have a valid entry point */
|
||||
if ((entry < crashk_res.start) || (entry > crashk_res.end))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
/* Allocate and initialize a controlling structure */
|
||||
image = do_kimage_alloc_init();
|
||||
if (!image)
|
||||
return -ENOMEM;
|
||||
|
||||
image->start = entry;
|
||||
|
||||
/* Enable the special crash kernel control page
|
||||
* allocation policy.
|
||||
*/
|
||||
image->control_page = crashk_res.start;
|
||||
image->type = KEXEC_TYPE_CRASH;
|
||||
|
||||
result = copy_user_segment_list(image, nr_segments, segments);
|
||||
if (result)
|
||||
goto out_free_image;
|
||||
|
||||
result = sanity_check_segment_list(image);
|
||||
if (result)
|
||||
goto out_free_image;
|
||||
|
||||
/*
|
||||
* Find a location for the control code buffer, and add
|
||||
* the vector of segments so that it's pages will also be
|
||||
* counted as destination pages.
|
||||
*/
|
||||
result = -ENOMEM;
|
||||
image->control_code_page = kimage_alloc_control_pages(image,
|
||||
get_order(KEXEC_CONTROL_PAGE_SIZE));
|
||||
if (!image->control_code_page) {
|
||||
pr_err("Could not allocate control_code_buffer\n");
|
||||
goto out_free_image;
|
||||
}
|
||||
|
||||
*rimage = image;
|
||||
return 0;
|
||||
|
||||
out_free_image:
|
||||
kfree(image);
|
||||
return result;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kimage_is_destination_range(struct kimage *image,
|
||||
|
@ -1004,16 +967,16 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
|
|||
|
||||
/* Loading another kernel to reboot into */
|
||||
if ((flags & KEXEC_ON_CRASH) == 0)
|
||||
result = kimage_normal_alloc(&image, entry,
|
||||
nr_segments, segments);
|
||||
result = kimage_alloc_init(&image, entry, nr_segments,
|
||||
segments, flags);
|
||||
/* Loading another kernel to switch to if this one crashes */
|
||||
else if (flags & KEXEC_ON_CRASH) {
|
||||
/* Free any current crash dump kernel before
|
||||
* we corrupt it.
|
||||
*/
|
||||
kimage_free(xchg(&kexec_crash_image, NULL));
|
||||
result = kimage_crash_alloc(&image, entry,
|
||||
nr_segments, segments);
|
||||
result = kimage_alloc_init(&image, entry, nr_segments,
|
||||
segments, flags);
|
||||
crash_map_reserved_pages();
|
||||
}
|
||||
if (result)
|
||||
|
|
Loading…
Reference in New Issue
Block a user