From patchwork Mon Sep 9 12:02:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrii Sultanov X-Patchwork-Id: 13796874 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 51A66ECE57A for ; Mon, 9 Sep 2024 12:03:12 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.794381.1203285 (Exim 4.92) (envelope-from ) id 1snd6l-0000rD-Tg; Mon, 09 Sep 2024 12:03:03 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 794381.1203285; Mon, 09 Sep 2024 12:03:03 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1snd6l-0000r4-Os; Mon, 09 Sep 2024 12:03:03 +0000 Received: by outflank-mailman (input) for mailman id 794381; Mon, 09 Sep 2024 12:03:02 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1snd6k-0000ce-PJ for xen-devel@lists.xenproject.org; Mon, 09 Sep 2024 12:03:02 +0000 Received: from mail-ej1-x632.google.com (mail-ej1-x632.google.com [2a00:1450:4864:20::632]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 7627bb3d-6ea3-11ef-a0b5-8be0dac302b0; Mon, 09 Sep 2024 14:03:01 +0200 (CEST) Received: by mail-ej1-x632.google.com with SMTP id a640c23a62f3a-a8d4979b843so188445666b.3 for ; Mon, 09 Sep 2024 05:03:01 -0700 (PDT) Received: from EMEAENGAAD87503.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a8d25d65742sm331603066b.216.2024.09.09.05.02.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Sep 2024 05:02:59 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 7627bb3d-6ea3-11ef-a0b5-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1725883380; x=1726488180; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CS9uEkUj8IaxPFALzgiU7ZUvbzIrHMm09v58rnSZdpg=; b=blL3ULlCJqFkdiRwbRbZlJU7f5B9V9xi2bzO3SFizwAwyNiznCT9iel6RO1nb16UA1 WGFIp6NQrVbfkUOQ3kguC0JUkefCM5njDA8qM3UTDaNfrK9Er8ZvU11zU9e9UzAkH83x S99C4viijaNI4OcqRwh6Y4P/fJVpZsRckL7oE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725883380; x=1726488180; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CS9uEkUj8IaxPFALzgiU7ZUvbzIrHMm09v58rnSZdpg=; b=UZbXqEyrMoDbkc+smhD3w6KOwollYqtO8KbN3rHHLByF+n8+mOS2tmat5z9bcLDH4u 6BMqpTDj9SqWrdjnBjUWcaw3JA+3v2bMbNlbndzmYpoxO2tLqrm9/INnYx3tbSJQIh+l N7rc4UKNZ6UrmvH4GpNQnim/ut+srduehJJZnUhmZsk7QVz9r075gcvRaHU5I6P6RSJH 03A5N/PouebyEsbBeDcelN/dT3Q7NjbAVkXUjUvXAo+39uxxo3dbv1ZitakJMleYb7Wc 0UkwLqY70ybBvromtw9Wiyq9nBrihAeXwmUfRDNly2+Qaba5nTslSltBVAi9rnZCwmFF 2R8Q== X-Gm-Message-State: AOJu0YwGUSlPGNzezKekHxH6LFMbR+s9VbmmWvvQJXlRxSCbOZdPKvBT l5Fa3rqkl1Rg7pSidskdtEVsMdxzJctkCJx1CAUskiS1MznkJoiC42CNBosAwCaOU8j5mh1ugHv 6 X-Google-Smtp-Source: AGHT+IGA1jOMYQNlgckHldbsJ/pUfv6SI50pdEiSt6HwzBdD8+6zuq2HAyb8AGGqPQMjkcvx64XjvA== X-Received: by 2002:a17:906:eec7:b0:a86:bb90:93fa with SMTP id a640c23a62f3a-a8a888726c3mr1087075466b.44.1725883380261; Mon, 09 Sep 2024 05:03:00 -0700 (PDT) From: Andrii Sultanov To: xen-devel@lists.xenproject.org Cc: Andrii Sultanov , Christian Lindig , David Scott , Anthony PERARD , Christian Lindig Subject: [PATCH v3 1/3] ocaml/libs: Implement a dynamically-loaded plugin for Xenctrl.domain_getinfo Date: Mon, 9 Sep 2024 13:02:40 +0100 Message-Id: <034c49b1bcfab5fb67bbf290328ac517ea82f30a.1725881488.git.andrii.sultanov@cloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 This plugin intends to hide the unstable Xenctrl interface under a stable one. In case of the change in the interface, a V2 of this plugin would need to be produced, but V1 with the old interface would need to be kept (with potential change in the implementation) in the meantime. To reduce the need for such changes in the future, this plugin only provides the absolute minimum functionality that Oxenstored uses - only three fields of the domaininfo struct are used and presented here. Oxenstored currently uses the single-domain domain_getinfo function, whereas Cxenstored uses the more-efficient domain_getinfolist. Both of these are provided in the plugin to allow a transition from one to the other without modifying the interface in the future. Both return identical structures and rely on the same fields in xenctrl, thus if one of them breaks, both will break, and a new version of the interface would need to be issued. Signed-off-by: Andrii Sultanov Acked-by: Christian Lindig --- * Reformat files appropriately * Rename all instances of 'xenstoredglue', 'xenstored_glue', 'xsglue' to 'xsd_glue' for consistency * Remove _v1 suffix from all static functions * Remove leftover #defines left unused by the previous changes * Fix inconsistent tabs/spaces usage, added blank lines where appropriate. * Define the 'xsd_glue_failwith' macro as suggested * Remove first_domain argument in 'domain_getinfolist' function * Remove unnecessary memory allocation alignment code in 'domain_getinfolist' * Improve error handling in 'domain_getinfolist' as suggested. * Add SPDX license headers to new files. tools/ocaml/Makefile | 1 + tools/ocaml/libs/Makefile | 2 +- tools/ocaml/libs/xsd_glue/META.in | 4 + tools/ocaml/libs/xsd_glue/Makefile | 46 +++++ .../xsd_glue/domain_getinfo_plugin_v1/META.in | 5 + .../domain_getinfo_plugin_v1/Makefile | 38 ++++ .../domain_getinfo_stubs_v1.c | 162 ++++++++++++++++++ .../domain_getinfo_v1.ml | 35 ++++ .../domain_getinfo_v1.mli | 1 + .../libs/xsd_glue/plugin_interface_v1.ml | 30 ++++ .../libs/xsd_glue/plugin_interface_v1.mli | 38 ++++ 11 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 tools/ocaml/libs/xsd_glue/META.in create mode 100644 tools/ocaml/libs/xsd_glue/Makefile create mode 100644 tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/META.in create mode 100644 tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile create mode 100644 tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_stubs_v1.c create mode 100644 tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_v1.ml create mode 100644 tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_v1.mli create mode 100644 tools/ocaml/libs/xsd_glue/plugin_interface_v1.ml create mode 100644 tools/ocaml/libs/xsd_glue/plugin_interface_v1.mli diff --git a/tools/ocaml/Makefile b/tools/ocaml/Makefile index 1557fd6c3c..7252eb23d7 100644 --- a/tools/ocaml/Makefile +++ b/tools/ocaml/Makefile @@ -29,6 +29,7 @@ build-tools-oxenstored: $(MAKE) -s -C libs/mmap $(MAKE) -s -C libs/xb $(MAKE) -s -C libs/xc + $(MAKE) -s -C libs/xsd_glue $(MAKE) -C xenstored .PHONY: format diff --git a/tools/ocaml/libs/Makefile b/tools/ocaml/libs/Makefile index 89350aa12f..6bcec58502 100644 --- a/tools/ocaml/libs/Makefile +++ b/tools/ocaml/libs/Makefile @@ -4,7 +4,7 @@ include $(XEN_ROOT)/tools/Rules.mk SUBDIRS= \ mmap \ eventchn xc \ - xb xs + xb xs xsd_glue .PHONY: all all: subdirs-all diff --git a/tools/ocaml/libs/xsd_glue/META.in b/tools/ocaml/libs/xsd_glue/META.in new file mode 100644 index 0000000000..dbd584ac17 --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/META.in @@ -0,0 +1,4 @@ +version = "@VERSION@" +description = "A small library on top of unstable Xenctrl interfaces used by Oxenstored" +archive(byte) = "plugin_interface_v1.cma" +archive(native) = "plugin_interface_v1.cmxa" diff --git a/tools/ocaml/libs/xsd_glue/Makefile b/tools/ocaml/libs/xsd_glue/Makefile new file mode 100644 index 0000000000..f84291f7fe --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/Makefile @@ -0,0 +1,46 @@ +OCAML_TOPLEVEL=$(CURDIR)/../.. +XEN_ROOT=$(OCAML_TOPLEVEL)/../.. +include $(OCAML_TOPLEVEL)/common.make + +SUBDIRS= domain_getinfo_plugin_v1 + +CFLAGS += $(CFLAGS_xeninclude) +OCAMLOPTFLAGS += -opaque + +OBJS = plugin_interface_v1 +INTF = $(foreach obj, $(OBJS),$(obj).cmi) +LIBS = plugin_interface_v1.cma plugin_interface_v1.cmxa +LIBS_plugin_interface_v1 = +plugin_interface_v1_OBJS=$(OBJS) + +.PHONY: all +all: $(INTF) $(LIBS) $(PROGRAMS) subdirs-all + +bins: $(PROGRAMS) + +libs: $(LIBS) + +plugin_interface_v1 = $(OBJS) + +OCAML_NOC_LIBRARY = plugin_interface_v1 + +.PHONY: install +install: $(LIBS) META subdirs-install + mkdir -p $(OCAMLDESTDIR) + $(OCAMLFIND) remove -destdir $(OCAMLDESTDIR) xsd_glue + $(OCAMLFIND) install -destdir $(OCAMLDESTDIR) -ldconf ignore xsd_glue META $(INTF) $(LIBS) + $(OCAMLFIND) remove -destdir $(OCAMLDESTDIR) xsd_glue_dev + $(OCAMLFIND) install -destdir $(OCAMLDESTDIR) -ldconf ignore xsd_glue_dev META $(INTF) $(LIBS) *.ml *.mli + +.PHONY: uninstall +uninstall: subdirs-uninstall + $(OCAMLFIND) remove -destdir $(OCAMLDESTDIR) xsd_glue + $(OCAMLFIND) remove -destdir $(OCAMLDESTDIR) xsd_glue_dev + +.PHONY: clean +clean: subdirs-clean + +.PHONY: distclean +distclean: subdirs-distclean + +include $(OCAML_TOPLEVEL)/Makefile.rules diff --git a/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/META.in b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/META.in new file mode 100644 index 0000000000..fb917def62 --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/META.in @@ -0,0 +1,5 @@ +version = "@VERSION@" +description = "Xenstored plugin for Xenctrl.domain_getinfo unstable interface - V1" +requires = "plugin_interface_v1" +archive(byte) = "domain_getinfo_v1.cma" +archive(native) = "domain_getinfo_v1.cmxa" diff --git a/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile new file mode 100644 index 0000000000..4f99e99e0f --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile @@ -0,0 +1,38 @@ +OCAML_TOPLEVEL=$(CURDIR)/../../.. +XEN_ROOT=$(OCAML_TOPLEVEL)/../.. +include $(OCAML_TOPLEVEL)/common.make + +CFLAGS += -I $(OCAML_TOPLEVEL)/libs -I $(OCAML_TOPLEVEL)/libs/xsd_glue +CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_xeninclude) $(APPEND_CFLAGS) +OCAMLOPTFLAGS += -opaque +OCAMLINCLUDE += -I ./ -I ../ + +OBJS = domain_getinfo_v1 +INTF = $(foreach obj, $(OBJS),$(obj).cmi) +LIBS = domain_getinfo_v1.cmxa domain_getinfo_v1.cmxs + +LIBS_xsd_glue = $(call xenlibs-ldflags-ldlibs,xenctrl) + +all: $(INTF) $(LIBS) $(PROGRAMS) + +bins: $(PROGRAMS) + +libs: $(LIBS) + +domain_getinfo_v1_OBJS = $(OBJS) +domain_getinfo_v1 = $(OBJS) +domain_getinfo_v1_C_OBJS = domain_getinfo_stubs_v1 + +OCAML_DYN_LIBRARY = domain_getinfo_v1 + +.PHONY: install +install: $(LIBS) META + $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC)/ocaml/xsd_glue/xenctrl_plugin + $(INSTALL_PROG) domain_getinfo_v1.cmxs $(DESTDIR)$(LIBEXEC)/ocaml/xsd_glue/xenctrl_plugin + +.PHONY: uninstall +uninstall: + rm -f $(DESTDIR)$(LIBEXEC)/ocaml/xsd_glue/xenctrl_plugin/domain_getinfo_v1.cmxs + +include $(OCAML_TOPLEVEL)/Makefile.rules + diff --git a/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_stubs_v1.c b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_stubs_v1.c new file mode 100644 index 0000000000..1a87849c83 --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_stubs_v1.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: LGPL-2.1-only WITH OCaml-LGPL-linking-exception */ + +#define _GNU_SOURCE + +#include +#include +#include + +#define CAML_NAME_SPACE +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "xen-caml-compat.h" + +static inline xc_interface *xsd_glue_xch_of_val(value v) +{ + xc_interface *xch = *(xc_interface **)Data_custom_val(v); + + return xch; +} + +static void xsd_glue_xenctrl_finalize(value v) +{ + xc_interface *xch = xsd_glue_xch_of_val(v); + + xc_interface_close(xch); +} + +static struct custom_operations xsd_glue_xenctrl_ops = { + .identifier = "xsd_glue.domain_getinfo_v1.xenctrl", + .finalize = xsd_glue_xenctrl_finalize, + .compare = custom_compare_default, /* Can't compare */ + .hash = custom_hash_default, /* Can't hash */ + .serialize = custom_serialize_default, /* Can't serialize */ + .deserialize = custom_deserialize_default, /* Can't deserialize */ + .compare_ext = custom_compare_ext_default, /* Can't compare */ +}; + +static void xsd_glue_failwith(xc_interface *xch, + const char *func, + unsigned int line) +{ + const xc_error *error = xch ? xc_get_last_error(xch) : NULL; + char *str = NULL; + CAMLparam0(); + CAMLlocal1(msg); + +#define ERR (error && error->code != XC_ERROR_NONE) + + int ret = asprintf(&str, + "%d: %s%s%s - called from %s:%u", + ERR ? error->code : errno, + ERR ? xc_error_code_to_desc(error->code) : strerror(errno), + ERR ? ": " : "", + ERR ? error->message : "", + func, line); + +#undef ERR + + if (!*str || (ret == -1)) + caml_raise_out_of_memory(); + + msg = caml_copy_string(str); + free(str); + + caml_raise_with_arg(*caml_named_value("xsg.error_v1"), msg); +} +#define xsd_glue_failwith(xch) xsd_glue_failwith(xch, __func__, __LINE__) + +CAMLprim value stub_xsd_glue_xc_interface_open(value unit) +{ + CAMLparam1(unit); + CAMLlocal1(result); + xc_interface *xch; + + result = caml_alloc_custom(&xsd_glue_xenctrl_ops, sizeof(xch), 0, 1); + + caml_enter_blocking_section(); + xch = xc_interface_open(NULL, NULL, 0); + caml_leave_blocking_section(); + + if (!xch) + xsd_glue_failwith(xch); + + *(xc_interface **)Data_custom_val(result) = xch; + + CAMLreturn(result); +} + +static value xsd_glue_alloc_domaininfo(const xc_domaininfo_t *info) +{ + CAMLparam0(); + CAMLlocal1(result); + + result = caml_alloc_tuple(4); + + Store_field(result, 0, Val_int(info->domain)); + Store_field(result, 1, Val_bool(info->flags & XEN_DOMINF_dying)); + Store_field(result, 2, Val_bool(info->flags & XEN_DOMINF_shutdown)); + Store_field(result, 3, Val_int(MASK_EXTR(info->flags, XEN_DOMINF_shutdownmask))); + + CAMLreturn(result); +} + +CAMLprim value stub_xsd_glue_xc_domain_getinfo(value xch_val, value domid) +{ + CAMLparam2(xch_val, domid); + CAMLlocal1(result); + xc_interface *xch = xsd_glue_xch_of_val(xch_val); + xc_domaininfo_t info; + int ret; + int domid_c = Int_val(domid); + + caml_enter_blocking_section(); + ret = xc_domain_getinfo_single(xch, domid_c, &info); + caml_leave_blocking_section(); + + if (ret < 0) + xsd_glue_failwith(xch); + + result = xsd_glue_alloc_domaininfo(&info); + + CAMLreturn(result); +} + +CAMLprim value stub_xsd_glue_xc_domain_getinfolist(value xch_val) +{ + CAMLparam1(xch_val); + CAMLlocal1(result); + xc_interface *xch = xsd_glue_xch_of_val(xch_val); + xc_domaininfo_t *info; + int i, retval; + + /* get the minimum number of allocate byte we need and bump it up to page boundary */ + info = malloc(sizeof(xc_domaininfo_t) * DOMID_FIRST_RESERVED); + if ( !info ) + caml_raise_out_of_memory(); + + caml_enter_blocking_section(); + retval = xc_domain_getinfolist(xch, 0, DOMID_FIRST_RESERVED, info); + caml_leave_blocking_section(); + + if (retval <= 0) { + free(info); + xsd_glue_failwith(xch); + } + + result = caml_alloc(retval, 0); + for (i = 0; i < retval; i++) { + caml_modify(&Field(result, i), xsd_glue_alloc_domaininfo(info + i)); + } + + free(info); + CAMLreturn(result); +} diff --git a/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_v1.ml b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_v1.ml new file mode 100644 index 0000000000..be50853c4b --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_v1.ml @@ -0,0 +1,35 @@ +(* SPDX-License-Identifier: LGPL-2.1-only WITH OCaml-LGPL-linking-exception *) +(** Minimal interface on top of unstable Xenctrl for Oxenstored's usage *) + +module P = Plugin_interface_v1 + +module M : P.Domain_getinfo_V1 = struct + exception Error of string + + type domid = int + type handle + + type domaininfo = { + domid : domid; + dying : bool; + shutdown : bool; + shutdown_code : int; + } + + external interface_open : unit -> handle = "stub_xsd_glue_xc_interface_open" + + external domain_getinfo : handle -> domid -> domaininfo + = "stub_xsd_glue_xc_domain_getinfo" + + external domain_getinfolist : handle -> domaininfo array + = "stub_xsd_glue_xc_domain_getinfolist" + + let _ = Callback.register_exception "xsg.error_v1" (Error "register_callback") +end + +let () = + Printf.ksprintf !P.logging_function "Registration of %s plugin started\n%!" + __MODULE__; + P.register_plugin_v1 (module M : P.Domain_getinfo_V1); + Printf.ksprintf !P.logging_function "Registration of %s plugin successful\n%!" + __MODULE__ diff --git a/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_v1.mli b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_v1.mli new file mode 100644 index 0000000000..465beda1a3 --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/domain_getinfo_v1.mli @@ -0,0 +1 @@ +(* SPDX-License-Identifier: LGPL-2.1-only WITH OCaml-LGPL-linking-exception *) diff --git a/tools/ocaml/libs/xsd_glue/plugin_interface_v1.ml b/tools/ocaml/libs/xsd_glue/plugin_interface_v1.ml new file mode 100644 index 0000000000..5ab98b83bd --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/plugin_interface_v1.ml @@ -0,0 +1,30 @@ +(* SPDX-License-Identifier: LGPL-2.1-only WITH OCaml-LGPL-linking-exception *) + +module type Domain_getinfo_V1 = sig + exception Error of string + + type domid = int + type handle + + type domaininfo = { + domid : domid; + dying : bool; + shutdown : bool; + shutdown_code : int; + } + + val interface_open : unit -> handle + val domain_getinfo : handle -> domid -> domaininfo + val domain_getinfolist : handle -> domaininfo array +end + +let ignore_logging : string -> unit = ignore +let logging_function = ref ignore_logging +let register_logging_function func = logging_function := func +let plugin_implementation_v1 : (module Domain_getinfo_V1) option ref = ref None +let register_plugin_v1 m = plugin_implementation_v1 := Some m + +let get_plugin_v1 () : (module Domain_getinfo_V1) = + match !plugin_implementation_v1 with + | Some s -> s + | None -> failwith "No plugin loaded" diff --git a/tools/ocaml/libs/xsd_glue/plugin_interface_v1.mli b/tools/ocaml/libs/xsd_glue/plugin_interface_v1.mli new file mode 100644 index 0000000000..69f91510f7 --- /dev/null +++ b/tools/ocaml/libs/xsd_glue/plugin_interface_v1.mli @@ -0,0 +1,38 @@ +(* SPDX-License-Identifier: LGPL-2.1-only WITH OCaml-LGPL-linking-exception *) + +(** To avoid breaking the plugin interface, this module needs to be + standalone and can't rely on any other Xen library. Even unrelated + changes in the interfaces of those modules would change the hash + of this interface and break the plugin system. + It can only depend on Stdlib, therefore all of the types (domid, + domaininfo etc.) are redefined here instead of using alternatives + defined elsewhere. + + NOTE: The signature of this interface should not be changed (no + functions or types can be added, modified, or removed). If + underlying Xenctrl changes require a new interface, a V2 with a + corresponding plugin should be created. +*) + +module type Domain_getinfo_V1 = sig + exception Error of string + + type domid = int + type handle + + type domaininfo = { + domid : domid; + dying : bool; + shutdown : bool; + shutdown_code : int; + } + + val interface_open : unit -> handle + val domain_getinfo : handle -> domid -> domaininfo + val domain_getinfolist : handle -> domaininfo array +end + +val register_logging_function : (string -> unit) -> unit +val logging_function : (string -> unit) ref +val register_plugin_v1 : (module Domain_getinfo_V1) -> unit +val get_plugin_v1 : unit -> (module Domain_getinfo_V1) From patchwork Mon Sep 9 12:02:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrii Sultanov X-Patchwork-Id: 13796876 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5C8A9ECE57E for ; Mon, 9 Sep 2024 12:03:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.794382.1203294 (Exim 4.92) (envelope-from ) id 1snd6n-00016K-20; Mon, 09 Sep 2024 12:03:05 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 794382.1203294; Mon, 09 Sep 2024 12:03:05 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1snd6m-00016D-Vf; Mon, 09 Sep 2024 12:03:04 +0000 Received: by outflank-mailman (input) for mailman id 794382; Mon, 09 Sep 2024 12:03:03 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1snd6l-0000ce-Ha for xen-devel@lists.xenproject.org; Mon, 09 Sep 2024 12:03:03 +0000 Received: from mail-ed1-x52c.google.com (mail-ed1-x52c.google.com [2a00:1450:4864:20::52c]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 770a7cff-6ea3-11ef-a0b5-8be0dac302b0; Mon, 09 Sep 2024 14:03:02 +0200 (CEST) Received: by mail-ed1-x52c.google.com with SMTP id 4fb4d7f45d1cf-5c241feb80dso10152064a12.0 for ; Mon, 09 Sep 2024 05:03:03 -0700 (PDT) Received: from EMEAENGAAD87503.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a8d25d65742sm331603066b.216.2024.09.09.05.03.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Sep 2024 05:03:01 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 770a7cff-6ea3-11ef-a0b5-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1725883382; x=1726488182; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=V5YgYhePmve9+WOG0QJ+xJp2hifKt7rcNXrTDKjPMNw=; b=MgGAIX6hUaiLb09g1jFQlzIg/AkeAECQhpvsoa0irwd2cJYvDMrEGj+ii/nun8A981 AO6erf6Vz2nLrs/8r5u0pJcVKxRYaea+X1LKQQO09Qbrv6icorWgAgRpjtikdF2t9Obj vBURs3LbmnodxHAOtFQvNcdm7H8Q4n9KxqbSA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725883382; x=1726488182; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=V5YgYhePmve9+WOG0QJ+xJp2hifKt7rcNXrTDKjPMNw=; b=Gn8LeaC/zSxEi4WmnwQu1jMrU+RVseEeVKNjFxkasal0ONond6uPXUa98URhtxUBlo ragqLJvV2IxCNOm1kBECQ0A6mI/zyQzvrOuZj4zmTp5AjXviA+O7eyAWoyb6rTCeoROs XSiQ3Vv6Fsb7pkPcnWoaR6Xybi1oL4uP8sy3r/KeEPD/+lZBrgl/lUmB8mncRW6yEtXX hzEOZUY+x2SHKM0uPCcd4yN+emJtl4UyQ9uP7A83d3iooqNbt7xqYp6sasYYaj5HDoaW 1POIyjxnuZqJOM+BHdhw8KcQZoTMzD/Sr2W04Pfdmt8nQ/OvcQrWP7uqeygTBnH+TuRv yX0A== X-Gm-Message-State: AOJu0YwJr/3+eA+fmGqWhZunqb6lAiHmBc8ggwYPX5FF39DB4KlWbVL9 zm3V8PiI4JDOCipUxIgpUXiDjRBjG5lO+RK42SMNmZy4AIIn/ABOwSNyqJ+aRsPPRq8KQQ/Zu43 4 X-Google-Smtp-Source: AGHT+IEhKat/dVQxAoOE6/dZlJtqBM9eMnI0VlNRo38sAf0RhyCh7F+7UXxIYtY5adE1nPVHc/monQ== X-Received: by 2002:a17:907:7ba3:b0:a8d:6372:2d38 with SMTP id a640c23a62f3a-a8d63722f43mr166834066b.18.1725883381675; Mon, 09 Sep 2024 05:03:01 -0700 (PDT) From: Andrii Sultanov To: xen-devel@lists.xenproject.org Cc: Andrii Sultanov , Christian Lindig , David Scott , Anthony PERARD , Christian Lindig Subject: [PATCH v3 2/3] tools/oxenstored: Load the plugin for Xenctrl.domain_getinfo Date: Mon, 9 Sep 2024 13:02:41 +0100 Message-Id: <4da0d29b49325f3684c283219144f9fbf3c241d3.1725881488.git.andrii.sultanov@cloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Oxenstored dynamically loads the plugin provided in ocaml/libs/xsd_glue. The plugin is verified to be providing the specified plugin_interface during its loading. If a V2 of the plugin is produced, V1 will still be present, and a new version should only be loaded if it's verified to exist (New oxenstored can run in an environment with only V1 of the plugin). The plugin is not switched to as of yet, the old Xenctrl stubs are still used. Signed-off-by: Andrii Sultanov Acked-by: Christian Lindig --- * This commit is a result of the split of one oxenstored commit into two. * Remove configure and paths.m4 defines as suggested. * Reformat files appropriately * Use libexec/ocaml as the plugin root dir instead of libexec/bin tools/ocaml/xenstored/Makefile | 5 ++++- tools/ocaml/xenstored/domains.ml | 28 ++++++++++++++++++++++++++++ tools/ocaml/xenstored/paths.ml.in | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/tools/ocaml/xenstored/Makefile b/tools/ocaml/xenstored/Makefile index fa45305d8c..5e8210a906 100644 --- a/tools/ocaml/xenstored/Makefile +++ b/tools/ocaml/xenstored/Makefile @@ -15,7 +15,8 @@ OCAMLINCLUDE += \ -I $(OCAML_TOPLEVEL)/libs/xb \ -I $(OCAML_TOPLEVEL)/libs/mmap \ -I $(OCAML_TOPLEVEL)/libs/xc \ - -I $(OCAML_TOPLEVEL)/libs/eventchn + -I $(OCAML_TOPLEVEL)/libs/eventchn \ + -I $(OCAML_TOPLEVEL)/libs/xsd_glue LIBS = syslog.cma syslog.cmxa poll.cma poll.cmxa syslog_OBJS = syslog @@ -59,6 +60,7 @@ INTF = symbol.cmi trie.cmi syslog.cmi systemd.cmi poll.cmi XENSTOREDLIBS = \ unix.cmxa \ + dynlink.cmxa \ -ccopt -L -ccopt . syslog.cmxa \ -ccopt -L -ccopt . systemd.cmxa \ -ccopt -L -ccopt . poll.cmxa \ @@ -66,6 +68,7 @@ XENSTOREDLIBS = \ -ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/eventchn $(OCAML_TOPLEVEL)/libs/eventchn/xeneventchn.cmxa \ -ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/xc $(OCAML_TOPLEVEL)/libs/xc/xenctrl.cmxa \ -ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/xb $(OCAML_TOPLEVEL)/libs/xb/xenbus.cmxa \ + -ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/xsd_glue $(OCAML_TOPLEVEL)/libs/xsd_glue/plugin_interface_v1.cmxa \ -ccopt -L -ccopt $(XEN_ROOT)/tools/libs/ctrl PROGRAMS = oxenstored diff --git a/tools/ocaml/xenstored/domains.ml b/tools/ocaml/xenstored/domains.ml index 7a3056c364..c233065711 100644 --- a/tools/ocaml/xenstored/domains.ml +++ b/tools/ocaml/xenstored/domains.ml @@ -20,6 +20,34 @@ let warn fmt = Logging.warn "domains" fmt let xc = Xenctrl.interface_open () +let load_plug fname = + let fail_with fmt = Printf.ksprintf failwith fmt in + let fname = Dynlink.adapt_filename fname in + if Sys.file_exists fname then + try Dynlink.loadfile fname with + | Dynlink.Error err as e -> + error "ERROR loading plugin '%s': %s\n%!" fname + (Dynlink.error_message err); + raise e + | _ -> fail_with "Unknown error while loading plugin" + else fail_with "Plugin file '%s' does not exist" fname + +let () = + let plugins_dir = Paths.libexec ^ "/ocaml/xsd_glue/xenctrl_plugin/" in + let filepath = plugins_dir ^ "domain_getinfo_v1.cmxs" in + debug "Trying to load plugin '%s'\n%!" filepath; + let list_files = Sys.readdir plugins_dir in + debug "Directory listing of '%s'\n%!" plugins_dir ; + Array.iter (fun x -> debug "\t%s\n%!" x) list_files; + Dynlink.allow_only [ "Plugin_interface_v1" ]; + load_plug filepath + +module Plugin = + (val Plugin_interface_v1.get_plugin_v1 () + : Plugin_interface_v1.Domain_getinfo_V1) + +let handle = Plugin.interface_open () + type domains = { eventchn: Event.t; table: (Xenctrl.domid, Domain.t) Hashtbl.t; diff --git a/tools/ocaml/xenstored/paths.ml.in b/tools/ocaml/xenstored/paths.ml.in index 37949dc8f3..acb6ea4ca7 100644 --- a/tools/ocaml/xenstored/paths.ml.in +++ b/tools/ocaml/xenstored/paths.ml.in @@ -2,3 +2,4 @@ let xen_log_dir = "@XEN_LOG_DIR@" let xen_config_dir = "@XEN_CONFIG_DIR@" let xen_run_dir = "@XEN_RUN_DIR@" let xen_run_stored = "@XEN_RUN_STORED@" +let libexec = "@LIBEXEC@" From patchwork Mon Sep 9 12:02:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrii Sultanov X-Patchwork-Id: 13796873 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 04533ECE579 for ; Mon, 9 Sep 2024 12:03:12 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.794383.1203303 (Exim 4.92) (envelope-from ) id 1snd6o-0001Md-Ez; Mon, 09 Sep 2024 12:03:06 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 794383.1203303; Mon, 09 Sep 2024 12:03:06 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1snd6o-0001MS-BR; Mon, 09 Sep 2024 12:03:06 +0000 Received: by outflank-mailman (input) for mailman id 794383; Mon, 09 Sep 2024 12:03:05 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1snd6n-0000ce-0W for xen-devel@lists.xenproject.org; Mon, 09 Sep 2024 12:03:05 +0000 Received: from mail-ed1-x530.google.com (mail-ed1-x530.google.com [2a00:1450:4864:20::530]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 77e928c2-6ea3-11ef-a0b5-8be0dac302b0; Mon, 09 Sep 2024 14:03:04 +0200 (CEST) Received: by mail-ed1-x530.google.com with SMTP id 4fb4d7f45d1cf-5c25f01879fso5271130a12.1 for ; Mon, 09 Sep 2024 05:03:04 -0700 (PDT) Received: from EMEAENGAAD87503.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a8d25d65742sm331603066b.216.2024.09.09.05.03.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Sep 2024 05:03:03 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 77e928c2-6ea3-11ef-a0b5-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1725883383; x=1726488183; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Dx3O4MBTaAWxPdBDzrYnpKhE+MJx2y5yX5SXZjkXD0g=; b=hIkWvxPxIMiep35c3Uu1kHAnpsBwb5Oxoar1Ewv1FR7uhOm62hEpDm9FqCTPHrZrfW AGMYf2mdN+7s9olDFZ1kWntKd0Ou+o0O/6lzlJX+NzLvuGuIcF2xT7FKTK2neffnOkG5 P+DMKItn6/1KzGeCQvam8KILNQTlTfsPTd7Hc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725883383; x=1726488183; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Dx3O4MBTaAWxPdBDzrYnpKhE+MJx2y5yX5SXZjkXD0g=; b=RvysO2HI4LBKnSriiIugqeFpw6KxPIkDCzKj27fY49EjU5Kp8QEfx7KPFY/pMVOciM HGvW7DfXmGIQrlcO7gZzJDSSg9qTycigPXosO0/ansLPYdCv+7XgMxmSS4lDVTiVJPao u+vMJPLPYMtkMVftJxbbI/j9dgrRly/E1SEAQhB84UCru/7jdTbR8TtctLbeTBw6Xb9D SjenTt4AT6i/7/3MbxepANdi4tEZl40snGoxi9OhzyFSryriGSVMVGc788eSETNkcMrK Sd5ipNKIXjPw7Vlp/R5k6GnA/QAlILcXNkL2fHdGzCQ3RD8Riu6uULWakOJxoh4ZZ4fA N0lA== X-Gm-Message-State: AOJu0Yy3BYObGgbWqRQ2CR+qjkhgkHOP6WvRa927Wz//PUvx5uDnUW8S ywBO45TYlPAaZ4NpyL/N8BkL9+QNAkUcjMgIJ1fuXJSlEc9eMl7tBE5MV1DT5A+Y2L4cZLTHkSe e X-Google-Smtp-Source: AGHT+IEN/G6OLfZtDKoYK25jJ/F4A+BFKt1jKuOHvs7Rc1f6vxHSp0AV604sumzAKQkn63Dwa0/mWg== X-Received: by 2002:a17:907:e90:b0:a7a:9447:3e8c with SMTP id a640c23a62f3a-a8a885bddf2mr663727566b.3.1725883383362; Mon, 09 Sep 2024 05:03:03 -0700 (PDT) From: Andrii Sultanov To: xen-devel@lists.xenproject.org Cc: Andrii Sultanov , Christian Lindig , David Scott , Anthony PERARD , Christian Lindig Subject: [PATCH v3 3/3] tools/oxenstored: Switch to using the plugin for Xenctrl.domain_getinfo Date: Mon, 9 Sep 2024 13:02:42 +0100 Message-Id: <23bc7f3e81dd89f8d5d6fd5f27d5dca0125b69a2.1725881488.git.andrii.sultanov@cloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Also run 'make format' on the file to reformat an adjacent block of code correctly. Signed-off-by: Andrii Sultanov Acked-by: Christian Lindig --- * This commit is a result of the split of one oxenstored commit into two. tools/ocaml/xenstored/domains.ml | 51 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/tools/ocaml/xenstored/domains.ml b/tools/ocaml/xenstored/domains.ml index c233065711..fabca00e6b 100644 --- a/tools/ocaml/xenstored/domains.ml +++ b/tools/ocaml/xenstored/domains.ml @@ -49,8 +49,8 @@ module Plugin = let handle = Plugin.interface_open () type domains = { - eventchn: Event.t; - table: (Xenctrl.domid, Domain.t) Hashtbl.t; + eventchn : Event.t; + table : (Plugin.domid, Domain.t) Hashtbl.t; (* N.B. the Queue module is not thread-safe but oxenstored is single-threaded. *) (* Domains queue up to regain conflict-credit; we have a queue for @@ -121,30 +121,29 @@ let cleanup doms = let notify = ref false in let dead_dom = ref [] in - Hashtbl.iter (fun id _ -> if id <> 0 then - try - let info = Xenctrl.domain_getinfo xc id in - if info.Xenctrl.shutdown || info.Xenctrl.dying then ( - debug "Domain %u died (dying=%b, shutdown %b -- code %d)" - id info.Xenctrl.dying info.Xenctrl.shutdown info.Xenctrl.shutdown_code; - if info.Xenctrl.dying then - dead_dom := id :: !dead_dom - else - notify := true; - ) - with Xenctrl.Error _ -> - debug "Domain %u died -- no domain info" id; - dead_dom := id :: !dead_dom; - ) doms.table; - List.iter (fun id -> - let dom = Hashtbl.find doms.table id in - Domain.close dom; - Hashtbl.remove doms.table id; - if dom.Domain.conflict_credit <= !Define.conflict_burst_limit - then ( - remove_from_queue dom doms.doms_with_conflict_penalty; - if (dom.Domain.conflict_credit <= 0.) then remove_from_queue dom doms.doms_conflict_paused - ) + Hashtbl.iter + (fun id _ -> + if id <> 0 then ( + try + let info = Plugin.domain_getinfo handle id in + if info.Plugin.shutdown || info.Plugin.dying then ( + debug "Domain %u died (dying=%b, shutdown %b -- code %d)" id + info.Plugin.dying info.Plugin.shutdown info.Plugin.shutdown_code; + if info.Plugin.dying then dead_dom := id :: !dead_dom else notify := true) + with Plugin.Error _ -> + debug "Domain %u died -- no domain info" id; + dead_dom := id :: !dead_dom)) + doms.table; + List.iter + (fun id -> + let dom = Hashtbl.find doms.table id in + Domain.close dom; + Hashtbl.remove doms.table id; + if dom.Domain.conflict_credit <= !Define.conflict_burst_limit + then ( + remove_from_queue dom doms.doms_with_conflict_penalty; + if (dom.Domain.conflict_credit <= 0.) then remove_from_queue dom doms.doms_conflict_paused + ) ) !dead_dom; !notify, !dead_dom