From: Jason Gunthorpe <jgg@xxxxxxxxxxxx> The remaining kernel headers are all inlined into a struct. To avoid major code changes we want to retain this arrangement, but still use the kernel headers directly. This solution is to mangle the kernel headers by script into an anonymous and tagless struct that can be used in place of the copied data. With the support of a few macros the whole thing becomes fairly straightforward. Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx> --- buildlib/make_abi_structs.py | 56 +++++++++++++++++++++++++++++++++++++++++++ kernel-headers/CMakeLists.txt | 35 +++++++++++++++++++++++++++ kernel-headers/kern-abi.c | 1 + libibverbs/CMakeLists.txt | 1 + 4 files changed, 93 insertions(+) create mode 100644 buildlib/make_abi_structs.py create mode 100644 kernel-headers/kern-abi.c diff --git a/buildlib/make_abi_structs.py b/buildlib/make_abi_structs.py new file mode 100644 index 00000000000000..029f10428ad300 --- /dev/null +++ b/buildlib/make_abi_structs.py @@ -0,0 +1,56 @@ +#/usr/bin/env python +"""This script transforms the structs inside the kernel ABI headers into a define +of an anonymous struct. + +eg + struct abc {int foo;}; +becomes + #define _STRUCT_abc struct {int foo;}; + +This allows the exact same struct to be included in the provider wrapper struct: + +struct abc_resp { + struct ibv_abc ibv_resp; + _STRUCT_abc; +}; + +Which duplicates the struct layout and naming we have historically used, but +sources the data directly from the kernel headers instead of manually copying.""" +import re; +import functools; +import sys; + +def in_struct(ln,FO,nesting=0): + """Copy a top level structure over to the #define output, keeping track of + nested structures.""" + if nesting == 0: + if ln == "};": + FO.write("}\n\n"); + return find_struct; + + FO.write(ln + " \\\n"); + + if ln == "struct {" or ln == "union {": + return functools.partial(in_struct,nesting=nesting+1); + + if re.match(r"}.*;",ln): + return functools.partial(in_struct,nesting=nesting-1); + return functools.partial(in_struct,nesting=nesting); + +def find_struct(ln,FO): + """Look for the start of a top level structure""" + if ln.startswith("struct ") or ln.startswith("union "): + g = re.match(r"(struct|union)\s+(\S+)\s+{",ln); + FO.write("#define _STRUCT_%s %s { \\\n"%(g.group(2),g.group(1))); + return in_struct; + return find_struct; + +with open(sys.argv[1]) as FI: + with open(sys.argv[2],"w") as FO: + state = find_struct; + for ln in FI: + # Drop obvious comments + ln = ln.strip(); + ln = re.sub(r"/\*.*\*/","",ln); + ln = re.sub(r"//.*$","",ln); + state = state(ln,FO); diff --git a/kernel-headers/CMakeLists.txt b/kernel-headers/CMakeLists.txt index 64bc5e66c21b18..0e163bd86c184d 100644 --- a/kernel-headers/CMakeLists.txt +++ b/kernel-headers/CMakeLists.txt @@ -25,3 +25,38 @@ publish_internal_headers(rdma/hfi rdma/hfi/hfi1_ioctl.h rdma/hfi/hfi1_user.h ) + +function(rdma_kernel_provider_abi) + # Older versions of cmake do not create the output directory automatically + set(DDIR "${BUILD_INCLUDE}/kernel-abi") + if(NOT EXISTS "${DDIR}/") + execute_process(COMMAND "${CMAKE_COMMAND}" "-E" "make_directory" + "${DDIR}" RESULT_VARIABLE retcode) + if(NOT "${retcode}" STREQUAL "0") + message(FATAL_ERROR "Failed to create directory ${DDIR}") + endif() + endif() + + set(HDRS "") + foreach(IHDR ${ARGN}) + get_filename_component(FIL ${IHDR} NAME) + set(OHDR "${DDIR}/${FIL}") + set(HDRS ${HDRS} ${OHDR}) + add_custom_command( + OUTPUT "${OHDR}" + COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/buildlib/make_abi_structs.py" "${IHDR}" "${OHDR}" + MAIN_DEPENDENCY "${IHDR}" + DEPENDS "${CMAKE_SOURCE_DIR}/buildlib/make_abi_structs.py" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Creating ABI wrapper ${OHDR}" + ) + endforeach() + + # This weird construction is needed to ensure ordering of the build. + add_library(kern-abi STATIC kern-abi.c ${HDRS}) +endfunction() + +# Transform the kernel ABIs used by the providers +rdma_kernel_provider_abi( + rdma/ib_user_verbs.h + ) diff --git a/kernel-headers/kern-abi.c b/kernel-headers/kern-abi.c new file mode 100644 index 00000000000000..cd2941ed829a5a --- /dev/null +++ b/kernel-headers/kern-abi.c @@ -0,0 +1 @@ +/* empty file for cmake */ diff --git a/libibverbs/CMakeLists.txt b/libibverbs/CMakeLists.txt index fd4374d9c8428b..6fdec63ac0c54c 100644 --- a/libibverbs/CMakeLists.txt +++ b/libibverbs/CMakeLists.txt @@ -46,4 +46,5 @@ target_link_libraries(ibverbs LINK_PRIVATE ${NL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} + kern-abi ) -- 2.16.1 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html