Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1343177 > unrolled thread

[PATCH] kexec: Make a pair of map/unmap reserved pages in error path

Started byMinfei Huang <mhuang@redhat.com>
First post2016-02-25 15:00 +0100
Last post2016-02-29 12:10 +0100
Articles 3 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH] kexec: Make a pair of map/unmap reserved pages in error path Minfei Huang <mhuang@redhat.com> - 2016-02-25 15:00 +0100
    Re: [PATCH] kexec: Make a pair of map/unmap reserved pages in error  path Andrew Morton <akpm@linux-foundation.org> - 2016-02-27 02:00 +0100
      Re: [PATCH] kexec: Make a pair of map/unmap reserved pages in error  path Minfei Huang <mhuang@redhat.com> - 2016-02-29 12:10 +0100

#1343177 — [PATCH] kexec: Make a pair of map/unmap reserved pages in error path

FromMinfei Huang <mhuang@redhat.com>
Date2016-02-25 15:00 +0100
Subject[PATCH] kexec: Make a pair of map/unmap reserved pages in error path
Message-ID<r64Cv-4Cd-11@gated-at.bofh.it>
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

[toc] | [next] | [standalone]


#1344875 — Re: [PATCH] kexec: Make a pair of map/unmap reserved pages in error path

FromAndrew Morton <akpm@linux-foundation.org>
Date2016-02-27 02:00 +0100
SubjectRe: [PATCH] kexec: Make a pair of map/unmap reserved pages in error path
Message-ID<r6BoK-3aU-5@gated-at.bofh.it>
In reply to#1343177
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;
> +}
> +
>
> ...
>

[toc] | [prev] | [next] | [standalone]


#1345663 — Re: [PATCH] kexec: Make a pair of map/unmap reserved pages in error path

FromMinfei Huang <mhuang@redhat.com>
Date2016-02-29 12:10 +0100
SubjectRe: [PATCH] kexec: Make a pair of map/unmap reserved pages in error path
Message-ID<r7tSb-2et-41@gated-at.bofh.it>
In reply to#1344875
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

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web