[PATCH v3] kexec-tools: Perform run-time linking of libxenctrl.so

Daniel Kiper daniel.kiper at oracle.com
Tue Jan 16 13:39:14 PST 2018


On Fri, Jan 12, 2018 at 03:21:13PM -0600, Eric DeVolder wrote:
> When kexec is utilized in a Xen environment, it has an explicit
> run-time dependency on libxenctrl.so. This dependency occurs
> during the configure stage and when building kexec-tools.
>
> When kexec is utilized in a non-Xen environment (either bare
> metal or KVM), the configure and build of kexec-tools omits
> any reference to libxenctrl.so.

[...]

Wow! What a long story! Patch looks quite good. Just a few nitpicks.
If you fix them then you can add Reviewed-by: Daniel Kiper <daniel.kiper at oracle.com>
to the next version.

> Signed-off-by: Eric DeVolder <eric.devolder at oracle.com>
> ---
> v1: 29nov2017
>  - Daniel Kiper suggested Debian's libxen package of libraries,
>    but I did not find similar package on most other systems.
>
> v2: 14dec2017
>  - Reposted to kexec and xen-devel mailing lists
>
> v3: 12jan2018
>  - Incorporated feedback from Daniel Kiper.
>    Configure changes for --with-xen=dl, style problems corrected.
>    Extensive testing of the new mode.
> ---
>  configure.ac                       | 27 ++++++++++----
>  kexec/Makefile                     |  1 +
>  kexec/arch/i386/crashdump-x86.c    |  4 +--
>  kexec/arch/i386/kexec-x86-common.c |  4 +--
>  kexec/crashdump-xen.c              |  4 +--
>  kexec/kexec-xen.c                  | 41 ++++++++++++++++++++-
>  kexec/kexec-xen.h                  | 73 ++++++++++++++++++++++++++++++++++++++
>  7 files changed, 138 insertions(+), 16 deletions(-)
>  create mode 100644 kexec/kexec-xen.h
>
> diff --git a/configure.ac b/configure.ac
> index 208dc0a..4dab57f 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -167,12 +167,27 @@ if test "$with_xen" = yes ; then
>  	AC_CHECK_HEADER(xenctrl.h,
>  		[AC_CHECK_LIB(xenctrl, xc_kexec_load, ,
>  		AC_MSG_NOTICE([Xen support disabled]))])
> -		if test "$ac_cv_lib_xenctrl_xc_kexec_load" = yes ; then
> -			AC_CHECK_LIB(xenctrl, xc_kexec_status,
> -				AC_DEFINE(HAVE_KEXEC_CMD_STATUS, 1,
> -					[The kexec_status call is available]),
> -				AC_MSG_NOTICE([The kexec_status call is not available]))
> -		fi
> +fi
> +
> +dnl Link libxenctrl.so at run-time rather than build-time
> +if test "$with_xen" = dl ; then
> +	AC_CHECK_HEADER(dlfcn.h,
> +		[AC_CHECK_LIB(dl, dlopen, ,
> +			AC_MSG_ERROR([Dynamic library linking not available]))],
> +		AC_MSG_ERROR([Dynamic library linking not available]))

I think that this error message should be like this:
  Dynamic library linking header not available

> +	AC_DEFINE(CONFIG_LIBXENCTRL_DL, 1, [Define to 1 to link libxenctrl.so at run-time rather than build-time])
> +	AC_CHECK_HEADER(xenctrl.h,
> +		[AC_CHECK_LIB(xenctrl, xc_kexec_load,
> +		AC_DEFINE(HAVE_LIBXENCTRL, 1, ), # required define, and prevent -lxenctrl
> +		AC_MSG_NOTICE([Xen support disabled]))])
> +fi
> +
> +dnl Check for the Xen kexec_status hypercall - reachable from --with-xen=yes|dl
> +if test "$ac_cv_lib_xenctrl_xc_kexec_load" = yes ; then
> +	AC_CHECK_LIB(xenctrl, xc_kexec_status,
> +		AC_DEFINE(HAVE_KEXEC_CMD_STATUS, 1,
> +			[The kexec_status call is available]),
> +		AC_MSG_NOTICE([The kexec_status call is not available]))
>  fi
>
>  dnl ---Sanity checks
> diff --git a/kexec/Makefile b/kexec/Makefile
> index 2b4fb3d..8871731 100644
> --- a/kexec/Makefile
> +++ b/kexec/Makefile
> @@ -36,6 +36,7 @@ dist += kexec/Makefile						\
>  	kexec/kexec-elf-boot.h					\
>  	kexec/kexec-elf.h kexec/kexec-sha256.h			\
>  	kexec/kexec-zlib.h kexec/kexec-lzma.h			\
> +	kexec/kexec-xen.h 								\

Could you fix backslash alignment? Maybe in separate patch. It can be
part of this series.

>  	kexec/kexec-syscall.h kexec/kexec.h kexec/kexec.8
>
>  dist				+= kexec/proc_iomem.c
> diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
> index 69a063a..a948d9f 100644
> --- a/kexec/arch/i386/crashdump-x86.c
> +++ b/kexec/arch/i386/crashdump-x86.c
> @@ -44,9 +44,7 @@
>  #include "kexec-x86.h"
>  #include "crashdump-x86.h"
>

Please remove this blank line...

> -#ifdef HAVE_LIBXENCTRL
> -#include <xenctrl.h>
> -#endif /* HAVE_LIBXENCTRL */
> +#include "../../kexec-xen.h"
>

...and this... Same things below... This was done to separate
conditional include from unconditional ones. So, blank lines
after your patch are no longer needed.

>  #include "x86-linux-setup.h"
>
> diff --git a/kexec/arch/i386/kexec-x86-common.c b/kexec/arch/i386/kexec-x86-common.c
> index be03618..b44c8b7 100644
> --- a/kexec/arch/i386/kexec-x86-common.c
> +++ b/kexec/arch/i386/kexec-x86-common.c
> @@ -40,9 +40,7 @@
>  #include "../../crashdump.h"
>  #include "kexec-x86.h"
>

Ditto...

> -#ifdef HAVE_LIBXENCTRL
> -#include <xenctrl.h>
> -#endif /* HAVE_LIBXENCTRL */
> +#include "../../kexec-xen.h"
>

But leave this one...

>  /* Used below but not present in (older?) xenctrl.h */
>  #ifndef E820_PMEM
> diff --git a/kexec/crashdump-xen.c b/kexec/crashdump-xen.c
> index 60594f6..2e4cbdc 100644
> --- a/kexec/crashdump-xen.c
> +++ b/kexec/crashdump-xen.c
> @@ -18,9 +18,7 @@
>
>  #include "config.h"
>

Ditto...

> -#ifdef HAVE_LIBXENCTRL
> -#include <xenctrl.h>
> -#endif
> +#include "kexec-xen.h"
>

But leave this one... And same rules below...

>  struct crash_note_info {
>  	unsigned long base;
> diff --git a/kexec/kexec-xen.c b/kexec/kexec-xen.c
> index 2b448d3..8ec3398 100644
> --- a/kexec/kexec-xen.c
> +++ b/kexec/kexec-xen.c
> @@ -10,10 +10,49 @@
>  #include "config.h"
>
>  #ifdef HAVE_LIBXENCTRL
> -#include <xenctrl.h>
> +#include "kexec-xen.h"
>
>  #include "crashdump.h"
>
> +#ifdef CONFIG_LIBXENCTRL_DL
> +void *xc_dlhandle;
> +xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(HYPERCALL_BUFFER_NULL);
> +xc_interface *__xc_interface_open(xentoollog_logger *logger,
> +                                xentoollog_logger *dombuild_logger,
> +                                unsigned open_flags)
> +{
> +    xc_interface *xch = NULL;
> +
> +    if (!xc_dlhandle)
> +        xc_dlhandle = dlopen("libxenctrl.so", RTLD_NOW | RTLD_NODELETE);
> +
> +    if (xc_dlhandle) {
> +        typedef xc_interface *(*func_t)(xentoollog_logger *logger,
> +                                xentoollog_logger *dombuild_logger,
> +                                unsigned open_flags);
> +        func_t func = (func_t)dlsym(xc_dlhandle, "xc_interface_open");

I know your opinion about that definitions but I am not happy with them here.
However, if maintainer is OK with them I will not insist on changing that. Just
please add one extra line between definitions above and function call below.

> +        xch = func(logger, dombuild_logger, open_flags);
> +    }
> +
> +    return xch;
> +}
> +
> +int __xc_interface_close(xc_interface *xch)
> +{
> +    int rc = -1;
> +
> +    if (xc_dlhandle) {
> +        typedef int (*func_t)(xc_interface *xch);
> +        func_t func = (func_t)dlsym(xc_dlhandle, "xc_interface_close");

Same as above... Please add empty line here...

> +        rc = func(xch);
> +

...and I think that you can drop this one here...

> +        xc_dlhandle = NULL;
> +    }
> +
> +    return rc;
> +}
> +#endif /* CONFIG_LIBXENCTRL_DL */
> +
>  int xen_kexec_load(struct kexec_info *info)
>  {
>  	uint32_t nr_segments = info->nr_segments;
> diff --git a/kexec/kexec-xen.h b/kexec/kexec-xen.h
> new file mode 100644
> index 0000000..50e2b3d
> --- /dev/null
> +++ b/kexec/kexec-xen.h
> @@ -0,0 +1,73 @@
> +#ifndef KEXEC_XEN_H
> +#define KEXEC_XEN_H
> +
> +#ifdef HAVE_LIBXENCTRL

I would add empty line here...

> +#include <xenctrl.h>
> +
> +#ifdef CONFIG_LIBXENCTRL_DL

...and here...

> +#include <dlfcn.h>
> +
> +/* The handle from dlopen(), needed by dlsym(), dlclose() */
> +extern void *xc_dlhandle;
> +
> +/* Wrappers around xc_interface_open/close() to insert dlopen/dlclose() */
> +xc_interface *__xc_interface_open(xentoollog_logger *logger,
> +                                xentoollog_logger *dombuild_logger,
> +                                unsigned open_flags);
> +int __xc_interface_close(xc_interface *xch);
> +
> +/* GCC expression statements for evaluating dlsym() */
> +#define __xc_call(dtype, name, args...) \
> +( \
> +    { dtype value; \
> +    typedef dtype (*func_t)(xc_interface *, ...); \
> +    func_t func = dlsym(xc_dlhandle, #name); \
> +    value = func(args); \
> +    value; } \

Please use one tab instead of spaces here.

> +)
> +#define __xc_data(dtype, name) \
> +( \
> +    { dtype *value = (dtype *)dlsym(xc_dlhandle, #name); \
> +    value; } \

It looks that this code can fit into one line. Could you change that?
And one tab instead of spaces...

> +)
> +
> +/* The wrappers around utilized xenctrl.h functions */
> +#define xc_interface_open(a, b, c)  \
> +    __xc_interface_open(a, b, c)

I would put 2 tabs instead of spaces here and below...

> +#define xc_interface_close(a)       \
> +    __xc_interface_close(a)
> +#define xc_version(args...)         \
> +    __xc_call(int, xc_version, args)
> +#define xc_get_max_cpus(args...)    \
> +    __xc_call(int, xc_get_max_cpus, args)
> +#define xc_get_machine_memory_map(args...)  \
> +    __xc_call(int, xc_get_machine_memory_map, args)
> +#define xc_kexec_get_range(args...) \
> +    __xc_call(int, xc_kexec_get_range, args)
> +#define xc_kexec_load(args...)      \
> +    __xc_call(int, xc_kexec_load, args)
> +#define xc_kexec_unload(args...)    \
> +    __xc_call(int, xc_kexec_unload, args)
> +#define xc_kexec_status(args...)    \
> +    __xc_call(int, xc_kexec_status, args)
> +#define xc_kexec_exec(args...)      \
> +    __xc_call(int, xc_kexec_exec, args)
> +#define xc_hypercall_buffer_array_create(args...)   \
> +    __xc_call(xc_hypercall_buffer_array_t *, xc_hypercall_buffer_array_create, args)
> +#define xc__hypercall_buffer_alloc_pages(args...)   \
> +    __xc_call(void *, xc__hypercall_buffer_alloc_pages, args)
> +#define xc__hypercall_buffer_free_pages(args...)    \
> +    __xc_call(void  , xc__hypercall_buffer_free_pages, args)
> +#define xc__hypercall_buffer_array_alloc(args...)   \
> +    __xc_call(void *, xc__hypercall_buffer_array_alloc, args)
> +#define xc__hypercall_buffer_array_get(args...)     \
> +    __xc_call(void *, xc__hypercall_buffer_array_get, args)
> +#define xc_hypercall_buffer_array_destroy(args...)  \
> +    __xc_call(void *, xc_hypercall_buffer_array_destroy, args)
> +
> +#endif /* CONFIG_LIBXENCTRL_DL */
> +

You can drop this empty line...

> +#endif /* HAVE_LIBXENCTRL */
> +

...and leave this one...

> +#endif /* KEXEC_XEN_H */
> +

...and drop this one...

Thanks,

Daniel



More information about the kexec mailing list