* [PATCH] kexec: Make a pair of map/unmap reserved pages in error path
@ 2016-02-25 14:02 Minfei Huang
2016-02-27 0:56 ` Andrew Morton
0 siblings, 1 reply; 3+ messages in thread
From: Minfei Huang @ 2016-02-25 14:02 UTC (permalink / raw)
To: ebiederm, akpm; +Cc: kexec, linux-kernel, mhuang, Minfei Huang
From: Minfei Huang <mnfhuang@gmail.com>
For some arch, kexec shall map the reserved pages, then use them, when
we try to start the kdump service.
kexec may return directly, without unmaping the reserved pages, if it
fails during starting service. To fix it, we make a pair of map/unmap
reserved pages both in generic path and error path.
Signed-off-by: Minfei Huang <mnfhuang@gmail.com>
---
kernel/kexec.c | 112 ++++++++++++++++++++++++++++++++-------------------------
1 file changed, 63 insertions(+), 49 deletions(-)
diff --git a/kernel/kexec.c b/kernel/kexec.c
index ee70aef..48cf69c 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -103,6 +103,68 @@ out_free_image:
return ret;
}
+static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
+ struct kexec_segment __user *segments, unsigned long flags)
+{
+ struct kimage **dest_image, *image;
+ unsigned long i;
+ int ret;
+
+ if (flags & KEXEC_ON_CRASH)
+ dest_image = &kexec_crash_image;
+ else
+ dest_image = &kexec_image;
+
+ if (nr_segments == 0) {
+ /* Uninstall image */
+ kimage_free(xchg(dest_image, NULL));
+ return 0;
+ }
+ if (flags & KEXEC_ON_CRASH) {
+ /*
+ * Loading another kernel to switch to if this one
+ * crashes. Free any current crash dump kernel before
+ * we corrupt it.
+ */
+ kimage_free(xchg(&kexec_crash_image, NULL));
+ }
+
+ ret = kimage_alloc_init(&image, entry, nr_segments, segments, flags);
+ if (ret)
+ return ret;
+
+ if (flags & KEXEC_ON_CRASH)
+ crash_map_reserved_pages();
+
+ if (flags & KEXEC_PRESERVE_CONTEXT)
+ image->preserve_context = 1;
+
+ ret = machine_kexec_prepare(image);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < nr_segments; i++) {
+ ret = kimage_load_segment(image, &image->segment[i]);
+ if (ret)
+ goto out;
+ }
+
+ kimage_terminate(image);
+
+ /* Install the new kernel and uninstall the old */
+ image = xchg(dest_image, image);
+
+out:
+ /*
+ * Once the reserved memory is mapped, we should unmap this memory
+ * before returning
+ */
+ if (flags & KEXEC_ON_CRASH)
+ crash_unmap_reserved_pages();
+ kimage_free(image);
+ return ret;
+}
+
/*
* Exec Kernel system call: for obvious reasons only root may call it.
*
@@ -127,7 +189,6 @@ out_free_image:
SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
struct kexec_segment __user *, segments, unsigned long, flags)
{
- struct kimage **dest_image, *image;
int result;
/* We only trust the superuser with rebooting the system. */
@@ -152,9 +213,6 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
if (nr_segments > KEXEC_SEGMENT_MAX)
return -EINVAL;
- image = NULL;
- result = 0;
-
/* Because we write directly to the reserved memory
* region when loading crash kernels we need a mutex here to
* prevent multiple crash kernels from attempting to load
@@ -166,53 +224,9 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
if (!mutex_trylock(&kexec_mutex))
return -EBUSY;
- dest_image = &kexec_image;
- if (flags & KEXEC_ON_CRASH)
- dest_image = &kexec_crash_image;
- if (nr_segments > 0) {
- unsigned long i;
-
- if (flags & KEXEC_ON_CRASH) {
- /*
- * Loading another kernel to switch to if this one
- * crashes. Free any current crash dump kernel before
- * we corrupt it.
- */
-
- kimage_free(xchg(&kexec_crash_image, NULL));
- result = kimage_alloc_init(&image, entry, nr_segments,
- segments, flags);
- crash_map_reserved_pages();
- } else {
- /* Loading another kernel to reboot into. */
-
- result = kimage_alloc_init(&image, entry, nr_segments,
- segments, flags);
- }
- if (result)
- goto out;
-
- if (flags & KEXEC_PRESERVE_CONTEXT)
- image->preserve_context = 1;
- result = machine_kexec_prepare(image);
- if (result)
- goto out;
-
- for (i = 0; i < nr_segments; i++) {
- result = kimage_load_segment(image, &image->segment[i]);
- if (result)
- goto out;
- }
- kimage_terminate(image);
- if (flags & KEXEC_ON_CRASH)
- crash_unmap_reserved_pages();
- }
- /* Install the new kernel, and Uninstall the old */
- image = xchg(dest_image, image);
+ result = do_kexec_load(entry, nr_segments, segments, flags);
-out:
mutex_unlock(&kexec_mutex);
- kimage_free(image);
return result;
}
--
2.1.0
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] kexec: Make a pair of map/unmap reserved pages in error path
2016-02-25 14:02 [PATCH] kexec: Make a pair of map/unmap reserved pages in error path Minfei Huang
@ 2016-02-27 0:56 ` Andrew Morton
2016-02-29 11:06 ` Minfei Huang
0 siblings, 1 reply; 3+ messages in thread
From: Andrew Morton @ 2016-02-27 0:56 UTC (permalink / raw)
To: Minfei Huang; +Cc: ebiederm, kexec, linux-kernel, Minfei Huang
On Thu, 25 Feb 2016 22:02:40 +0800 Minfei Huang <mhuang@redhat.com> wrote:
> From: Minfei Huang <mnfhuang@gmail.com>
>
> For some arch, kexec shall map the reserved pages, then use them, when
> we try to start the kdump service.
>
> kexec may return directly, without unmaping the reserved pages, if it
> fails during starting service. To fix it, we make a pair of map/unmap
> reserved pages both in generic path and error path.
This patch both refactors the code AND fixes the bug. It is a
decent-looking refactoring, but mixing the two together makes it *much*
harder to review the bugfix. These two steps should be separated
please, with the bugfix patch coming first.
> --- a/kernel/kexec.c
> +++ b/kernel/kexec.c
> @@ -103,6 +103,68 @@ out_free_image:
> return ret;
> }
>
> +static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
> + struct kexec_segment __user *segments, unsigned long flags)
> +{
> + struct kimage **dest_image, *image;
> + unsigned long i;
> + int ret;
> +
> + if (flags & KEXEC_ON_CRASH)
> + dest_image = &kexec_crash_image;
> + else
> + dest_image = &kexec_image;
> +
> + if (nr_segments == 0) {
> + /* Uninstall image */
> + kimage_free(xchg(dest_image, NULL));
> + return 0;
> + }
> + if (flags & KEXEC_ON_CRASH) {
> + /*
> + * Loading another kernel to switch to if this one
> + * crashes. Free any current crash dump kernel before
> + * we corrupt it.
> + */
> + kimage_free(xchg(&kexec_crash_image, NULL));
> + }
> +
> + ret = kimage_alloc_init(&image, entry, nr_segments, segments, flags);
> + if (ret)
> + return ret;
This is a bug, isn't it? Missed kimage_free().
> + if (flags & KEXEC_ON_CRASH)
> + crash_map_reserved_pages();
> +
> + if (flags & KEXEC_PRESERVE_CONTEXT)
> + image->preserve_context = 1;
> +
> + ret = machine_kexec_prepare(image);
> + if (ret)
> + goto out;
> +
> + for (i = 0; i < nr_segments; i++) {
> + ret = kimage_load_segment(image, &image->segment[i]);
> + if (ret)
> + goto out;
> + }
> +
> + kimage_terminate(image);
> +
> + /* Install the new kernel and uninstall the old */
> + image = xchg(dest_image, image);
> +
> +out:
> + /*
> + * Once the reserved memory is mapped, we should unmap this memory
> + * before returning
> + */
> + if (flags & KEXEC_ON_CRASH)
> + crash_unmap_reserved_pages();
> + kimage_free(image);
> + return ret;
> +}
> +
>
> ...
>
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] kexec: Make a pair of map/unmap reserved pages in error path
2016-02-27 0:56 ` Andrew Morton
@ 2016-02-29 11:06 ` Minfei Huang
0 siblings, 0 replies; 3+ messages in thread
From: Minfei Huang @ 2016-02-29 11:06 UTC (permalink / raw)
To: Andrew Morton; +Cc: ebiederm, kexec, linux-kernel, Minfei Huang
On 02/26/16 at 04:56pm, Andrew Morton wrote:
> On Thu, 25 Feb 2016 22:02:40 +0800 Minfei Huang <mhuang@redhat.com> wrote:
>
> > From: Minfei Huang <mnfhuang@gmail.com>
> >
> > For some arch, kexec shall map the reserved pages, then use them, when
> > we try to start the kdump service.
> >
> > kexec may return directly, without unmaping the reserved pages, if it
> > fails during starting service. To fix it, we make a pair of map/unmap
> > reserved pages both in generic path and error path.
>
> This patch both refactors the code AND fixes the bug. It is a
> decent-looking refactoring, but mixing the two together makes it *much*
> harder to review the bugfix. These two steps should be separated
> please, with the bugfix patch coming first.
I will bisect this patch to make it more simple to be reviewed.
>
> > --- a/kernel/kexec.c
> > +++ b/kernel/kexec.c
> > @@ -103,6 +103,68 @@ out_free_image:
> > return ret;
> > }
> >
> > +static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
> > + struct kexec_segment __user *segments, unsigned long flags)
> > +{
> > + struct kimage **dest_image, *image;
> > + unsigned long i;
> > + int ret;
> > +
> > + if (flags & KEXEC_ON_CRASH)
> > + dest_image = &kexec_crash_image;
> > + else
> > + dest_image = &kexec_image;
> > +
> > + if (nr_segments == 0) {
> > + /* Uninstall image */
> > + kimage_free(xchg(dest_image, NULL));
> > + return 0;
> > + }
> > + if (flags & KEXEC_ON_CRASH) {
> > + /*
> > + * Loading another kernel to switch to if this one
> > + * crashes. Free any current crash dump kernel before
> > + * we corrupt it.
> > + */
> > + kimage_free(xchg(&kexec_crash_image, NULL));
> > + }
> > +
> > + ret = kimage_alloc_init(&image, entry, nr_segments, segments, flags);
> > + if (ret)
> > + return ret;
>
> This is a bug, isn't it? Missed kimage_free().
The variable image is NULL, if kimage_alloc_init returns with error. And
kimage_alloc_init will do the cleanup before returning. So it's fine
without calling kimage_free.
Thanks
Minfei
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-02-29 11:03 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-25 14:02 [PATCH] kexec: Make a pair of map/unmap reserved pages in error path Minfei Huang
2016-02-27 0:56 ` Andrew Morton
2016-02-29 11:06 ` Minfei Huang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®