[PATCH v2 31/32] libluo: introduce luoctl

Pasha Tatashin posted 32 patches 2 months, 2 weeks ago
There is a newer version of this series
[PATCH v2 31/32] libluo: introduce luoctl
Posted by Pasha Tatashin 2 months, 2 weeks ago
From: Pratyush Yadav <ptyadav@amazon.de>

luoctl is a utility to interact with the LUO state machine. It currently
supports viewing and change the current state of LUO. This can be used
by scripts, tools, or developers to control LUO state during the live
update process.

Example usage:

    $ luoctl state
    normal
    $ luoctl prepare
    $ luoctl state
    prepared
    $ luoctl cancel
    $ luoctl state
    normal

Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 tools/lib/luo/Makefile       |   6 +-
 tools/lib/luo/cli/.gitignore |   1 +
 tools/lib/luo/cli/Makefile   |  18 ++++
 tools/lib/luo/cli/luoctl.c   | 178 +++++++++++++++++++++++++++++++++++
 4 files changed, 202 insertions(+), 1 deletion(-)
 create mode 100644 tools/lib/luo/cli/.gitignore
 create mode 100644 tools/lib/luo/cli/Makefile
 create mode 100644 tools/lib/luo/cli/luoctl.c

diff --git a/tools/lib/luo/Makefile b/tools/lib/luo/Makefile
index e851c37d3d0a..e8f6bd3b9e85 100644
--- a/tools/lib/luo/Makefile
+++ b/tools/lib/luo/Makefile
@@ -13,7 +13,7 @@ LIB_NAME = libluo
 STATIC_LIB = $(LIB_NAME).a
 SHARED_LIB = $(LIB_NAME).so
 
-.PHONY: all clean install
+.PHONY: all clean install cli
 
 all: $(STATIC_LIB) $(SHARED_LIB)
 
@@ -26,8 +26,12 @@ $(SHARED_LIB): $(OBJS)
 %.o: %.c $(HEADERS)
 	$(CC) $(CFLAGS) -c $< -o $@
 
+cli: $(STATIC_LIB)
+	$(MAKE) -C cli
+
 clean:
 	rm -f $(OBJS) $(STATIC_LIB) $(SHARED_LIB)
+	$(MAKE) -C cli clean
 
 install: all
 	install -d $(DESTDIR)/usr/local/lib
diff --git a/tools/lib/luo/cli/.gitignore b/tools/lib/luo/cli/.gitignore
new file mode 100644
index 000000000000..3a5e2d287f60
--- /dev/null
+++ b/tools/lib/luo/cli/.gitignore
@@ -0,0 +1 @@
+/luoctl
diff --git a/tools/lib/luo/cli/Makefile b/tools/lib/luo/cli/Makefile
new file mode 100644
index 000000000000..6c0cbf92a420
--- /dev/null
+++ b/tools/lib/luo/cli/Makefile
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+LUOCTL = luoctl
+INCLUDE_DIR = ../include
+HEADERS = $(wildcard $(INCLUDE_DIR)/*.h)
+
+CC = gcc
+CFLAGS = -Wall -Wextra -O2 -g -I$(INCLUDE_DIR)
+LDFLAGS = -L.. -l:libluo.a
+
+.PHONY: all clean
+
+all: $(LUOCTL)
+
+luoctl: luoctl.c ../libluo.a $(HEADERS)
+	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
+
+clean:
+	rm -f $(LUOCTL)
diff --git a/tools/lib/luo/cli/luoctl.c b/tools/lib/luo/cli/luoctl.c
new file mode 100644
index 000000000000..39ba0bdd44f0
--- /dev/null
+++ b/tools/lib/luo/cli/luoctl.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+/**
+ * @file luoctl.c
+ * @brief Simple utility to interact with LUO
+ *
+ * This utility allows viewing and controlling LUO state.
+ *
+ * Copyright (C) 2025 Amazon.com Inc. or its affiliates.
+ * Author: Pratyush Yadav <ptyadav@amazon.de>
+ */
+
+#include <libluo.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+
+#define fatal(fmt, ...)					\
+	do {						\
+		fprintf(stderr, "Error: " fmt, ##__VA_ARGS__);	\
+		exit(1);				\
+	} while (0)
+
+struct command {
+	char *name;
+	int (*handler)(void);
+};
+
+static void usage(const char *prog_name)
+{
+	printf("Usage: %s [command]\n\n", prog_name);
+	printf("Commands:\n");
+	printf("  state         - Show current LUO state\n");
+	printf("  prepare       - Prepare for live update\n");
+	printf("  cancel        - Cancel live update preparation\n");
+	printf("  finish        - Signal completion of restoration\n");
+}
+
+static enum liveupdate_state get_state(void)
+{
+	enum liveupdate_state state;
+	int ret;
+
+	ret = luo_get_state(&state);
+	if (ret)
+		fatal("failed to get LUO state: %s\n", strerror(-ret));
+
+	return state;
+}
+
+static int show_state(void)
+{
+	enum liveupdate_state state;
+
+	state = get_state();
+	printf("%s\n", luo_state_to_string(state));
+	return 0;
+}
+
+static int do_prepare(void)
+{
+	enum liveupdate_state state;
+	int ret;
+
+	state = get_state();
+	if (state != LIVEUPDATE_STATE_NORMAL)
+		fatal("can only switch to prepared state from normal state. Current state: %s\n",
+		      luo_state_to_string(state));
+
+	ret = luo_prepare();
+	if (ret)
+		fatal("failed to prepare for live update: %s\n", strerror(-ret));
+
+	return 0;
+}
+
+static int do_cancel(void)
+{
+	enum liveupdate_state state;
+	int ret;
+
+	state = get_state();
+	if (state != LIVEUPDATE_STATE_PREPARED)
+		fatal("can only cancel from normal state. Current state: %s\n",
+		      luo_state_to_string(state));
+
+	ret = luo_cancel();
+	if (ret)
+		fatal("failed to cancel live update: %s\n", strerror(-ret));
+
+	return 0;
+}
+
+static int do_finish(void)
+{
+	enum liveupdate_state state;
+	int ret;
+
+	state = get_state();
+	if (state != LIVEUPDATE_STATE_UPDATED)
+		fatal("can only finish from updated state. Current state: %s\n",
+		      luo_state_to_string(state));
+
+	ret = luo_finish();
+	if (ret)
+		fatal("failed to finish live update: %s\n", strerror(-ret));
+
+	return 0;
+}
+
+static struct command commands[] = {
+	{"state", show_state},
+	{"prepare", do_prepare},
+	{"cancel", do_cancel},
+	{"finish", do_finish},
+	{NULL, NULL},
+};
+
+int main(int argc, char *argv[])
+{
+	struct option long_options[] = {
+		{"help", no_argument, 0, 'h'},
+		{0, 0, 0, 0}
+	};
+	struct command *command;
+	int ret = -EINVAL, opt;
+	char *cmd;
+
+	if (!luo_is_available()) {
+		fprintf(stderr, "LUO is not available on this system\n");
+		return 1;
+	}
+
+	while ((opt = getopt_long(argc, argv, "ht:e:", long_options, NULL)) != -1) {
+		switch (opt) {
+		case 'h':
+			usage(argv[0]);
+			return 0;
+		default:
+			fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
+			return 1;
+		}
+	}
+
+	if (argc - optind != 1) {
+		usage(argv[0]);
+		return 1;
+	}
+
+	cmd = argv[optind];
+
+	ret = luo_init();
+	if (ret < 0) {
+		fprintf(stderr, "Failed to initialize LibLUO: %s\n", strerror(-ret));
+		return 1;
+	}
+
+	command = &commands[0];
+	while (command->name) {
+		if (!strcmp(cmd, command->name)) {
+			ret = command->handler();
+			break;
+		}
+		command++;
+	}
+
+	if (!command->name) {
+		fprintf(stderr, "Unknown command %s. Try '%s --help' for more information\n",
+			cmd, argv[0]);
+		ret = -EINVAL;
+	}
+
+	luo_cleanup();
+	return (ret < 0) ? 1 : 0;
+}
-- 
2.50.0.727.gbf7dc18ff4-goog
Re: [PATCH v2 31/32] libluo: introduce luoctl
Posted by Jason Gunthorpe 2 months, 1 week ago
On Wed, Jul 23, 2025 at 02:46:44PM +0000, Pasha Tatashin wrote:
> From: Pratyush Yadav <ptyadav@amazon.de>
> 
> luoctl is a utility to interact with the LUO state machine. It currently
> supports viewing and change the current state of LUO. This can be used
> by scripts, tools, or developers to control LUO state during the live
> update process.
>
> Example usage:
> 
>     $ luoctl state
>     normal
>     $ luoctl prepare
>     $ luoctl state
>     prepared
>     $ luoctl cancel
>     $ luoctl state
>     normal
> 
> Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> ---
>  tools/lib/luo/Makefile       |   6 +-
>  tools/lib/luo/cli/.gitignore |   1 +
>  tools/lib/luo/cli/Makefile   |  18 ++++
>  tools/lib/luo/cli/luoctl.c   | 178 +++++++++++++++++++++++++++++++++++
>  4 files changed, 202 insertions(+), 1 deletion(-)
>  create mode 100644 tools/lib/luo/cli/.gitignore
>  create mode 100644 tools/lib/luo/cli/Makefile
>  create mode 100644 tools/lib/luo/cli/luoctl.c

In the calls I thought the plan had changed to put libluo in its own
repository?

There is nothing tightly linked to the kernel here, I think it would
be easier on everyone to not add ordinary libraries to the kernel
tree.

Jason
Re: [PATCH v2 31/32] libluo: introduce luoctl
Posted by Thomas Gleixner 2 months, 1 week ago
On Tue, Jul 29 2025 at 13:14, Jason Gunthorpe wrote:
> On Wed, Jul 23, 2025 at 02:46:44PM +0000, Pasha Tatashin wrote:
>> From: Pratyush Yadav <ptyadav@amazon.de>
>>  tools/lib/luo/Makefile       |   6 +-
>>  tools/lib/luo/cli/.gitignore |   1 +
>>  tools/lib/luo/cli/Makefile   |  18 ++++
>>  tools/lib/luo/cli/luoctl.c   | 178 +++++++++++++++++++++++++++++++++++
>>  4 files changed, 202 insertions(+), 1 deletion(-)
>>  create mode 100644 tools/lib/luo/cli/.gitignore
>>  create mode 100644 tools/lib/luo/cli/Makefile
>>  create mode 100644 tools/lib/luo/cli/luoctl.c
>
> In the calls I thought the plan had changed to put libluo in its own
> repository?
>
> There is nothing tightly linked to the kernel here, I think it would
> be easier on everyone to not add ordinary libraries to the kernel
> tree.

As this is an evolving mechanism, having the corresponding library in
the kernel similar to what we do with perf and other things makes a lot
of sense.

Thanks,

        tglx
Re: [PATCH v2 31/32] libluo: introduce luoctl
Posted by Jason Gunthorpe 2 months, 1 week ago
On Tue, Jul 29, 2025 at 09:53:47PM +0200, Thomas Gleixner wrote:
> On Tue, Jul 29 2025 at 13:14, Jason Gunthorpe wrote:
> > On Wed, Jul 23, 2025 at 02:46:44PM +0000, Pasha Tatashin wrote:
> >> From: Pratyush Yadav <ptyadav@amazon.de>
> >>  tools/lib/luo/Makefile       |   6 +-
> >>  tools/lib/luo/cli/.gitignore |   1 +
> >>  tools/lib/luo/cli/Makefile   |  18 ++++
> >>  tools/lib/luo/cli/luoctl.c   | 178 +++++++++++++++++++++++++++++++++++
> >>  4 files changed, 202 insertions(+), 1 deletion(-)
> >>  create mode 100644 tools/lib/luo/cli/.gitignore
> >>  create mode 100644 tools/lib/luo/cli/Makefile
> >>  create mode 100644 tools/lib/luo/cli/luoctl.c
> >
> > In the calls I thought the plan had changed to put libluo in its own
> > repository?
> >
> > There is nothing tightly linked to the kernel here, I think it would
> > be easier on everyone to not add ordinary libraries to the kernel
> > tree.
> 
> As this is an evolving mechanism, having the corresponding library in
> the kernel similar to what we do with perf and other things makes a lot
> of sense.

If we did this everywhere we'd have hundreds of libraries in the
kernel tree and I would feel bad for all the distros that have to deal
with packaging such a thing :(

It is great for development but I'm not sure mono-repo directions are
so good for the overall ecosystem.

I understood perf had a special reason to be in the kernel tree? I
don't think there is any special here beyond it is new.

Jason
Re: [PATCH v2 31/32] libluo: introduce luoctl
Posted by Steven Rostedt 2 months, 1 week ago
On Tue, 29 Jul 2025 19:21:57 -0300
Jason Gunthorpe <jgg@nvidia.com> wrote:

> > As this is an evolving mechanism, having the corresponding library in
> > the kernel similar to what we do with perf and other things makes a lot
> > of sense.  
> 
> If we did this everywhere we'd have hundreds of libraries in the
> kernel tree and I would feel bad for all the distros that have to deal
> with packaging such a thing :(
> 
> It is great for development but I'm not sure mono-repo directions are
> so good for the overall ecosystem.

I have to agree here. When libtraceevent was in the kernel, it was a pain
to orchestrate releases with distros. When it was moved out of the kernel,
it made it much easier to manage.

The main issue was versioning numbers. I know the kernel versioning is
simply just "hey we added more stuff" and the numbers are meaningless.

But a library usually has a different cycle than the kernel. If it doesn't
have any changes from one kernel release to the next, the distros will make
a new version anyway, as each kernel release means a new library release.

This luoctl.c isn't even a library, as it has a "main()" and looks to me
like an application. So my question is, why is it in tools/lib?

-- Steve
Re: [PATCH v2 31/32] libluo: introduce luoctl
Posted by Pratyush Yadav 2 months, 1 week ago
On Tue, Jul 29 2025, Steven Rostedt wrote:

> On Tue, 29 Jul 2025 19:21:57 -0300
> Jason Gunthorpe <jgg@nvidia.com> wrote:
>
>> > As this is an evolving mechanism, having the corresponding library in
>> > the kernel similar to what we do with perf and other things makes a lot
>> > of sense.  
>> 
>> If we did this everywhere we'd have hundreds of libraries in the
>> kernel tree and I would feel bad for all the distros that have to deal
>> with packaging such a thing :(
>> 
>> It is great for development but I'm not sure mono-repo directions are
>> so good for the overall ecosystem.
>
> I have to agree here. When libtraceevent was in the kernel, it was a pain
> to orchestrate releases with distros. When it was moved out of the kernel,
> it made it much easier to manage.
>
> The main issue was versioning numbers. I know the kernel versioning is
> simply just "hey we added more stuff" and the numbers are meaningless.
>
> But a library usually has a different cycle than the kernel. If it doesn't
> have any changes from one kernel release to the next, the distros will make
> a new version anyway, as each kernel release means a new library release.
>
> This luoctl.c isn't even a library, as it has a "main()" and looks to me
> like an application. So my question is, why is it in tools/lib?

luoctl isn't the library, it is a user of it. See previous patches for
the main library. Don't get too excited though, it is only a thin
wrapper around the ioctls. The more interesting stuff is in patch 32
which shows the API in action.

To add some context: one of the reasons to include it in the series as
an RFC at the end was to showcase the userspace side of the API and have
a way for people to see how it can be used. Seeing an API in action
provides useful context for reviewing patches.

I think Pasha forgot to add the RFC tags when he created v2, since it is
only meant to be RFC right now and not proper patches.

The point of moving out of tree was also brought up in the live update
call and I agree with Jason's feedback on it. The plan is to drop it
from the series in the next revision, and just leave a reference to it
in the cover letter instead.

-- 
Regards,
Pratyush Yadav
Re: [PATCH v2 31/32] libluo: introduce luoctl
Posted by Pasha Tatashin 2 months ago
> To add some context: one of the reasons to include it in the series as
> an RFC at the end was to showcase the userspace side of the API and have
> a way for people to see how it can be used. Seeing an API in action
> provides useful context for reviewing patches.
>
> I think Pasha forgot to add the RFC tags when he created v2, since it is
> only meant to be RFC right now and not proper patches.

Correct, I accidently removed RFC from memfd patches in the version. I
will include memfd preservation as RFCv1 in v3 submission.

>
> The point of moving out of tree was also brought up in the live update
> call and I agree with Jason's feedback on it. The plan is to drop it
> from the series in the next revision, and just leave a reference to it
> in the cover letter instead.

 I will drop libluo/luoctl and will add a pointer to an external repo
where they can be accessed from.

Pasha
Re: [PATCH v2 31/32] libluo: introduce luoctl
Posted by Pratyush Yadav 2 months ago
Hi Pasha,

On Tue, Aug 05 2025, Pasha Tatashin wrote:

>> To add some context: one of the reasons to include it in the series as
>> an RFC at the end was to showcase the userspace side of the API and have
>> a way for people to see how it can be used. Seeing an API in action
>> provides useful context for reviewing patches.
>>
>> I think Pasha forgot to add the RFC tags when he created v2, since it is
>> only meant to be RFC right now and not proper patches.
>
> Correct, I accidently removed RFC from memfd patches in the version. I
> will include memfd preservation as RFCv1 in v3 submission.

I didn't mean this for the memfd patches, only for libluo.

I think the memfd patches are in decent shape. They aren't pristine, but
I do think they are good enough to land and be improved iteratively.

If you think otherwise, then what do you reckon needs to be done to make
them _not_ RFC?

-- 
Regards,
Pratyush Yadav
Re: [PATCH v2 31/32] libluo: introduce luoctl
Posted by Pasha Tatashin 2 months ago
> I didn't mean this for the memfd patches, only for libluo.

Makes, sense, memfd patches are going to be submitted together with
the rest of the series as PATCH, sorry for confusion.

Pasha