[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