import CS libguestfs-1.54.0-11.el9
This commit is contained in:
parent
59d72cefdc
commit
b64cb2c7bf
45
SOURCES/0018-lib-Print-kernel-utsname-in-debug-output.patch
Normal file
45
SOURCES/0018-lib-Print-kernel-utsname-in-debug-output.patch
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
From 19c4d1c8b9f278e054594660b5392d6c08a59d8f Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Mon, 10 Mar 2025 18:52:08 +0000
|
||||||
|
Subject: [PATCH] lib: Print kernel utsname in debug output
|
||||||
|
|
||||||
|
Useful for debugging problems caused by the host kernel. In
|
||||||
|
particular we were looking at a problem with passt creating a user
|
||||||
|
namespace but didn't know what exact kernel was being used.
|
||||||
|
|
||||||
|
(cherry picked from commit 31fa712aa07190f2c5ed789712b92b4be2d51488)
|
||||||
|
---
|
||||||
|
lib/launch.c | 6 ++++++
|
||||||
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/lib/launch.c b/lib/launch.c
|
||||||
|
index b9b76e50..9c44612d 100644
|
||||||
|
--- a/lib/launch.c
|
||||||
|
+++ b/lib/launch.c
|
||||||
|
@@ -36,6 +36,7 @@
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
+#include <sys/utsname.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
@@ -93,6 +94,7 @@ guestfs_impl_launch (guestfs_h *g)
|
||||||
|
struct backend *b;
|
||||||
|
CLEANUP_FREE char *backend = guestfs_get_backend (g);
|
||||||
|
int mask;
|
||||||
|
+ struct utsname utsname;
|
||||||
|
|
||||||
|
debug (g, "launch: program=%s", g->program);
|
||||||
|
if (STRNEQ (g->identifier, ""))
|
||||||
|
@@ -109,6 +111,10 @@ guestfs_impl_launch (guestfs_h *g)
|
||||||
|
if (mask >= 0)
|
||||||
|
debug (g, "launch: umask=0%03o", (unsigned) mask);
|
||||||
|
debug (g, "launch: euid=%ju", (uintmax_t) geteuid ());
|
||||||
|
+ if (uname (&utsname) == 0)
|
||||||
|
+ debug (g, "launch: host: %s %s %s %s %s",
|
||||||
|
+ utsname.sysname, utsname.nodename, utsname.release,
|
||||||
|
+ utsname.version, utsname.machine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Launch the appliance. */
|
@ -0,0 +1,29 @@
|
|||||||
|
From fa1c16528267c89de8a2ecebd44405cbd04fa0ee Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 11 Mar 2025 13:36:12 +0000
|
||||||
|
Subject: [PATCH] daemon: Fix loongarch64 detection on RHEL 9
|
||||||
|
|
||||||
|
$ rpm -q file
|
||||||
|
file-5.39-16.el9.x86_64
|
||||||
|
$ file ./test-data/binaries/bin-loongarch64-dynamic
|
||||||
|
./test-data/binaries/bin-loongarch64-dynamic: ELF 64-bit LSB pie executable, *unknown arch 0x102* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-loongarch-lp64d.so.1, BuildID[sha1]=7622a1a70bf6e697851ac3790557e1ca686459b5, for GNU/Linux 5.19.0, stripped
|
||||||
|
|
||||||
|
Updates: commit 729d6d55ea84494f0398d02450bd29c39c55f0bd
|
||||||
|
(cherry picked from commit 4176b2043f6cf65f8f5f4f7d6fa39beb9c0a22c6)
|
||||||
|
---
|
||||||
|
daemon/filearch.ml | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/filearch.ml b/daemon/filearch.ml
|
||||||
|
index 7dfc1cb7..e2bd5a2c 100644
|
||||||
|
--- a/daemon/filearch.ml
|
||||||
|
+++ b/daemon/filearch.ml
|
||||||
|
@@ -100,6 +100,8 @@ and canonical_elf_arch bits endianness elf_arch =
|
||||||
|
)
|
||||||
|
else if substr "LoongArch" then
|
||||||
|
sprintf "loongarch%s" bits
|
||||||
|
+ else if substr "*unknown arch 0x102*" then (* file command on RHEL 9 *)
|
||||||
|
+ sprintf "loongarch%s" bits
|
||||||
|
else
|
||||||
|
elf_arch
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
From 68cecb64758b8ff6d3af842721cb7cf706cb5d0c Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 16 Apr 2025 10:01:33 +0100
|
||||||
|
Subject: [PATCH] daemon: inspect: Add some debugging of /usr merging
|
||||||
|
|
||||||
|
(cherry picked from commit 2d1e8941301373d04a436333219358a72f9660f1)
|
||||||
|
---
|
||||||
|
daemon/inspect.ml | 15 ++++++++++++++-
|
||||||
|
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/daemon/inspect.ml b/daemon/inspect.ml
|
||||||
|
index f6e0ce1f..bec9d567 100644
|
||||||
|
--- a/daemon/inspect.ml
|
||||||
|
+++ b/daemon/inspect.ml
|
||||||
|
@@ -47,18 +47,21 @@ let rec inspect_os () =
|
||||||
|
* multiple filesystems. Gather all the inspected information in the
|
||||||
|
* inspect_fs struct of the root filesystem.
|
||||||
|
*)
|
||||||
|
+ eprintf "inspect_os: collect_coreos_inspection_info\n%!";
|
||||||
|
let fses = collect_coreos_inspection_info fses in
|
||||||
|
|
||||||
|
(* Check if the same filesystem was listed twice as root in fses.
|
||||||
|
* This may happen for the *BSD root partition where an MBR partition
|
||||||
|
* is a shadow of the real root partition probably /dev/sda5
|
||||||
|
*)
|
||||||
|
+ eprintf "inspect_os: check_for_duplicated_bsd_root\n%!";
|
||||||
|
let fses = check_for_duplicated_bsd_root fses in
|
||||||
|
|
||||||
|
(* For Linux guests with a separate /usr filesystem, merge some of the
|
||||||
|
* inspected information in that partition to the inspect_fs struct
|
||||||
|
* of the root filesystem.
|
||||||
|
*)
|
||||||
|
+ eprintf "inspect_os: collect_linux_inspection_info\n%!";
|
||||||
|
let fses = collect_linux_inspection_info fses in
|
||||||
|
|
||||||
|
(* Save what we found in a global variable. *)
|
||||||
|
@@ -194,6 +197,9 @@ and collect_linux_inspection_info fses =
|
||||||
|
* or other ways to identify the OS).
|
||||||
|
*)
|
||||||
|
and collect_linux_inspection_info_for fses root =
|
||||||
|
+ eprintf "inspect_os: collect_linux_inspection_info_for %s\n"
|
||||||
|
+ (string_of_location root.fs_location);
|
||||||
|
+
|
||||||
|
let root_fstab =
|
||||||
|
match root with
|
||||||
|
| { role = RoleRoot { fstab = f } } -> f
|
||||||
|
@@ -207,14 +213,21 @@ and collect_linux_inspection_info_for fses root =
|
||||||
|
(* This checks that this usr is found in the fstab of
|
||||||
|
* the root filesystem.
|
||||||
|
*)
|
||||||
|
+ eprintf "inspect_os: checking if %s found in fstab of this root\n"
|
||||||
|
+ (string_of_location usr_mp);
|
||||||
|
List.exists (
|
||||||
|
fun (mountable, _) ->
|
||||||
|
+ eprintf "inspect_os: collect_linux_inspection_info_for: \
|
||||||
|
+ compare %s = %s\n"
|
||||||
|
+ (Mountable.to_string usr_mp.mountable)
|
||||||
|
+ (Mountable.to_string mountable);
|
||||||
|
usr_mp.mountable = mountable
|
||||||
|
) root_fstab
|
||||||
|
| _ -> false
|
||||||
|
) fses in
|
||||||
|
|
||||||
|
- eprintf "collect_linux_inspection_info_for: merging:\n%sinto:\n%s"
|
||||||
|
+ eprintf "inspect_os: collect_linux_inspection_info_for: merging:\n\
|
||||||
|
+ %sinto:\n%s"
|
||||||
|
(string_of_fs usr) (string_of_fs root);
|
||||||
|
merge usr root;
|
||||||
|
root
|
490
SOURCES/0021-generator-Implement-struct-FDevice-type.patch
Normal file
490
SOURCES/0021-generator-Implement-struct-FDevice-type.patch
Normal file
@ -0,0 +1,490 @@
|
|||||||
|
From 4e27b259c166d87a57d133a79b8eed3b556288b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 16 Apr 2025 11:35:13 +0100
|
||||||
|
Subject: [PATCH] generator: Implement struct FDevice type
|
||||||
|
|
||||||
|
This acts just like FString except that we do reverse device name
|
||||||
|
translation on it. The only use is in the 'pvs-full' API where we
|
||||||
|
will use it (in a subsequent commit) to reverse translate the pv_name
|
||||||
|
field (a device name) before returning it from the daemon.
|
||||||
|
|
||||||
|
Compare this to the 'pvs' API which also returns a list of device
|
||||||
|
names, but using the generator's 'RStructList (RDevice,...)' return
|
||||||
|
type, where RDevice is similarly reverse translated.
|
||||||
|
|
||||||
|
Note in the library-side bindings, because the name has already been
|
||||||
|
translated in the daemon, we just treat it exactly the same as
|
||||||
|
FString. The vast majority of this patch is this mechanical change.
|
||||||
|
|
||||||
|
(cherry picked from commit 0ff73a42c7f4f309fbab11ea2e89ee6f0501367d)
|
||||||
|
---
|
||||||
|
generator/GObject.ml | 6 +++---
|
||||||
|
generator/OCaml.ml | 6 ++----
|
||||||
|
generator/XDR.ml | 2 +-
|
||||||
|
generator/c.ml | 20 +++++++++-----------
|
||||||
|
generator/csharp.ml | 2 +-
|
||||||
|
generator/daemon.ml | 30 ++++++++++++++++++++++++++----
|
||||||
|
generator/erlang.ml | 2 +-
|
||||||
|
generator/golang.ml | 4 ++--
|
||||||
|
generator/java.ml | 7 ++++---
|
||||||
|
generator/lua.ml | 2 +-
|
||||||
|
generator/perl.ml | 4 ++--
|
||||||
|
generator/php.ml | 4 ++--
|
||||||
|
generator/python.ml | 2 +-
|
||||||
|
generator/ruby.ml | 4 ++--
|
||||||
|
generator/rust.ml | 6 +++---
|
||||||
|
generator/types.ml | 1 +
|
||||||
|
generator/types.mli | 1 +
|
||||||
|
17 files changed, 62 insertions(+), 41 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/generator/GObject.ml b/generator/GObject.ml
|
||||||
|
index 6c74b31b..e7462c0e 100644
|
||||||
|
--- a/generator/GObject.ml
|
||||||
|
+++ b/generator/GObject.ml
|
||||||
|
@@ -206,7 +206,7 @@ let generate_gobject_struct_header filename typ cols () =
|
||||||
|
pr " * @%s: An unsigned 64-bit integer\n" n
|
||||||
|
| n, FInt64 ->
|
||||||
|
pr " * @%s: A signed 64-bit integer\n" n
|
||||||
|
- | n, FString ->
|
||||||
|
+ | n, (FString|FDevice) ->
|
||||||
|
pr " * @%s: A NULL-terminated string\n" n
|
||||||
|
| n, FBuffer ->
|
||||||
|
pr " * @%s: A GByteArray\n" n
|
||||||
|
@@ -231,7 +231,7 @@ let generate_gobject_struct_header filename typ cols () =
|
||||||
|
pr " guint64 %s;\n" n
|
||||||
|
| n, FInt64 ->
|
||||||
|
pr " gint64 %s;\n" n
|
||||||
|
- | n, FString ->
|
||||||
|
+ | n, (FString|FDevice) ->
|
||||||
|
pr " gchar *%s;\n" n
|
||||||
|
| n, FBuffer ->
|
||||||
|
pr " GByteArray *%s;\n" n
|
||||||
|
@@ -1228,7 +1228,7 @@ guestfs_session_close (GuestfsSession *session, GError **err)
|
||||||
|
| n, FUUID ->
|
||||||
|
pr "%smemcpy (%s%s, %s%s, sizeof (%s%s));\n"
|
||||||
|
indent dst n src n dst n
|
||||||
|
- | n, FString ->
|
||||||
|
+ | n, (FString|FDevice) ->
|
||||||
|
pr "%sif (%s%s) %s%s = g_strdup (%s%s);\n"
|
||||||
|
indent src n dst n src n
|
||||||
|
| n, FBuffer ->
|
||||||
|
diff --git a/generator/OCaml.ml b/generator/OCaml.ml
|
||||||
|
index 1e6f603a..4ef07e27 100644
|
||||||
|
--- a/generator/OCaml.ml
|
||||||
|
+++ b/generator/OCaml.ml
|
||||||
|
@@ -512,7 +512,7 @@ copy_table (char * const * argv)
|
||||||
|
List.iteri (
|
||||||
|
fun i col ->
|
||||||
|
(match col with
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " v = caml_copy_string (%s->%s);\n" typ name
|
||||||
|
| name, FBuffer ->
|
||||||
|
pr " v = caml_alloc_initialized_string (%s->%s_len, %s->%s);\n"
|
||||||
|
@@ -839,9 +839,7 @@ and generate_ocaml_structure_decls () =
|
||||||
|
pr "type %s = {\n" typ;
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString -> pr " %s : string;\n" name
|
||||||
|
- | name, FBuffer -> pr " %s : string;\n" name
|
||||||
|
- | name, FUUID -> pr " %s : string;\n" name
|
||||||
|
+ | name, (FString|FDevice|FBuffer|FUUID) -> pr " %s : string;\n" name
|
||||||
|
| name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
|
||||||
|
| name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
|
||||||
|
| name, FChar -> pr " %s : char;\n" name
|
||||||
|
diff --git a/generator/XDR.ml b/generator/XDR.ml
|
||||||
|
index 566ba69e..e71d97f5 100644
|
||||||
|
--- a/generator/XDR.ml
|
||||||
|
+++ b/generator/XDR.ml
|
||||||
|
@@ -66,7 +66,7 @@ let generate_xdr () =
|
||||||
|
pr "struct guestfs_int_%s {\n" typ;
|
||||||
|
List.iter (function
|
||||||
|
| name, FChar -> pr " char %s;\n" name
|
||||||
|
- | name, FString -> pr " string %s<>;\n" name
|
||||||
|
+ | name, (FString|FDevice) -> pr " string %s<>;\n" name
|
||||||
|
| name, FBuffer -> pr " opaque %s<>;\n" name
|
||||||
|
| name, FUUID -> pr " opaque %s[32];\n" name
|
||||||
|
| name, FInt32 -> pr " int %s;\n" name
|
||||||
|
diff --git a/generator/c.ml b/generator/c.ml
|
||||||
|
index 09181028..124aeb6d 100644
|
||||||
|
--- a/generator/c.ml
|
||||||
|
+++ b/generator/c.ml
|
||||||
|
@@ -352,7 +352,7 @@ and generate_structs_pod () =
|
||||||
|
| name, FInt32 -> pr " int32_t %s;\n" name
|
||||||
|
| name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
|
||||||
|
| name, FInt64 -> pr " int64_t %s;\n" name
|
||||||
|
- | name, FString -> pr " char *%s;\n" name
|
||||||
|
+ | name, (FString|FDevice) -> pr " char *%s;\n" name
|
||||||
|
| name, FBuffer ->
|
||||||
|
pr " /* The next two fields describe a byte array. */\n";
|
||||||
|
pr " uint32_t %s_len;\n" name;
|
||||||
|
@@ -609,7 +609,7 @@ extern GUESTFS_DLL_PUBLIC void *guestfs_next_private (guestfs_h *g, const char *
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
| name, FChar -> pr " char %s;\n" name
|
||||||
|
- | name, FString -> pr " char *%s;\n" name
|
||||||
|
+ | name, (FString|FDevice) -> pr " char *%s;\n" name
|
||||||
|
| name, FBuffer ->
|
||||||
|
pr " uint32_t %s_len;\n" name;
|
||||||
|
pr " char *%s;\n" name
|
||||||
|
@@ -916,7 +916,7 @@ and generate_client_structs_compare () =
|
||||||
|
fun { s_name = typ; s_cols = cols } ->
|
||||||
|
let has_nonnumeric_cols =
|
||||||
|
let nonnumeric = function
|
||||||
|
- | _,(FString|FUUID|FBuffer) -> true
|
||||||
|
+ | _,(FString|FDevice|FUUID|FBuffer) -> true
|
||||||
|
| _,(FChar|FUInt32|FInt32|FUInt64|FBytes|FInt64|FOptPercent) -> false
|
||||||
|
in
|
||||||
|
List.exists nonnumeric cols in
|
||||||
|
@@ -932,7 +932,7 @@ and generate_client_structs_compare () =
|
||||||
|
);
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " r = strcmp (s1->%s, s2->%s);\n" name name;
|
||||||
|
pr " if (r != 0) return r;\n"
|
||||||
|
| name, FBuffer ->
|
||||||
|
@@ -1001,7 +1001,7 @@ and generate_client_structs_copy () =
|
||||||
|
fun { s_name = typ; s_cols = cols } ->
|
||||||
|
let has_boxed_cols =
|
||||||
|
let boxed = function
|
||||||
|
- | _,(FString|FBuffer) -> true
|
||||||
|
+ | _,(FString|FDevice|FBuffer) -> true
|
||||||
|
| _,(FChar|FUUID|FUInt32|FInt32|FUInt64|FBytes|FInt64|FOptPercent) ->
|
||||||
|
false
|
||||||
|
in
|
||||||
|
@@ -1014,8 +1014,7 @@ and generate_client_structs_copy () =
|
||||||
|
pr "{\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString
|
||||||
|
- | name, FBuffer -> pr " free (s->%s);\n" name
|
||||||
|
+ | name, (FString|FDevice|FBuffer) -> pr " free (s->%s);\n" name
|
||||||
|
| _, FChar
|
||||||
|
| _, FUUID
|
||||||
|
| _, FUInt32
|
||||||
|
@@ -1038,8 +1037,7 @@ and generate_client_structs_copy () =
|
||||||
|
pr "\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString
|
||||||
|
- | name, FBuffer -> pr " out->%s = NULL;\n" name
|
||||||
|
+ | name, (FString|FDevice|FBuffer) -> pr " out->%s = NULL;\n" name
|
||||||
|
| _, FChar
|
||||||
|
| _, FUUID
|
||||||
|
| _, FUInt32
|
||||||
|
@@ -1051,7 +1049,7 @@ and generate_client_structs_copy () =
|
||||||
|
) cols;
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " out->%s = strdup (inp->%s);\n" name name;
|
||||||
|
pr " if (out->%s == NULL) goto error;\n" name
|
||||||
|
| name, FBuffer ->
|
||||||
|
@@ -1234,7 +1232,7 @@ and generate_client_structs_print_c () =
|
||||||
|
);
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " fprintf (dest, \"%%s%s: %%s%%s\", indent, %s->%s, linesep);\n"
|
||||||
|
name typ name
|
||||||
|
| name, FUUID ->
|
||||||
|
diff --git a/generator/csharp.ml b/generator/csharp.ml
|
||||||
|
index 43579df5..6ab6c3c9 100644
|
||||||
|
--- a/generator/csharp.ml
|
||||||
|
+++ b/generator/csharp.ml
|
||||||
|
@@ -119,7 +119,7 @@ namespace Guestfs
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
| name, FChar -> pr " char %s;\n" name
|
||||||
|
- | name, FString -> pr " string %s;\n" name
|
||||||
|
+ | name, (FString | FDevice) -> pr " string %s;\n" name
|
||||||
|
| name, FBuffer ->
|
||||||
|
pr " uint %s_len;\n" name;
|
||||||
|
pr " string %s;\n" name
|
||||||
|
diff --git a/generator/daemon.ml b/generator/daemon.ml
|
||||||
|
index 9ab9e12d..0baa7708 100644
|
||||||
|
--- a/generator/daemon.ml
|
||||||
|
+++ b/generator/daemon.ml
|
||||||
|
@@ -442,15 +442,37 @@ let generate_daemon_stubs actions () =
|
||||||
|
pr " ret.%s.%s_val = r;\n" n n;
|
||||||
|
pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
|
||||||
|
name
|
||||||
|
- | RStruct (n, _) ->
|
||||||
|
+ | RStruct (n, typ) ->
|
||||||
|
+ (* XXX RStruct containing an FDevice field would require
|
||||||
|
+ * reverse device name translation. That is not implemented.
|
||||||
|
+ * See also RStructList immediately below this.
|
||||||
|
+ *)
|
||||||
|
+ let cols = (Structs.lookup_struct typ).s_cols in
|
||||||
|
+ assert (not (List.exists
|
||||||
|
+ (function (_, FDevice) -> true | _ -> false) cols));
|
||||||
|
pr " struct guestfs_%s_ret ret;\n" name;
|
||||||
|
pr " ret.%s = *r;\n" n;
|
||||||
|
pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
|
||||||
|
name;
|
||||||
|
pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
|
||||||
|
name
|
||||||
|
- | RStructList (n, _) ->
|
||||||
|
+ | RStructList (n, typ) ->
|
||||||
|
pr " struct guestfs_%s_ret ret;\n" name;
|
||||||
|
+ let cols = (Structs.lookup_struct typ).s_cols in
|
||||||
|
+ List.iter (
|
||||||
|
+ function
|
||||||
|
+ | (fname, FDevice) ->
|
||||||
|
+ pr " for (size_t i = 0; i < r->guestfs_int_%s_list_len; ++i) {\n"
|
||||||
|
+ typ;
|
||||||
|
+ pr " char *field = r->guestfs_int_%s_list_val[i].%s;\n"
|
||||||
|
+ typ fname;
|
||||||
|
+ pr " char *rr = reverse_device_name_translation (field);\n";
|
||||||
|
+ pr " if (!rr) abort ();\n";
|
||||||
|
+ pr " free (field);\n";
|
||||||
|
+ pr " r->guestfs_int_%s_list_val[i].%s = rr;\n" typ fname;
|
||||||
|
+ pr " }\n";
|
||||||
|
+ | _ -> ()
|
||||||
|
+ ) cols;
|
||||||
|
pr " ret.%s = *r;\n" n;
|
||||||
|
pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
|
||||||
|
name;
|
||||||
|
@@ -619,7 +641,7 @@ let generate_daemon_caml_stubs () =
|
||||||
|
fun i ->
|
||||||
|
pr " v = Field (retv, %d);\n" i;
|
||||||
|
function
|
||||||
|
- | n, (FString|FUUID) ->
|
||||||
|
+ | n, (FString|FDevice|FUUID) ->
|
||||||
|
pr " ret->%s = strdup (String_val (v));\n" n;
|
||||||
|
pr " if (ret->%s == NULL) return NULL;\n" n
|
||||||
|
| n, FBuffer ->
|
||||||
|
@@ -986,7 +1008,7 @@ let generate_daemon_lvm_tokenization () =
|
||||||
|
pr " if (*p) next = p+1; else next = NULL;\n";
|
||||||
|
pr " *p = '\\0';\n";
|
||||||
|
(match coltype with
|
||||||
|
- | FString ->
|
||||||
|
+ | FString | FDevice ->
|
||||||
|
pr " r->%s = strdup (tok);\n" name;
|
||||||
|
pr " if (r->%s == NULL) {\n" name;
|
||||||
|
pr " perror (\"strdup\");\n";
|
||||||
|
diff --git a/generator/erlang.ml b/generator/erlang.ml
|
||||||
|
index 65af75aa..864b3ff0 100644
|
||||||
|
--- a/generator/erlang.ml
|
||||||
|
+++ b/generator/erlang.ml
|
||||||
|
@@ -286,7 +286,7 @@ and generate_erlang_structs () =
|
||||||
|
List.iteri (
|
||||||
|
fun i col ->
|
||||||
|
(match col with
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " if (ei_x_encode_string (buff, %s->%s) != 0) return -1;\n" typ name
|
||||||
|
| name, FBuffer ->
|
||||||
|
pr " if (ei_x_encode_string_len (buff, %s->%s, %s->%s_len) != 0) return -1;\n"
|
||||||
|
diff --git a/generator/golang.ml b/generator/golang.ml
|
||||||
|
index 0d6a9236..a5b39f5d 100644
|
||||||
|
--- a/generator/golang.ml
|
||||||
|
+++ b/generator/golang.ml
|
||||||
|
@@ -248,7 +248,7 @@ func return_hashtable (argv **C.char) map[string]string {
|
||||||
|
let n = String.capitalize_ascii n in
|
||||||
|
match field with
|
||||||
|
| FChar -> pr " %s byte\n" n
|
||||||
|
- | FString -> pr " %s string\n" n
|
||||||
|
+ | FString | FDevice -> pr " %s string\n" n
|
||||||
|
| FBuffer -> pr " %s []byte\n" n
|
||||||
|
| FUInt32 -> pr " %s uint32\n" n
|
||||||
|
| FInt32 -> pr " %s int32\n" n
|
||||||
|
@@ -267,7 +267,7 @@ func return_hashtable (argv **C.char) map[string]string {
|
||||||
|
let gon = String.capitalize_ascii n in
|
||||||
|
match field with
|
||||||
|
| FChar -> pr " r.%s = byte (c.%s)\n" gon n
|
||||||
|
- | FString -> pr " r.%s = C.GoString (c.%s)\n" gon n
|
||||||
|
+ | FString | FDevice -> pr " r.%s = C.GoString (c.%s)\n" gon n
|
||||||
|
| FBuffer ->
|
||||||
|
pr " r.%s = C.GoBytes (unsafe.Pointer (c.%s), C.int (c.%s_len))\n"
|
||||||
|
gon n n
|
||||||
|
diff --git a/generator/java.ml b/generator/java.ml
|
||||||
|
index afcddf90..4b74203a 100644
|
||||||
|
--- a/generator/java.ml
|
||||||
|
+++ b/generator/java.ml
|
||||||
|
@@ -560,6 +560,7 @@ public class %s {
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
| name, FString
|
||||||
|
+ | name, FDevice
|
||||||
|
| name, FUUID
|
||||||
|
| name, FBuffer -> pr " public String %s;\n" name
|
||||||
|
| name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
|
||||||
|
@@ -947,7 +948,7 @@ and generate_java_struct_return typ jtyp cols =
|
||||||
|
pr " jr = (*env)->AllocObject (env, cl);\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
|
||||||
|
pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
|
||||||
|
| name, FUUID ->
|
||||||
|
@@ -997,7 +998,7 @@ and generate_java_struct_list_return typ jtyp cols =
|
||||||
|
fun (name, ftyp) ->
|
||||||
|
(* Get the field ID in 'fl'. *)
|
||||||
|
let java_field_type = match ftyp with
|
||||||
|
- | FString | FUUID | FBuffer -> "Ljava/lang/String;"
|
||||||
|
+ | FString | FDevice | FUUID | FBuffer -> "Ljava/lang/String;"
|
||||||
|
| FBytes | FUInt64 | FInt64 -> "J"
|
||||||
|
| FUInt32 | FInt32 -> "I"
|
||||||
|
| FOptPercent -> "F"
|
||||||
|
@@ -1007,7 +1008,7 @@ and generate_java_struct_list_return typ jtyp cols =
|
||||||
|
|
||||||
|
(* Assign the value to this field. *)
|
||||||
|
match ftyp with
|
||||||
|
- | FString ->
|
||||||
|
+ | FString | FDevice ->
|
||||||
|
pr " (*env)->SetObjectField (env, jfl, fl,\n";
|
||||||
|
pr " (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
|
||||||
|
| FUUID ->
|
||||||
|
diff --git a/generator/lua.ml b/generator/lua.ml
|
||||||
|
index 0d7e63be..685645ab 100644
|
||||||
|
--- a/generator/lua.ml
|
||||||
|
+++ b/generator/lua.ml
|
||||||
|
@@ -824,7 +824,7 @@ push_event (lua_State *L, uint64_t event)
|
||||||
|
(match field with
|
||||||
|
| FChar ->
|
||||||
|
pr " lua_pushlstring (L, &v->%s, 1);\n" n
|
||||||
|
- | FString ->
|
||||||
|
+ | FString | FDevice ->
|
||||||
|
pr " lua_pushstring (L, v->%s);\n" n
|
||||||
|
| FBuffer ->
|
||||||
|
pr " lua_pushlstring (L, v->%s, v->%s_len);\n" n n
|
||||||
|
diff --git a/generator/perl.ml b/generator/perl.ml
|
||||||
|
index 8b9834ef..e0edc249 100644
|
||||||
|
--- a/generator/perl.ml
|
||||||
|
+++ b/generator/perl.ml
|
||||||
|
@@ -607,7 +607,7 @@ and generate_perl_struct_list_code typ cols name style =
|
||||||
|
pr " hv = newHV ();\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " (void) hv_store (hv, \"%s\", %d, newSVpv (r->val[i].%s, 0), 0);\n"
|
||||||
|
name (String.length name) name
|
||||||
|
| name, FUUID ->
|
||||||
|
@@ -645,7 +645,7 @@ and generate_perl_struct_code typ cols name style =
|
||||||
|
pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
|
||||||
|
|
||||||
|
match col with
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " PUSHs (sv_2mortal (newSVpv (r->%s, 0)));\n"
|
||||||
|
name
|
||||||
|
| name, FBuffer ->
|
||||||
|
diff --git a/generator/php.ml b/generator/php.ml
|
||||||
|
index 99ec66c7..5023e0c5 100644
|
||||||
|
--- a/generator/php.ml
|
||||||
|
+++ b/generator/php.ml
|
||||||
|
@@ -616,7 +616,7 @@ and generate_php_struct_code typ cols =
|
||||||
|
pr " array_init (return_value);\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " guestfs_add_assoc_string (return_value, \"%s\", r->%s, 1);\n" name name
|
||||||
|
| name, FBuffer ->
|
||||||
|
pr " guestfs_add_assoc_stringl (return_value, \"%s\", r->%s, r->%s_len, 1);\n"
|
||||||
|
@@ -650,7 +650,7 @@ and generate_php_struct_list_code typ cols =
|
||||||
|
pr " array_init (z_elem);\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " guestfs_add_assoc_string (z_elem, \"%s\", r->val[c].%s, 1);\n"
|
||||||
|
name name
|
||||||
|
| name, FBuffer ->
|
||||||
|
diff --git a/generator/python.ml b/generator/python.ml
|
||||||
|
index ad02ea93..5534e74a 100644
|
||||||
|
--- a/generator/python.ml
|
||||||
|
+++ b/generator/python.ml
|
||||||
|
@@ -168,7 +168,7 @@ and generate_python_structs () =
|
||||||
|
pr " return NULL;\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " value = guestfs_int_py_fromstring (%s->%s);\n" typ name;
|
||||||
|
pr " if (value == NULL)\n";
|
||||||
|
pr " goto err;\n";
|
||||||
|
diff --git a/generator/ruby.ml b/generator/ruby.ml
|
||||||
|
index be3238f6..ea5a3194 100644
|
||||||
|
--- a/generator/ruby.ml
|
||||||
|
+++ b/generator/ruby.ml
|
||||||
|
@@ -526,7 +526,7 @@ and generate_ruby_struct_code typ cols =
|
||||||
|
pr " volatile VALUE rv = rb_hash_new ();\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
|
||||||
|
| name, FBuffer ->
|
||||||
|
pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
|
||||||
|
@@ -556,7 +556,7 @@ and generate_ruby_struct_list_code typ cols =
|
||||||
|
pr " volatile VALUE hv = rb_hash_new ();\n";
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
- | name, FString ->
|
||||||
|
+ | name, (FString|FDevice) ->
|
||||||
|
pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
|
||||||
|
| name, FBuffer ->
|
||||||
|
pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, r->val[i].%s_len));\n" name name name
|
||||||
|
diff --git a/generator/rust.ml b/generator/rust.ml
|
||||||
|
index 1f5cefa6..f4dcfd72 100644
|
||||||
|
--- a/generator/rust.ml
|
||||||
|
+++ b/generator/rust.ml
|
||||||
|
@@ -115,7 +115,7 @@ extern \"C\" {
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
| n, FChar -> pr " pub %s: i8,\n" n
|
||||||
|
- | n, FString -> pr " pub %s: String,\n" n
|
||||||
|
+ | n, (FString|FDevice) -> pr " pub %s: String,\n" n
|
||||||
|
| n, FBuffer -> pr " pub %s: Vec<u8>,\n" n
|
||||||
|
| n, FUInt32 -> pr " pub %s: u32,\n" n
|
||||||
|
| n, FInt32 -> pr " pub %s: i32,\n" n
|
||||||
|
@@ -130,7 +130,7 @@ extern \"C\" {
|
||||||
|
List.iter (
|
||||||
|
function
|
||||||
|
| n, FChar -> pr " %s: c_char,\n" n
|
||||||
|
- | n, FString -> pr " %s: *const c_char,\n" n
|
||||||
|
+ | n, (FString|FDevice) -> pr " %s: *const c_char,\n" n
|
||||||
|
| n, FBuffer ->
|
||||||
|
pr " %s_len: usize,\n" n;
|
||||||
|
pr " %s: *const c_char,\n" n;
|
||||||
|
@@ -154,7 +154,7 @@ extern \"C\" {
|
||||||
|
match x with
|
||||||
|
| n, FChar ->
|
||||||
|
pr "%s: (*raw).%s as i8,\n" n n;
|
||||||
|
- | n, FString ->
|
||||||
|
+ | n, (FString|FDevice) ->
|
||||||
|
pr "%s: char_ptr_to_string((*raw).%s)?,\n" n n;
|
||||||
|
| n, FBuffer ->
|
||||||
|
pr "%s: slice::from_raw_parts((*raw).%s as *const u8, (*raw).%s_len).to_vec(),\n" n n n
|
||||||
|
diff --git a/generator/types.ml b/generator/types.ml
|
||||||
|
index d9b00885..c901aa73 100644
|
||||||
|
--- a/generator/types.ml
|
||||||
|
+++ b/generator/types.ml
|
||||||
|
@@ -215,6 +215,7 @@ let defaults = { name = "";
|
||||||
|
type field =
|
||||||
|
| FChar (* C 'char' (really, a 7 bit byte). *)
|
||||||
|
| FString (* nul-terminated ASCII string, NOT NULL. *)
|
||||||
|
+ | FDevice (* device name, needs reverse transl. *)
|
||||||
|
| FBuffer (* opaque buffer of bytes, (char *, int) pair *)
|
||||||
|
| FUInt32
|
||||||
|
| FInt32
|
||||||
|
diff --git a/generator/types.mli b/generator/types.mli
|
||||||
|
index 0ce0d33b..0a4752d5 100644
|
||||||
|
--- a/generator/types.mli
|
||||||
|
+++ b/generator/types.mli
|
||||||
|
@@ -413,6 +413,7 @@ val defaults : action
|
||||||
|
type field =
|
||||||
|
| FChar (** C 'char' (really, a 7 bit byte). *)
|
||||||
|
| FString (** nul-terminated ASCII string, NOT NULL. *)
|
||||||
|
+ | FDevice (** device name, needs reverse transl. *)
|
||||||
|
| FBuffer (** opaque buffer of bytes, (char *, int) pair*)
|
||||||
|
| FUInt32
|
||||||
|
| FInt32
|
@ -0,0 +1,68 @@
|
|||||||
|
From b306532e7a4a3f235b24e5dab22ab36b849ac886 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 16 Apr 2025 11:50:37 +0100
|
||||||
|
Subject: [PATCH] generator: Use new FDevice type for the pvs-full pv_name
|
||||||
|
field
|
||||||
|
|
||||||
|
Remove the code which did explicit reverse device name translation,
|
||||||
|
and use the generator's code instead.
|
||||||
|
|
||||||
|
(cherry picked from commit 5a16d1120fb7b046974abde43b1c40250bfd1a95)
|
||||||
|
---
|
||||||
|
daemon/lvm.c | 29 +----------------------------
|
||||||
|
generator/structs.ml | 2 +-
|
||||||
|
2 files changed, 2 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/daemon/lvm.c b/daemon/lvm.c
|
||||||
|
index b8c01f71..7e76e17c 100644
|
||||||
|
--- a/daemon/lvm.c
|
||||||
|
+++ b/daemon/lvm.c
|
||||||
|
@@ -146,34 +146,7 @@ do_vgs (void)
|
||||||
|
guestfs_int_lvm_pv_list *
|
||||||
|
do_pvs_full (void)
|
||||||
|
{
|
||||||
|
- guestfs_int_lvm_pv_list *r;
|
||||||
|
- size_t i;
|
||||||
|
- char *din, *dout;
|
||||||
|
-
|
||||||
|
- r = parse_command_line_pvs ();
|
||||||
|
- if (r == NULL)
|
||||||
|
- /* parse_command_line_pvs has already called reply_with_error */
|
||||||
|
- return NULL;
|
||||||
|
-
|
||||||
|
- /* The pv_name fields contain device names which must be reverse
|
||||||
|
- * translated. The problem here is that the generator does not have
|
||||||
|
- * a "FMountable" field type in types.mli.
|
||||||
|
- */
|
||||||
|
- for (i = 0; i < r->guestfs_int_lvm_pv_list_len; ++i) {
|
||||||
|
- din = r->guestfs_int_lvm_pv_list_val[i].pv_name;
|
||||||
|
- if (din) {
|
||||||
|
- dout = reverse_device_name_translation (din);
|
||||||
|
- if (!dout) {
|
||||||
|
- /* reverse_device_name_translation has already called reply_with_error*/
|
||||||
|
- /* XXX memory leak here */
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
- r->guestfs_int_lvm_pv_list_val[i].pv_name = dout;
|
||||||
|
- free (din);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return r;
|
||||||
|
+ return parse_command_line_pvs ();
|
||||||
|
}
|
||||||
|
|
||||||
|
guestfs_int_lvm_vg_list *
|
||||||
|
diff --git a/generator/structs.ml b/generator/structs.ml
|
||||||
|
index c1408804..93a3ed03 100644
|
||||||
|
--- a/generator/structs.ml
|
||||||
|
+++ b/generator/structs.ml
|
||||||
|
@@ -35,7 +35,7 @@ type struc = {
|
||||||
|
* we have to pull out the LVM columns separately here.
|
||||||
|
*)
|
||||||
|
let lvm_pv_cols = [
|
||||||
|
- "pv_name", FString;
|
||||||
|
+ "pv_name", FDevice;
|
||||||
|
"pv_uuid", FUUID;
|
||||||
|
"pv_fmt", FString;
|
||||||
|
"pv_size", FBytes;
|
@ -0,0 +1,46 @@
|
|||||||
|
From 0d466cb25e86ab6f7f6838d35afb37b99f83e0e4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 16 Apr 2025 10:13:52 +0100
|
||||||
|
Subject: [PATCH] daemon: inspect: Resolve Ubuntu 22+ /dev/disk/by-uuid/ in
|
||||||
|
fstab
|
||||||
|
|
||||||
|
Ubuntu 22= uses /dev/disk/by-uuid/ followed by a filesystem UUID in
|
||||||
|
fstab entries. Resolve these to mountables.
|
||||||
|
|
||||||
|
A typical fstab entry looks like this:
|
||||||
|
|
||||||
|
# /boot was on /dev/vda2 during curtin installation
|
||||||
|
/dev/disk/by-uuid/b4e56462-5a64-4272-b76d-f5e58bd8f128 /boot ext4 defaults 0 1
|
||||||
|
|
||||||
|
The comment is generated by the installer and appears in the fstab.
|
||||||
|
This entry would be translated to /dev/sda2.
|
||||||
|
|
||||||
|
(cherry picked from commit 7a1ffd744b12c4c79fa1b78341ea714d831f4205)
|
||||||
|
---
|
||||||
|
daemon/inspect_fs_unix_fstab.ml | 13 +++++++++++++
|
||||||
|
1 file changed, 13 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
index f5817a31..45c62175 100644
|
||||||
|
--- a/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
+++ b/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
@@ -394,6 +394,19 @@ and resolve_fstab_device spec md_map os_type =
|
||||||
|
resolve_diskbyid part default
|
||||||
|
)
|
||||||
|
|
||||||
|
+ (* Ubuntu 22+ uses /dev/disk/by-uuid/ followed by a UUID. *)
|
||||||
|
+ else if String.is_prefix spec "/dev/disk/by-uuid/" then (
|
||||||
|
+ debug_matching "diskbyuuid";
|
||||||
|
+ let uuid = String.sub spec 18 (String.length spec - 18) in
|
||||||
|
+ try
|
||||||
|
+ (* Try a filesystem UUID. Unclear if this could be a partition UUID
|
||||||
|
+ * as well, but in the Ubuntu guest I tried it was an fs UUID XXX.
|
||||||
|
+ *)
|
||||||
|
+ Mountable.of_device (Findfs.findfs_uuid uuid)
|
||||||
|
+ with
|
||||||
|
+ Failure _ -> default
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
else if PCRE.matches re_freebsd_gpt spec then (
|
||||||
|
debug_matching "FreeBSD GPT";
|
||||||
|
(* group 1 (type) is not used *)
|
@ -0,0 +1,43 @@
|
|||||||
|
From 1b64c54b8a7f3a0ada0cc52fc74d800a55318112 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 16 Apr 2025 13:19:17 +0100
|
||||||
|
Subject: [PATCH] generator: Fix implementation of FUUID for OCaml functions
|
||||||
|
|
||||||
|
This was implemented wrongly. In the XDR protocol, UUIDs are fixed
|
||||||
|
buffers of length 32. We can just use memcpy to copy from the OCaml
|
||||||
|
string to the UUID, but we have to ensure the string length returned
|
||||||
|
by OCaml is correct (if not we just assert, it's an internal error).
|
||||||
|
|
||||||
|
(It didn't even compile before, so we know it was never used).
|
||||||
|
|
||||||
|
(cherry picked from commit bcd6b3ec3a1038d840e832732b3910f939566436)
|
||||||
|
---
|
||||||
|
generator/daemon.ml | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/generator/daemon.ml b/generator/daemon.ml
|
||||||
|
index 0baa7708..91decf40 100644
|
||||||
|
--- a/generator/daemon.ml
|
||||||
|
+++ b/generator/daemon.ml
|
||||||
|
@@ -606,6 +606,7 @@ let generate_daemon_caml_stubs () =
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <errno.h>
|
||||||
|
+#include <assert.h>
|
||||||
|
|
||||||
|
#include <caml/alloc.h>
|
||||||
|
#include <caml/callback.h>
|
||||||
|
@@ -641,9 +642,12 @@ let generate_daemon_caml_stubs () =
|
||||||
|
fun i ->
|
||||||
|
pr " v = Field (retv, %d);\n" i;
|
||||||
|
function
|
||||||
|
- | n, (FString|FDevice|FUUID) ->
|
||||||
|
+ | n, (FString|FDevice) ->
|
||||||
|
pr " ret->%s = strdup (String_val (v));\n" n;
|
||||||
|
pr " if (ret->%s == NULL) return NULL;\n" n
|
||||||
|
+ | n, FUUID ->
|
||||||
|
+ pr " assert (caml_string_length (v) == sizeof ret->%s);\n" n;
|
||||||
|
+ pr " memcpy (ret->%s, String_val (v), sizeof ret->%s);\n" n n
|
||||||
|
| n, FBuffer ->
|
||||||
|
pr " ret->%s_len = caml_string_length (v);\n" n;
|
||||||
|
pr " ret->%s = strdup (String_val (v));\n" n;
|
42
SOURCES/0025-Update-common-submodule.patch
Normal file
42
SOURCES/0025-Update-common-submodule.patch
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
From c7930f21405720f51d74efa9f6f7b9da0132a929 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 16 Apr 2025 21:31:49 +0100
|
||||||
|
Subject: [PATCH] Update common submodule
|
||||||
|
|
||||||
|
Richard W.M. Jones (1):
|
||||||
|
mlstdutils: Implement String.implode
|
||||||
|
---
|
||||||
|
common | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Submodule common e9eea65a..8aed7b6a:
|
||||||
|
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
|
||||||
|
index 86b21a7c..1177ff69 100644
|
||||||
|
--- a/common/mlstdutils/std_utils.ml
|
||||||
|
+++ b/common/mlstdutils/std_utils.ml
|
||||||
|
@@ -256,6 +256,12 @@ module String = struct
|
||||||
|
let map_chars f str =
|
||||||
|
List.map f (explode str)
|
||||||
|
|
||||||
|
+ let implode cs =
|
||||||
|
+ let n = List.length cs in
|
||||||
|
+ let b = Bytes.create n in
|
||||||
|
+ List.iteri (Bytes.unsafe_set b) cs;
|
||||||
|
+ Bytes.to_string b
|
||||||
|
+
|
||||||
|
let spaces n = String.make n ' '
|
||||||
|
|
||||||
|
let span str accept =
|
||||||
|
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
|
||||||
|
index a39ac5f3..6811b4bc 100644
|
||||||
|
--- a/common/mlstdutils/std_utils.mli
|
||||||
|
+++ b/common/mlstdutils/std_utils.mli
|
||||||
|
@@ -123,6 +123,8 @@ module String : sig
|
||||||
|
(** Explode a string into a list of characters. *)
|
||||||
|
val map_chars : (char -> 'a) -> string -> 'a list
|
||||||
|
(** Explode string, then map function over the characters. *)
|
||||||
|
+ val implode : char list -> string
|
||||||
|
+ (** Join list of characters into a single string. *)
|
||||||
|
val spaces : int -> string
|
||||||
|
(** [spaces n] creates a string of n spaces. *)
|
||||||
|
val span : string -> string -> int
|
659
SOURCES/0026-daemon-Rewrite-pvs-vgs-lvs-full-APIs-in-OCaml.patch
Normal file
659
SOURCES/0026-daemon-Rewrite-pvs-vgs-lvs-full-APIs-in-OCaml.patch
Normal file
@ -0,0 +1,659 @@
|
|||||||
|
From 80b2fcb243613bc16217b5908941ed2607f398fd Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 16 Apr 2025 10:41:59 +0100
|
||||||
|
Subject: [PATCH] daemon: Rewrite {pvs,vgs,lvs}-full APIs in OCaml
|
||||||
|
|
||||||
|
These were previously written in very convoluted C which had to deal
|
||||||
|
with parsing the crazy output of the "lvm" command. In fact the
|
||||||
|
parsing was so complex that it was generated by the generator. It's
|
||||||
|
easier to do this in OCaml.
|
||||||
|
|
||||||
|
These are basically legacy APIs. They cannot be expanded and LVM
|
||||||
|
already supports many more fields. We should replace these with APIs
|
||||||
|
for getting single named fields from LVM.
|
||||||
|
|
||||||
|
(cherry picked from commit a73f248369d35249a9324a0e0df9f7ccd1420d3f)
|
||||||
|
---
|
||||||
|
.gitignore | 2 +-
|
||||||
|
daemon/Makefile.am | 5 +-
|
||||||
|
daemon/lvm.c | 22 ----
|
||||||
|
daemon/lvm_full.ml | 221 ++++++++++++++++++++++++++++++++++++++
|
||||||
|
docs/C_SOURCE_FILES | 1 -
|
||||||
|
generator/actions_core.ml | 3 +
|
||||||
|
generator/daemon.ml | 190 --------------------------------
|
||||||
|
generator/daemon.mli | 1 -
|
||||||
|
generator/main.ml | 2 -
|
||||||
|
generator/structs.ml | 4 +-
|
||||||
|
generator/structs.mli | 7 --
|
||||||
|
po/POTFILES | 1 -
|
||||||
|
12 files changed, 229 insertions(+), 230 deletions(-)
|
||||||
|
create mode 100644 daemon/lvm_full.ml
|
||||||
|
|
||||||
|
diff --git a/.gitignore b/.gitignore
|
||||||
|
index 68b27c79..c5e8f802 100644
|
||||||
|
--- a/.gitignore
|
||||||
|
+++ b/.gitignore
|
||||||
|
@@ -97,7 +97,7 @@ Makefile.in
|
||||||
|
/daemon/listfs.mli
|
||||||
|
/daemon/lvm.mli
|
||||||
|
/daemon/lvm_dm.mli
|
||||||
|
-/daemon/lvm-tokenization.c
|
||||||
|
+/daemon/lvm_full.mli
|
||||||
|
/daemon/md.mli
|
||||||
|
/daemon/mount.mli
|
||||||
|
/daemon/names.c
|
||||||
|
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
|
||||||
|
index bb72c024..90ece846 100644
|
||||||
|
--- a/daemon/Makefile.am
|
||||||
|
+++ b/daemon/Makefile.am
|
||||||
|
@@ -22,7 +22,6 @@ BUILT_SOURCES = \
|
||||||
|
caml-stubs.c \
|
||||||
|
dispatch.c \
|
||||||
|
names.c \
|
||||||
|
- lvm-tokenization.c \
|
||||||
|
structs-cleanups.c \
|
||||||
|
structs-cleanups.h \
|
||||||
|
stubs-0.c \
|
||||||
|
@@ -52,6 +51,7 @@ generator_built = \
|
||||||
|
listfs.mli \
|
||||||
|
lvm.mli \
|
||||||
|
lvm_dm.mli \
|
||||||
|
+ lvm_full.mli \
|
||||||
|
md.mli \
|
||||||
|
mount.mli \
|
||||||
|
optgroups.ml \
|
||||||
|
@@ -152,7 +152,6 @@ guestfsd_SOURCES = \
|
||||||
|
luks.c \
|
||||||
|
lvm.c \
|
||||||
|
lvm-filter.c \
|
||||||
|
- lvm-tokenization.c \
|
||||||
|
md.c \
|
||||||
|
mkfs.c \
|
||||||
|
mknod.c \
|
||||||
|
@@ -298,6 +297,7 @@ SOURCES_MLI = \
|
||||||
|
listfs.mli \
|
||||||
|
lvm.mli \
|
||||||
|
lvm_dm.mli \
|
||||||
|
+ lvm_full.mli \
|
||||||
|
lvm_utils.mli \
|
||||||
|
md.mli \
|
||||||
|
mount.mli \
|
||||||
|
@@ -333,6 +333,7 @@ SOURCES_ML = \
|
||||||
|
ldm.ml \
|
||||||
|
link.ml \
|
||||||
|
lvm.ml \
|
||||||
|
+ lvm_full.ml \
|
||||||
|
lvm_utils.ml \
|
||||||
|
lvm_dm.ml \
|
||||||
|
findfs.ml \
|
||||||
|
diff --git a/daemon/lvm.c b/daemon/lvm.c
|
||||||
|
index 7e76e17c..001aacb2 100644
|
||||||
|
--- a/daemon/lvm.c
|
||||||
|
+++ b/daemon/lvm.c
|
||||||
|
@@ -139,28 +139,6 @@ do_vgs (void)
|
||||||
|
return convert_lvm_output (out, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* These were so complex to implement that I ended up auto-generating
|
||||||
|
- * the code. That code is in stubs.c, and it is generated as usual
|
||||||
|
- * by generator.ml.
|
||||||
|
- */
|
||||||
|
-guestfs_int_lvm_pv_list *
|
||||||
|
-do_pvs_full (void)
|
||||||
|
-{
|
||||||
|
- return parse_command_line_pvs ();
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-guestfs_int_lvm_vg_list *
|
||||||
|
-do_vgs_full (void)
|
||||||
|
-{
|
||||||
|
- return parse_command_line_vgs ();
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-guestfs_int_lvm_lv_list *
|
||||||
|
-do_lvs_full (void)
|
||||||
|
-{
|
||||||
|
- return parse_command_line_lvs ();
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int
|
||||||
|
do_pvcreate (const char *device)
|
||||||
|
{
|
||||||
|
diff --git a/daemon/lvm_full.ml b/daemon/lvm_full.ml
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..d5653d2f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/daemon/lvm_full.ml
|
||||||
|
@@ -0,0 +1,221 @@
|
||||||
|
+(* guestfs-inspection
|
||||||
|
+ * Copyright (C) 2009-2025 Red Hat Inc.
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation; either version 2 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License along
|
||||||
|
+ * with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
+ *)
|
||||||
|
+
|
||||||
|
+(* This file implements the complicated lvs-full, vgs-full and pvs-full APIs
|
||||||
|
+ *
|
||||||
|
+ * XXX Deprecate these APIs are replace with APIs for getting single
|
||||||
|
+ * named fields from LVM. That will be slower but far more flexible
|
||||||
|
+ * and extensible.
|
||||||
|
+ *)
|
||||||
|
+
|
||||||
|
+open Unix
|
||||||
|
+open Printf
|
||||||
|
+
|
||||||
|
+open Std_utils
|
||||||
|
+
|
||||||
|
+open Utils
|
||||||
|
+
|
||||||
|
+(* LVM UUIDs are basically 32 byte strings with '-' inserted.
|
||||||
|
+ * Remove the '-' characters and check it's the right length.
|
||||||
|
+ *)
|
||||||
|
+let parse_uuid uuid =
|
||||||
|
+ let uuid' =
|
||||||
|
+ uuid |> String.explode |> List.filter ((<>) '-') |> String.implode in
|
||||||
|
+ if String.length uuid' <> 32 then
|
||||||
|
+ failwithf "lvm-full: parse_uuid: unexpected UUID format: %S" uuid;
|
||||||
|
+ uuid'
|
||||||
|
+
|
||||||
|
+(* Parse the percent fields. These can be empty. *)
|
||||||
|
+let parse_percent pc = if pc = "" then None else Some (float_of_string pc)
|
||||||
|
+
|
||||||
|
+(* XXX These must match generator/structs.ml *)
|
||||||
|
+let lvm_pv_cols = [
|
||||||
|
+ "pv_name"; (* FString *)
|
||||||
|
+ "pv_uuid"; (* FUUID *)
|
||||||
|
+ "pv_fmt"; (* FString *)
|
||||||
|
+ "pv_size"; (* FBytes *)
|
||||||
|
+ "dev_size"; (* FBytes *)
|
||||||
|
+ "pv_free"; (* FBytes *)
|
||||||
|
+ "pv_used"; (* FBytes *)
|
||||||
|
+ "pv_attr"; (* FString (* XXX *) *)
|
||||||
|
+ "pv_pe_count"; (* FInt64 *)
|
||||||
|
+ "pv_pe_alloc_count"; (* FInt64 *)
|
||||||
|
+ "pv_tags"; (* FString *)
|
||||||
|
+ "pe_start"; (* FBytes *)
|
||||||
|
+ "pv_mda_count"; (* FInt64 *)
|
||||||
|
+ "pv_mda_free"; (* FBytes *)
|
||||||
|
+]
|
||||||
|
+
|
||||||
|
+let tokenize_pvs = function
|
||||||
|
+ | [ pv_name; pv_uuid; pv_fmt; pv_size; dev_size; pv_free;
|
||||||
|
+ pv_used; pv_attr; pv_pe_count; pv_pe_alloc_count; pv_tags;
|
||||||
|
+ pe_start; pv_mda_count; pv_mda_free ] ->
|
||||||
|
+ { Structs.pv_name = pv_name;
|
||||||
|
+ pv_uuid = parse_uuid pv_uuid;
|
||||||
|
+ pv_fmt = pv_fmt;
|
||||||
|
+ pv_size = Int64.of_string pv_size;
|
||||||
|
+ dev_size = Int64.of_string dev_size;
|
||||||
|
+ pv_free = Int64.of_string pv_free;
|
||||||
|
+ pv_used = Int64.of_string pv_used;
|
||||||
|
+ pv_attr = pv_attr;
|
||||||
|
+ pv_pe_count = Int64.of_string pv_pe_count;
|
||||||
|
+ pv_pe_alloc_count = Int64.of_string pv_pe_alloc_count;
|
||||||
|
+ pv_tags = pv_tags;
|
||||||
|
+ pe_start = Int64.of_string pe_start;
|
||||||
|
+ pv_mda_count = Int64.of_string pv_mda_count;
|
||||||
|
+ pv_mda_free = Int64.of_string pv_mda_free }
|
||||||
|
+
|
||||||
|
+ | fields ->
|
||||||
|
+ failwithf "pvs-full: tokenize_pvs: unexpected number of fields: %d"
|
||||||
|
+ (List.length fields)
|
||||||
|
+
|
||||||
|
+(* XXX These must match generator/structs.ml *)
|
||||||
|
+let lvm_vg_cols = [
|
||||||
|
+ "vg_name"; (* FString *)
|
||||||
|
+ "vg_uuid"; (* FUUID *)
|
||||||
|
+ "vg_fmt"; (* FString *)
|
||||||
|
+ "vg_attr"; (* FString (* XXX *) *)
|
||||||
|
+ "vg_size"; (* FBytes *)
|
||||||
|
+ "vg_free"; (* FBytes *)
|
||||||
|
+ "vg_sysid"; (* FString *)
|
||||||
|
+ "vg_extent_size"; (* FBytes *)
|
||||||
|
+ "vg_extent_count"; (* FInt64 *)
|
||||||
|
+ "vg_free_count"; (* FInt64 *)
|
||||||
|
+ "max_lv"; (* FInt64 *)
|
||||||
|
+ "max_pv"; (* FInt64 *)
|
||||||
|
+ "pv_count"; (* FInt64 *)
|
||||||
|
+ "lv_count"; (* FInt64 *)
|
||||||
|
+ "snap_count"; (* FInt64 *)
|
||||||
|
+ "vg_seqno"; (* FInt64 *)
|
||||||
|
+ "vg_tags"; (* FString *)
|
||||||
|
+ "vg_mda_count"; (* FInt64 *)
|
||||||
|
+ "vg_mda_free"; (* FBytes *)
|
||||||
|
+]
|
||||||
|
+
|
||||||
|
+let tokenize_vgs = function
|
||||||
|
+ | [ vg_name; vg_uuid; vg_fmt; vg_attr; vg_size; vg_free; vg_sysid;
|
||||||
|
+ vg_extent_size; vg_extent_count; vg_free_count; max_lv;
|
||||||
|
+ max_pv; pv_count; lv_count; snap_count; vg_seqno; vg_tags;
|
||||||
|
+ vg_mda_count; vg_mda_free ] ->
|
||||||
|
+ { Structs.vg_name = vg_name;
|
||||||
|
+ vg_uuid = parse_uuid vg_uuid;
|
||||||
|
+ vg_fmt = vg_fmt;
|
||||||
|
+ vg_attr = vg_attr;
|
||||||
|
+ vg_size = Int64.of_string vg_size;
|
||||||
|
+ vg_free = Int64.of_string vg_free;
|
||||||
|
+ vg_sysid = vg_sysid;
|
||||||
|
+ vg_extent_size = Int64.of_string vg_extent_size;
|
||||||
|
+ vg_extent_count = Int64.of_string vg_extent_count;
|
||||||
|
+ vg_free_count = Int64.of_string vg_free_count;
|
||||||
|
+ max_lv = Int64.of_string max_lv;
|
||||||
|
+ max_pv = Int64.of_string max_pv;
|
||||||
|
+ pv_count = Int64.of_string pv_count;
|
||||||
|
+ lv_count = Int64.of_string lv_count;
|
||||||
|
+ snap_count = Int64.of_string snap_count;
|
||||||
|
+ vg_seqno = Int64.of_string vg_seqno;
|
||||||
|
+ vg_tags = vg_tags;
|
||||||
|
+ vg_mda_count = Int64.of_string vg_mda_count;
|
||||||
|
+ vg_mda_free = Int64.of_string vg_mda_free }
|
||||||
|
+
|
||||||
|
+ | fields ->
|
||||||
|
+ failwithf "pvs-full: tokenize_vgs: unexpected number of fields: %d"
|
||||||
|
+ (List.length fields)
|
||||||
|
+
|
||||||
|
+(* XXX These must match generator/structs.ml *)
|
||||||
|
+let lvm_lv_cols = [
|
||||||
|
+ "lv_name"; (* FString *)
|
||||||
|
+ "lv_uuid"; (* FUUID *)
|
||||||
|
+ "lv_attr"; (* FString (* XXX *) *)
|
||||||
|
+ "lv_major"; (* FInt64 *)
|
||||||
|
+ "lv_minor"; (* FInt64 *)
|
||||||
|
+ "lv_kernel_major"; (* FInt64 *)
|
||||||
|
+ "lv_kernel_minor"; (* FInt64 *)
|
||||||
|
+ "lv_size"; (* FBytes *)
|
||||||
|
+ "seg_count"; (* FInt64 *)
|
||||||
|
+ "origin"; (* FString *)
|
||||||
|
+ "snap_percent"; (* FOptPercent *)
|
||||||
|
+ "copy_percent"; (* FOptPercent *)
|
||||||
|
+ "move_pv"; (* FString *)
|
||||||
|
+ "lv_tags"; (* FString *)
|
||||||
|
+ "mirror_log"; (* FString *)
|
||||||
|
+ "modules"; (* FString *)
|
||||||
|
+]
|
||||||
|
+
|
||||||
|
+let tokenize_lvs = function
|
||||||
|
+ | [ lv_name; lv_uuid; lv_attr; lv_major; lv_minor; lv_kernel_major;
|
||||||
|
+ lv_kernel_minor; lv_size; seg_count; origin; snap_percent;
|
||||||
|
+ copy_percent; move_pv; lv_tags; mirror_log; modules ] ->
|
||||||
|
+ { Structs.lv_name = lv_name;
|
||||||
|
+ lv_uuid = parse_uuid lv_uuid;
|
||||||
|
+ lv_attr = lv_attr;
|
||||||
|
+ lv_major = Int64.of_string lv_major;
|
||||||
|
+ lv_minor = Int64.of_string lv_minor;
|
||||||
|
+ lv_kernel_major = Int64.of_string lv_kernel_major;
|
||||||
|
+ lv_kernel_minor = Int64.of_string lv_kernel_minor;
|
||||||
|
+ lv_size = Int64.of_string lv_size;
|
||||||
|
+ seg_count = Int64.of_string seg_count;
|
||||||
|
+ origin = origin;
|
||||||
|
+ snap_percent = parse_percent snap_percent;
|
||||||
|
+ copy_percent = parse_percent copy_percent;
|
||||||
|
+ move_pv = move_pv;
|
||||||
|
+ lv_tags = lv_tags;
|
||||||
|
+ mirror_log = mirror_log;
|
||||||
|
+ modules = modules }
|
||||||
|
+
|
||||||
|
+ | fields ->
|
||||||
|
+ failwithf "pvs-full: tokenize_vgs: unexpected number of fields: %d"
|
||||||
|
+ (List.length fields)
|
||||||
|
+
|
||||||
|
+let rec pvs_full () =
|
||||||
|
+ let out = run_lvm_command "pvs" lvm_pv_cols in
|
||||||
|
+ let lines = trim_and_split out in
|
||||||
|
+ let pvs = List.map tokenize_pvs lines in
|
||||||
|
+ pvs
|
||||||
|
+
|
||||||
|
+and vgs_full () =
|
||||||
|
+ let out = run_lvm_command "vgs" lvm_vg_cols in
|
||||||
|
+ let lines = trim_and_split out in
|
||||||
|
+ let vgs = List.map tokenize_vgs lines in
|
||||||
|
+ vgs
|
||||||
|
+
|
||||||
|
+and lvs_full () =
|
||||||
|
+ let out = run_lvm_command "lvs" lvm_lv_cols in
|
||||||
|
+ let lines = trim_and_split out in
|
||||||
|
+ let lvs = List.map tokenize_lvs lines in
|
||||||
|
+ lvs
|
||||||
|
+
|
||||||
|
+and run_lvm_command typ cols =
|
||||||
|
+ let cols = String.concat "," cols in
|
||||||
|
+ let cmd = [ typ; "-o"; cols;
|
||||||
|
+ "--unbuffered"; "--noheadings"; "--nosuffix";
|
||||||
|
+ "--separator"; "\r"; "--units"; "b" ] in
|
||||||
|
+ command "lvm" cmd
|
||||||
|
+
|
||||||
|
+and trim_and_split out =
|
||||||
|
+ (* Split the output into lines. *)
|
||||||
|
+ let lines = String.nsplit "\n" out in
|
||||||
|
+
|
||||||
|
+ (* LVM puts leading whitespace on each line so remove that. *)
|
||||||
|
+ let lines = List.map String.triml lines in
|
||||||
|
+
|
||||||
|
+ (* Ignore any blank lines. *)
|
||||||
|
+ let lines = List.filter ((<>) "") lines in
|
||||||
|
+
|
||||||
|
+ (* Split each line into fields. *)
|
||||||
|
+ let lines = List.map (String.nsplit "\r") lines in
|
||||||
|
+ lines
|
||||||
|
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
|
||||||
|
index 0038f95e..cdfb1d61 100644
|
||||||
|
--- a/docs/C_SOURCE_FILES
|
||||||
|
+++ b/docs/C_SOURCE_FILES
|
||||||
|
@@ -111,7 +111,6 @@ daemon/link.c
|
||||||
|
daemon/ls.c
|
||||||
|
daemon/luks.c
|
||||||
|
daemon/lvm-filter.c
|
||||||
|
-daemon/lvm-tokenization.c
|
||||||
|
daemon/lvm.c
|
||||||
|
daemon/md.c
|
||||||
|
daemon/mkfs.c
|
||||||
|
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
|
||||||
|
index eb047b6b..01991dd0 100644
|
||||||
|
--- a/generator/actions_core.ml
|
||||||
|
+++ b/generator/actions_core.ml
|
||||||
|
@@ -1767,6 +1767,7 @@ See also C<guestfs_lvs_full>, C<guestfs_list_filesystems>." };
|
||||||
|
{ defaults with
|
||||||
|
name = "pvs_full"; added = (0, 0, 4);
|
||||||
|
style = RStructList ("physvols", "lvm_pv"), [], [];
|
||||||
|
+ impl = OCaml "Lvm_full.pvs_full";
|
||||||
|
optional = Some "lvm2";
|
||||||
|
shortdesc = "list the LVM physical volumes (PVs)";
|
||||||
|
longdesc = "\
|
||||||
|
@@ -1776,6 +1777,7 @@ of the L<pvs(8)> command. The \"full\" version includes all fields." };
|
||||||
|
{ defaults with
|
||||||
|
name = "vgs_full"; added = (0, 0, 4);
|
||||||
|
style = RStructList ("volgroups", "lvm_vg"), [], [];
|
||||||
|
+ impl = OCaml "Lvm_full.vgs_full";
|
||||||
|
optional = Some "lvm2";
|
||||||
|
shortdesc = "list the LVM volume groups (VGs)";
|
||||||
|
longdesc = "\
|
||||||
|
@@ -1785,6 +1787,7 @@ of the L<vgs(8)> command. The \"full\" version includes all fields." };
|
||||||
|
{ defaults with
|
||||||
|
name = "lvs_full"; added = (0, 0, 4);
|
||||||
|
style = RStructList ("logvols", "lvm_lv"), [], [];
|
||||||
|
+ impl = OCaml "Lvm_full.lvs_full";
|
||||||
|
optional = Some "lvm2";
|
||||||
|
shortdesc = "list the LVM logical volumes (LVs)";
|
||||||
|
longdesc = "\
|
||||||
|
diff --git a/generator/daemon.ml b/generator/daemon.ml
|
||||||
|
index 91decf40..f9b77a18 100644
|
||||||
|
--- a/generator/daemon.ml
|
||||||
|
+++ b/generator/daemon.ml
|
||||||
|
@@ -951,196 +951,6 @@ let generate_daemon_dispatch () =
|
||||||
|
pr "}\n";
|
||||||
|
pr "\n"
|
||||||
|
|
||||||
|
-let generate_daemon_lvm_tokenization () =
|
||||||
|
- generate_header CStyle GPLv2plus;
|
||||||
|
-
|
||||||
|
- pr "\
|
||||||
|
-#include <config.h>
|
||||||
|
-
|
||||||
|
-#include <stdio.h>
|
||||||
|
-#include <stdlib.h>
|
||||||
|
-#include <string.h>
|
||||||
|
-#include <inttypes.h>
|
||||||
|
-#include <errno.h>
|
||||||
|
-#include <rpc/types.h>
|
||||||
|
-#include <rpc/xdr.h>
|
||||||
|
-
|
||||||
|
-#include \"daemon.h\"
|
||||||
|
-#include \"c-ctype.h\"
|
||||||
|
-#include \"guestfs_protocol.h\"
|
||||||
|
-#include \"actions.h\"
|
||||||
|
-#include \"optgroups.h\"
|
||||||
|
-
|
||||||
|
-";
|
||||||
|
-
|
||||||
|
- (* LVM columns and tokenization functions. *)
|
||||||
|
- (* XXX This generates crap code. We should rethink how we
|
||||||
|
- * do this parsing.
|
||||||
|
- *)
|
||||||
|
- List.iter (
|
||||||
|
- function
|
||||||
|
- | typ, cols ->
|
||||||
|
- pr "static const char lvm_%s_cols[] = \"%s\";\n"
|
||||||
|
- typ (String.concat "," (List.map fst cols));
|
||||||
|
- pr "\n";
|
||||||
|
-
|
||||||
|
- pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
|
||||||
|
- pr "{\n";
|
||||||
|
- pr " char *tok, *p, *next;\n";
|
||||||
|
- pr " size_t i, j;\n";
|
||||||
|
- pr "\n";
|
||||||
|
- (*
|
||||||
|
- pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
|
||||||
|
- pr "\n";
|
||||||
|
- *)
|
||||||
|
- pr " if (!str) {\n";
|
||||||
|
- pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr " if (!*str || c_isspace (*str)) {\n";
|
||||||
|
- pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr " tok = str;\n";
|
||||||
|
- List.iter (
|
||||||
|
- fun (name, coltype) ->
|
||||||
|
- pr " if (!tok) {\n";
|
||||||
|
- pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr " p = strchrnul (tok, '\\r');\n";
|
||||||
|
- pr " if (*p) next = p+1; else next = NULL;\n";
|
||||||
|
- pr " *p = '\\0';\n";
|
||||||
|
- (match coltype with
|
||||||
|
- | FString | FDevice ->
|
||||||
|
- pr " r->%s = strdup (tok);\n" name;
|
||||||
|
- pr " if (r->%s == NULL) {\n" name;
|
||||||
|
- pr " perror (\"strdup\");\n";
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " }\n"
|
||||||
|
- | FUUID ->
|
||||||
|
- pr " for (i = j = 0; i < 32; ++j) {\n";
|
||||||
|
- pr " if (tok[j] == '\\0') {\n";
|
||||||
|
- pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " } else if (tok[j] != '-')\n";
|
||||||
|
- pr " r->%s[i++] = tok[j];\n" name;
|
||||||
|
- pr " }\n";
|
||||||
|
- | FBytes ->
|
||||||
|
- pr " if (sscanf (tok, \"%%\" SCNi64, &r->%s) != 1) {\n" name;
|
||||||
|
- pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- | FInt64 ->
|
||||||
|
- pr " if (sscanf (tok, \"%%\" SCNi64, &r->%s) != 1) {\n" name;
|
||||||
|
- pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- | FOptPercent ->
|
||||||
|
- pr " if (tok[0] == '\\0')\n";
|
||||||
|
- pr " r->%s = -1;\n" name;
|
||||||
|
- pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
|
||||||
|
- pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
|
||||||
|
- assert false (* can never be an LVM column *)
|
||||||
|
- );
|
||||||
|
- pr " tok = next;\n";
|
||||||
|
- ) cols;
|
||||||
|
-
|
||||||
|
- pr " if (tok != NULL) {\n";
|
||||||
|
- pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
|
||||||
|
- pr " return -1;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr " return 0;\n";
|
||||||
|
- pr "}\n";
|
||||||
|
- pr "\n";
|
||||||
|
-
|
||||||
|
- pr "guestfs_int_lvm_%s_list *\n" typ;
|
||||||
|
- pr "parse_command_line_%ss (void)\n" typ;
|
||||||
|
- pr "{\n";
|
||||||
|
- pr " char *out, *err;\n";
|
||||||
|
- pr " char *p, *pend;\n";
|
||||||
|
- pr " int r, i;\n";
|
||||||
|
- pr " guestfs_int_lvm_%s_list *ret;\n" typ;
|
||||||
|
- pr " void *newp;\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " ret = malloc (sizeof *ret);\n";
|
||||||
|
- pr " if (!ret) {\n";
|
||||||
|
- pr " reply_with_perror (\"malloc\");\n";
|
||||||
|
- pr " return NULL;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
|
||||||
|
- pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
|
||||||
|
- pr "\n";
|
||||||
|
- pr " r = command (&out, &err,\n";
|
||||||
|
- pr " \"lvm\", \"%ss\",\n" typ;
|
||||||
|
- pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
|
||||||
|
- pr " \"--nosuffix\", \"--separator\", \"\\r\", \"--units\", \"b\", NULL);\n";
|
||||||
|
- pr " if (r == -1) {\n";
|
||||||
|
- pr " reply_with_error (\"%%s\", err);\n";
|
||||||
|
- pr " free (out);\n";
|
||||||
|
- pr " free (err);\n";
|
||||||
|
- pr " free (ret);\n";
|
||||||
|
- pr " return NULL;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " free (err);\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " /* Tokenize each line of the output. */\n";
|
||||||
|
- pr " p = out;\n";
|
||||||
|
- pr " i = 0;\n";
|
||||||
|
- pr " while (p) {\n";
|
||||||
|
- pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
|
||||||
|
- pr " if (pend) {\n";
|
||||||
|
- pr " *pend = '\\0';\n";
|
||||||
|
- pr " pend++;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
|
||||||
|
- pr " p++;\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " if (!*p) { /* Empty line? Skip it. */\n";
|
||||||
|
- pr " p = pend;\n";
|
||||||
|
- pr " continue;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " /* Allocate some space to store this next entry. */\n";
|
||||||
|
- pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
|
||||||
|
- pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
|
||||||
|
- pr " if (newp == NULL) {\n";
|
||||||
|
- pr " reply_with_perror (\"realloc\");\n";
|
||||||
|
- pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
|
||||||
|
- pr " free (ret);\n";
|
||||||
|
- pr " free (out);\n";
|
||||||
|
- pr " return NULL;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
|
||||||
|
- pr "\n";
|
||||||
|
- pr " /* Tokenize the next entry. */\n";
|
||||||
|
- pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
|
||||||
|
- pr " if (r == -1) {\n";
|
||||||
|
- pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
|
||||||
|
- pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
|
||||||
|
- pr " free (ret);\n";
|
||||||
|
- pr " free (out);\n";
|
||||||
|
- pr " return NULL;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " ++i;\n";
|
||||||
|
- pr " p = pend;\n";
|
||||||
|
- pr " }\n";
|
||||||
|
- pr "\n";
|
||||||
|
- pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
|
||||||
|
- pr "\n";
|
||||||
|
- pr " free (out);\n";
|
||||||
|
- pr " return ret;\n";
|
||||||
|
- pr "}\n"
|
||||||
|
-
|
||||||
|
- ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
|
||||||
|
-
|
||||||
|
(* Generate a list of function names, for debugging in the daemon.. *)
|
||||||
|
let generate_daemon_names () =
|
||||||
|
generate_header CStyle GPLv2plus;
|
||||||
|
diff --git a/generator/daemon.mli b/generator/daemon.mli
|
||||||
|
index edf331a9..77c6e632 100644
|
||||||
|
--- a/generator/daemon.mli
|
||||||
|
+++ b/generator/daemon.mli
|
||||||
|
@@ -23,7 +23,6 @@ val generate_daemon_caml_stubs : unit -> unit
|
||||||
|
val generate_daemon_caml_callbacks_ml : unit -> unit
|
||||||
|
val generate_daemon_caml_interface : string -> unit -> unit
|
||||||
|
val generate_daemon_dispatch : unit -> unit
|
||||||
|
-val generate_daemon_lvm_tokenization : unit -> unit
|
||||||
|
val generate_daemon_names : unit -> unit
|
||||||
|
val generate_daemon_optgroups_c : unit -> unit
|
||||||
|
val generate_daemon_optgroups_h : unit -> unit
|
||||||
|
diff --git a/generator/main.ml b/generator/main.ml
|
||||||
|
index ff5e964a..6e36d9c7 100644
|
||||||
|
--- a/generator/main.ml
|
||||||
|
+++ b/generator/main.ml
|
||||||
|
@@ -147,8 +147,6 @@ Run it from the top source directory using the command
|
||||||
|
Daemon.generate_daemon_optgroups_ml;
|
||||||
|
output_to "daemon/optgroups.mli"
|
||||||
|
Daemon.generate_daemon_optgroups_mli;
|
||||||
|
- output_to "daemon/lvm-tokenization.c"
|
||||||
|
- Daemon.generate_daemon_lvm_tokenization;
|
||||||
|
output_to "daemon/structs-cleanups.c"
|
||||||
|
Daemon.generate_daemon_structs_cleanups_c;
|
||||||
|
output_to "daemon/structs-cleanups.h"
|
||||||
|
diff --git a/generator/structs.ml b/generator/structs.ml
|
||||||
|
index 93a3ed03..239a5d5e 100644
|
||||||
|
--- a/generator/structs.ml
|
||||||
|
+++ b/generator/structs.ml
|
||||||
|
@@ -31,9 +31,7 @@ type struc = {
|
||||||
|
s_unused : unit; (* Silences warning 23 when using 'defaults with ...' *)
|
||||||
|
}
|
||||||
|
|
||||||
|
-(* Because we generate extra parsing code for LVM command line tools,
|
||||||
|
- * we have to pull out the LVM columns separately here.
|
||||||
|
- *)
|
||||||
|
+(* XXX These must match daemon/lvm_full.ml *)
|
||||||
|
let lvm_pv_cols = [
|
||||||
|
"pv_name", FDevice;
|
||||||
|
"pv_uuid", FUUID;
|
||||||
|
diff --git a/generator/structs.mli b/generator/structs.mli
|
||||||
|
index e7a29b01..b3444623 100644
|
||||||
|
--- a/generator/structs.mli
|
||||||
|
+++ b/generator/structs.mli
|
||||||
|
@@ -34,13 +34,6 @@ type struc = {
|
||||||
|
val structs : struc list
|
||||||
|
(** List of structures. *)
|
||||||
|
|
||||||
|
-val lvm_pv_cols : cols
|
||||||
|
-val lvm_vg_cols : cols
|
||||||
|
-val lvm_lv_cols : cols
|
||||||
|
-(** These are exported to the daemon code generator where they are
|
||||||
|
- used to generate code for parsing the output of commands like
|
||||||
|
- [lvs]. One day replace this with liblvm API calls. *)
|
||||||
|
-
|
||||||
|
val lookup_struct : string -> struc
|
||||||
|
(** Lookup a struct by name. *)
|
||||||
|
|
||||||
|
diff --git a/po/POTFILES b/po/POTFILES
|
||||||
|
index 75b040c0..d10f9710 100644
|
||||||
|
--- a/po/POTFILES
|
||||||
|
+++ b/po/POTFILES
|
||||||
|
@@ -90,7 +90,6 @@ daemon/link.c
|
||||||
|
daemon/ls.c
|
||||||
|
daemon/luks.c
|
||||||
|
daemon/lvm-filter.c
|
||||||
|
-daemon/lvm-tokenization.c
|
||||||
|
daemon/lvm.c
|
||||||
|
daemon/md.c
|
||||||
|
daemon/mkfs.c
|
@ -0,0 +1,70 @@
|
|||||||
|
From 180293338e0d127d0545fe03b6141ed04e22e441 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 16 Apr 2025 10:27:25 +0100
|
||||||
|
Subject: [PATCH] daemon: inspect: Resolve Ubuntu 22+
|
||||||
|
/dev/disk/by-id/dm-uuid-LVM-... in fstab
|
||||||
|
|
||||||
|
Linux + LVM supports device names like /dev/disk/by-id/dm-uuid-LVM-
|
||||||
|
followed by two concatenated UUIDs, firstly for the volume group and
|
||||||
|
secondly for the logical volume. We can reverse those to get the
|
||||||
|
device name (/dev/VG/LV).
|
||||||
|
|
||||||
|
fstab entries look like:
|
||||||
|
|
||||||
|
# / was on /dev/vg0/lv-0 during curtin installation
|
||||||
|
/dev/disk/by-id/dm-uuid-LVM-OzFWT6NHkstr1hcmrWRRMDGPn9xdZj1YOOycQ533186x288FdU6UubU3OlnWJz6D / ext4 defaults 0 1
|
||||||
|
# /usr was on /dev/vg0/lv-1 during curtin installation
|
||||||
|
/dev/disk/by-id/dm-uuid-LVM-OzFWT6NHkstr1hcmrWRRMDGPn9xdZj1YZu53m4ZssZ8Jeb3I14RAJwIj5YlHIb9P /usr ext4 defaults 0 1
|
||||||
|
|
||||||
|
The upshot of this fix is that we are now able to correctly inspect
|
||||||
|
and run virt-v2v on Ubuntu 22+ guests with split /usr. In particular,
|
||||||
|
we correctly map /etc/fstab entries like the above to LV device names,
|
||||||
|
which means that /usr merging now works correctly.
|
||||||
|
|
||||||
|
Reported-by: Jaroslav Spanko
|
||||||
|
Thanks: Daniel Berrange
|
||||||
|
Fixes: https://issues.redhat.com/browse/RHEL-87493
|
||||||
|
(cherry picked from commit e43ca1912973b3ddfa73b09a4690aa8bb26e08af)
|
||||||
|
---
|
||||||
|
daemon/inspect_fs_unix_fstab.ml | 21 +++++++++++++++++++++
|
||||||
|
1 file changed, 21 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
index 45c62175..dcbdab3c 100644
|
||||||
|
--- a/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
+++ b/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
@@ -27,6 +27,7 @@ open Inspect_utils
|
||||||
|
|
||||||
|
let re_cciss = PCRE.compile "^/dev/(cciss/c\\d+d\\d+)(?:p(\\d+))?$"
|
||||||
|
let re_diskbyid = PCRE.compile "^/dev/disk/by-id/.*-part(\\d+)$"
|
||||||
|
+let re_dmuuid = PCRE.compile "^/dev/disk/by-id/dm-uuid-LVM-([0-9a-zA-Z]{32})([0-9a-zA-Z]{32})$"
|
||||||
|
let re_freebsd_gpt = PCRE.compile "^/dev/(ada{0,1}|vtbd)(\\d+)p(\\d+)$"
|
||||||
|
let re_freebsd_mbr = PCRE.compile "^/dev/(ada{0,1}|vtbd)(\\d+)s(\\d+)([a-z])$"
|
||||||
|
let re_hurd_dev = PCRE.compile "^/dev/(h)d(\\d+)s(\\d+)$"
|
||||||
|
@@ -407,6 +408,26 @@ and resolve_fstab_device spec md_map os_type =
|
||||||
|
Failure _ -> default
|
||||||
|
)
|
||||||
|
|
||||||
|
+ (* Ubuntu 22+ uses /dev/disk/by-id/dm-uuid-LVM-... followed by a
|
||||||
|
+ * double UUID which identifies an LV. The first part of the UUID
|
||||||
|
+ * is the VG UUID. The second part is the LV UUID.
|
||||||
|
+ *)
|
||||||
|
+ else if PCRE.matches re_dmuuid spec then (
|
||||||
|
+ debug_matching "dmuuid";
|
||||||
|
+ let vg_uuid_spec = PCRE.sub 1 and lv_uuid_spec = PCRE.sub 2 in
|
||||||
|
+ try
|
||||||
|
+ (* Get the list of all VGs and LVs. *)
|
||||||
|
+ let vgs = Lvm_full.vgs_full () and lvs = Lvm_full.lvs_full () in
|
||||||
|
+ (* Find one VG & LV (hopefully) that matches the UUIDs. *)
|
||||||
|
+ let vg =
|
||||||
|
+ List.find (fun { Structs.vg_uuid } -> vg_uuid = vg_uuid_spec) vgs
|
||||||
|
+ and lv =
|
||||||
|
+ List.find (fun { Structs.lv_uuid } -> lv_uuid = lv_uuid_spec) lvs in
|
||||||
|
+ Mountable.of_device (sprintf "/dev/%s/%s" vg.vg_name lv.lv_name)
|
||||||
|
+ with
|
||||||
|
+ Failure _ | Not_found -> default
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
else if PCRE.matches re_freebsd_gpt spec then (
|
||||||
|
debug_matching "FreeBSD GPT";
|
||||||
|
(* group 1 (type) is not used *)
|
@ -0,0 +1,38 @@
|
|||||||
|
From 14b2ac2d5f087b0d8fc8c1e0451cae22af753734 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Fri, 25 Apr 2025 15:14:24 +0100
|
||||||
|
Subject: [PATCH] RHEL 9: daemon/fstrim.c: Run the fstrim command twice
|
||||||
|
|
||||||
|
Workaround for https://issues.redhat.com/browse/RHEL-88450
|
||||||
|
|
||||||
|
Fixes: https://issues.redhat.com/browse/RHEL-88508
|
||||||
|
Related: https://issues.redhat.com/browse/RHEL-88450
|
||||||
|
Thanks: Eric Sandeen
|
||||||
|
---
|
||||||
|
daemon/fstrim.c | 11 +++++++++++
|
||||||
|
1 file changed, 11 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/fstrim.c b/daemon/fstrim.c
|
||||||
|
index f6869042..06707a7f 100644
|
||||||
|
--- a/daemon/fstrim.c
|
||||||
|
+++ b/daemon/fstrim.c
|
||||||
|
@@ -101,8 +101,19 @@ do_fstrim (const char *path,
|
||||||
|
ADD_ARG (argv, i, buf);
|
||||||
|
ADD_ARG (argv, i, NULL);
|
||||||
|
|
||||||
|
+ /* Run the command twice to workaround
|
||||||
|
+ * https://issues.redhat.com/browse/RHEL-88450
|
||||||
|
+ */
|
||||||
|
+ r = commandv (&out, &err, argv);
|
||||||
|
+ if (r == -1) goto error;
|
||||||
|
+ if (verbose)
|
||||||
|
+ fprintf (stderr, "%s\n", out);
|
||||||
|
+ free (out); out = NULL;
|
||||||
|
+ free (err); err = NULL;
|
||||||
|
+
|
||||||
|
r = commandv (&out, &err, argv);
|
||||||
|
if (r == -1) {
|
||||||
|
+ error:
|
||||||
|
/* If the error is about the kernel operation not being supported
|
||||||
|
* for this filesystem type, then return errno ENOTSUP here.
|
||||||
|
*/
|
@ -0,0 +1,29 @@
|
|||||||
|
From e9a7378d730477d6a548c18244ba0bde9c7dc93d Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Fri, 25 Apr 2025 15:24:43 +0100
|
||||||
|
Subject: [PATCH] daemon/fstrim.c: Issue sync_disks after fstrim
|
||||||
|
|
||||||
|
Thanks: Eric Sandeen
|
||||||
|
(cherry picked from commit e127edcafc95c75bf484bf2199eb746a392c58c0)
|
||||||
|
---
|
||||||
|
daemon/fstrim.c | 8 ++++++++
|
||||||
|
1 file changed, 8 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/fstrim.c b/daemon/fstrim.c
|
||||||
|
index 06707a7f..474ef72d 100644
|
||||||
|
--- a/daemon/fstrim.c
|
||||||
|
+++ b/daemon/fstrim.c
|
||||||
|
@@ -127,5 +127,13 @@ do_fstrim (const char *path,
|
||||||
|
if (verbose)
|
||||||
|
fprintf (stderr, "%s\n", out);
|
||||||
|
|
||||||
|
+ /* Sync the disks again. In practice we always call fstrim
|
||||||
|
+ * expecting that afterwards the results are visible in the qemu
|
||||||
|
+ * devices backing the guest. Depending on the Linux filesystem,
|
||||||
|
+ * fstrim may issue asynch discard requests, so it's not necessarily
|
||||||
|
+ * true that everything has been written out before this point.
|
||||||
|
+ */
|
||||||
|
+ sync_disks ();
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
From 682765a63ec7c3140e6332f15d9833072eea05e1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 8 May 2025 09:10:38 +0100
|
||||||
|
Subject: [PATCH] daemon: inspect: Remove duplicate root mountpoints in
|
||||||
|
/etc/fstab
|
||||||
|
|
||||||
|
A customer case was found where /etc/fstab contained multiple root
|
||||||
|
mountpoints, something like:
|
||||||
|
|
||||||
|
LABEL=System / xfs ...
|
||||||
|
LABEL=Boot /boot ext2 ...
|
||||||
|
LABEL=System / xfs ...
|
||||||
|
|
||||||
|
This causes libguestfs and virt-v2v to fail. Either (on RHEL 9) we
|
||||||
|
try to mount the second instance of / which gives an error. Or (on
|
||||||
|
upstream kernels) we are able to mount the second instance but then
|
||||||
|
libguestfs gets confused when trying to unmount them.
|
||||||
|
|
||||||
|
In this case as the mounted devices are the same we can just delete
|
||||||
|
the duplicate. It's also possible that there could be multiple
|
||||||
|
non-identical root mountpoints, in which case we have to pick one, and
|
||||||
|
this code arbitrarily picks the first[*] (but emits a warning).
|
||||||
|
|
||||||
|
We don't do anything for non-root mountpoints.
|
||||||
|
|
||||||
|
Update common submodule to add 'List.same' function from mlstdutils.
|
||||||
|
|
||||||
|
[*] Which one is "the first" depends on what version of ocaml-augeas
|
||||||
|
we are using. ocaml-augeas version 0.6 Augeas.matches function
|
||||||
|
returns entries in reverse order (compared to augeas itself). This is
|
||||||
|
fixed in version 0.7:
|
||||||
|
http://git.annexia.org/?p=ocaml-augeas.git;a=commitdiff;h=b703b92e3d26690aa6f7b822132049ce5435983e
|
||||||
|
|
||||||
|
Fixes: https://issues.redhat.com/browse/RHEL-90168
|
||||||
|
(cherry picked from commit 5441d3dd0c8843897f65c8d40c82e0d204748b4e)
|
||||||
|
---
|
||||||
|
common | 2 +-
|
||||||
|
daemon/inspect_fs_unix_fstab.ml | 31 +++++++++++++++++++++++++++++--
|
||||||
|
2 files changed, 30 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
Submodule common 8aed7b6a..9053edae:
|
||||||
|
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
|
||||||
|
index 1177ff69..a0745d38 100644
|
||||||
|
--- a/common/mlstdutils/std_utils.ml
|
||||||
|
+++ b/common/mlstdutils/std_utils.ml
|
||||||
|
@@ -396,6 +396,18 @@ module List = struct
|
||||||
|
|
||||||
|
let push_back_list xsp xs = xsp := !xsp @ xs
|
||||||
|
let push_front_list xs xsp = xsp := xs @ !xsp
|
||||||
|
+
|
||||||
|
+ let make n x =
|
||||||
|
+ let rec loop acc = function
|
||||||
|
+ | 0 -> acc
|
||||||
|
+ | i when i > 0 -> loop (x :: acc) (i-1)
|
||||||
|
+ | _ -> invalid_arg "make"
|
||||||
|
+ in
|
||||||
|
+ loop [] n
|
||||||
|
+
|
||||||
|
+ let same = function
|
||||||
|
+ | [] -> true
|
||||||
|
+ | x :: xs -> List.for_all ((=) x) xs
|
||||||
|
end
|
||||||
|
|
||||||
|
module Option = struct
|
||||||
|
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
|
||||||
|
index 6811b4bc..f5ff3470 100644
|
||||||
|
--- a/common/mlstdutils/std_utils.mli
|
||||||
|
+++ b/common/mlstdutils/std_utils.mli
|
||||||
|
@@ -289,6 +289,12 @@ module List : sig
|
||||||
|
|
||||||
|
[push_front_list] is like {!push_front} above, except it prepends
|
||||||
|
a list to the list reference. *)
|
||||||
|
+
|
||||||
|
+ val make : int -> 'a -> 'a list
|
||||||
|
+ (** [make n x] returns a list with [x] repeated [n] times. *)
|
||||||
|
+ val same : 'a list -> bool
|
||||||
|
+ (** [same xs] returns true iff the list contains only identical elements,
|
||||||
|
+ or is the empty list. *)
|
||||||
|
end
|
||||||
|
(** Override the List module from stdlib. *)
|
||||||
|
|
||||||
|
diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
index dcbdab3c..b0de55e4 100644
|
||||||
|
--- a/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
+++ b/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
@@ -53,8 +53,10 @@ and check_fstab_aug mdadm_conf root_mountable os_type aug =
|
||||||
|
let md_map = if mdadm_conf then map_md_devices aug else StringMap.empty in
|
||||||
|
|
||||||
|
let path = "/files/etc/fstab/*[label() != '#comment']" in
|
||||||
|
- let entries = aug_matches_noerrors aug path in
|
||||||
|
- List.filter_map (check_fstab_entry md_map root_mountable os_type aug) entries
|
||||||
|
+ path |>
|
||||||
|
+ aug_matches_noerrors aug |>
|
||||||
|
+ List.filter_map (check_fstab_entry md_map root_mountable os_type aug) |>
|
||||||
|
+ remove_duplicate_root_mountpoints
|
||||||
|
|
||||||
|
and check_fstab_entry md_map root_mountable os_type aug entry =
|
||||||
|
with_return (fun {return} ->
|
||||||
|
@@ -604,3 +606,28 @@ and resolve_diskbyid part default =
|
||||||
|
if is_partition dev then Mountable.of_device dev
|
||||||
|
else default
|
||||||
|
)
|
||||||
|
+
|
||||||
|
+(* Remove duplicate root mountpoints if they are identical. If
|
||||||
|
+ * there are multiple non-identical roots we pick the first and
|
||||||
|
+ * emit a warning (RHEL-90168).
|
||||||
|
+ *)
|
||||||
|
+and remove_duplicate_root_mountpoints (entries : fstab_entry list) =
|
||||||
|
+ let root_entries, non_root_entries =
|
||||||
|
+ List.partition (function (_, "/") -> true | _ -> false) entries in
|
||||||
|
+ (* If there is one root entry (the normal case) return the list unmodified. *)
|
||||||
|
+ if List.length root_entries <= 1 then entries
|
||||||
|
+ else (
|
||||||
|
+ (* If they are not the same, issue a warning. *)
|
||||||
|
+ if not (List.same root_entries) then
|
||||||
|
+ eprintf "check_fstab: multiple, non-identical root mountpoints found \
|
||||||
|
+ in the /etc/fstab of this guest, picking the first. The \
|
||||||
|
+ root entries were: [%s]\n"
|
||||||
|
+ (String.concat "; "
|
||||||
|
+ (List.map (fun (mountable, mp) ->
|
||||||
|
+ sprintf "%s -> %s" (Mountable.to_string mountable) mp)
|
||||||
|
+ root_entries)
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ (* Choose the first root entry and return it. *)
|
||||||
|
+ List.hd root_entries :: non_root_entries
|
||||||
|
+ )
|
@ -0,0 +1,41 @@
|
|||||||
|
From e73ac4912d4864d5d378cd40bf1979e02bf0fcb1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 11 Jun 2025 11:38:23 +0100
|
||||||
|
Subject: [PATCH] lib/inspect-osinfo.c: Generate new osinfo shortname for SLES
|
||||||
|
>= 15
|
||||||
|
|
||||||
|
libosinfo changes the naming scheme it uses for SUSE starting with
|
||||||
|
major version 15. Previously it used names like "sles12" (or
|
||||||
|
"sles12sp1"), "sled12" for Server and Desktop variants. In 15+ it
|
||||||
|
uses "sle15" as there are no variants any longer (instead the
|
||||||
|
installer asks you what variant you want to install). We're only
|
||||||
|
interested in the Server variant. Change the name that we return to
|
||||||
|
"sle15" or "sle15sp1".
|
||||||
|
|
||||||
|
See: https://gitlab.com/libosinfo/osinfo-db/-/commit/b0fa386699ce634abb6dd4b56aa0e83d979353fc
|
||||||
|
Fixes: https://issues.redhat.com/browse/RHEL-95791
|
||||||
|
Thanks: Ming Xie, Victor Toso
|
||||||
|
Related: https://issues.redhat.com/browse/RHEL-95540
|
||||||
|
(cherry picked from commit db46bcb5356e1c654a4b5b8ecca1ae657d46b9cf)
|
||||||
|
---
|
||||||
|
lib/inspect-osinfo.c | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/inspect-osinfo.c b/lib/inspect-osinfo.c
|
||||||
|
index f792d771..1fc2f59a 100644
|
||||||
|
--- a/lib/inspect-osinfo.c
|
||||||
|
+++ b/lib/inspect-osinfo.c
|
||||||
|
@@ -62,10 +62,11 @@ guestfs_impl_inspect_get_osinfo (guestfs_h *g, const char *root)
|
||||||
|
else if (STREQ (distro, "fedora") || STREQ (distro, "mageia"))
|
||||||
|
return safe_asprintf (g, "%s%d", distro, major);
|
||||||
|
else if (STREQ (distro, "sles")) {
|
||||||
|
+ const char *base = major >= 15 ? "sle" : "sles";
|
||||||
|
if (minor == 0)
|
||||||
|
- return safe_asprintf (g, "%s%d", distro, major);
|
||||||
|
+ return safe_asprintf (g, "%s%d", base, major);
|
||||||
|
else
|
||||||
|
- return safe_asprintf (g, "%s%dsp%d", distro, major, minor);
|
||||||
|
+ return safe_asprintf (g, "%s%dsp%d", base, major, minor);
|
||||||
|
}
|
||||||
|
else if (STREQ (distro, "ubuntu"))
|
||||||
|
return safe_asprintf (g, "%s%d.%02d", distro, major, minor);
|
@ -0,0 +1,47 @@
|
|||||||
|
From dbdc5bc7868ce4431d3dbf613c4b86d47236a34b Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 30 Jul 2025 10:53:20 +0100
|
||||||
|
Subject: [PATCH] daemon: Add contents of /etc/fstab to verbose log
|
||||||
|
|
||||||
|
Also some mdadm configuration files. This is useful for debugging.
|
||||||
|
|
||||||
|
The output looks like this:
|
||||||
|
|
||||||
|
info: /etc/fstab in /dev/VG/Root
|
||||||
|
LABEL=BOOT /boot ext2 default 0 0$
|
||||||
|
LABEL=ROOT / ext2 default 0 0$
|
||||||
|
|
||||||
|
Fixes: https://issues.redhat.com/browse/RHEL-106490
|
||||||
|
(cherry picked from commit f4f84a882468cb7b2dc4c265bdc18a5df79c3d4d)
|
||||||
|
---
|
||||||
|
daemon/inspect_fs_unix_fstab.ml | 17 +++++++++++++++++
|
||||||
|
1 file changed, 17 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
index b0de55e4..83d5016a 100644
|
||||||
|
--- a/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
+++ b/daemon/inspect_fs_unix_fstab.ml
|
||||||
|
@@ -43,6 +43,23 @@ let rec check_fstab ?(mdadm_conf = false) (root_mountable : Mountable.t)
|
||||||
|
if mdadm_conf then ["/etc/mdadm.conf"; "/etc/mdadm/mdadm.conf"] else [] in
|
||||||
|
let configfiles = "/etc/fstab" :: mdadmfiles in
|
||||||
|
|
||||||
|
+ (* If verbose, dump the contents of each config file as that can be
|
||||||
|
+ * useful for debugging.
|
||||||
|
+ *)
|
||||||
|
+ if verbose () then (
|
||||||
|
+ List.iter (
|
||||||
|
+ fun filename ->
|
||||||
|
+ let sysroot_filename = Sysroot.sysroot_path filename in
|
||||||
|
+ if Sys.file_exists sysroot_filename then (
|
||||||
|
+ eprintf "info: %s in %s\n%!"
|
||||||
|
+ filename (Mountable.to_string root_mountable);
|
||||||
|
+ let cmd = sprintf "cat -A %s >&2" (quote sysroot_filename) in
|
||||||
|
+ ignore (Sys.command cmd);
|
||||||
|
+ eprintf "\n%!"
|
||||||
|
+ )
|
||||||
|
+ ) configfiles
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
with_augeas ~name:"check_fstab_aug"
|
||||||
|
configfiles (check_fstab_aug mdadm_conf root_mountable os_type)
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
From b448164dff834fe4e7a652bf9a4ef79f8d7952e2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 30 Jul 2025 11:05:17 +0100
|
||||||
|
Subject: [PATCH] appliance/init: Add lsblk and blkid output to verbose log
|
||||||
|
|
||||||
|
This is useful for debugging. The output looks like:
|
||||||
|
|
||||||
|
+ lsblk
|
||||||
|
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
|
||||||
|
sda 8:0 0 1G 0 disk
|
||||||
|
|-sda1 8:1 0 512M 0 part
|
||||||
|
`-sda2 8:2 0 512M 0 part
|
||||||
|
|-VG-Root 252:0 0 32M 0 lvm
|
||||||
|
|-VG-LV1 252:1 0 32M 0 lvm
|
||||||
|
|-VG-LV2 252:2 0 32M 0 lvm
|
||||||
|
`-VG-LV3 252:3 0 64M 0 lvm
|
||||||
|
sdb 8:16 0 4G 0 disk /
|
||||||
|
+ blkid
|
||||||
|
/dev/mapper/VG-LV1: UUID="cc8a3437-4169-4b1c-b432-ee8adc563f6d" BLOCK_SIZE="4096" TYPE="ext2"
|
||||||
|
/dev/sdb: UUID="30c70ddc-d00b-4620-a408-025890e59aa6" BLOCK_SIZE="4096" TYPE="ext2"
|
||||||
|
/dev/mapper/VG-LV2: UUID="747009aa-e183-46ba-a034-0c437b15cebc" BLOCK_SIZE="1024" TYPE="ext2"
|
||||||
|
/dev/mapper/VG-Root: LABEL="ROOT" UUID="01234567-0123-0123-0123-012345678902" BLOCK_SIZE="4096" TYPE="ext2"
|
||||||
|
/dev/sda2: UUID="DfEjc1-wRU6-vh8U-we7U-ivEl-FRwo-rG0ZuL" TYPE="LVM2_member" PARTUUID="184cbb43-02"
|
||||||
|
/dev/sda1: LABEL="BOOT" UUID="01234567-0123-0123-0123-012345678901" BLOCK_SIZE="4096" TYPE="ext2" PARTUUID="184cbb43-01"
|
||||||
|
/dev/mapper/VG-LV3: UUID="f9e5dc21-9a2a-45a0-85b0-e2889607139a" BLOCK_SIZE="2048" TYPE="ext2"
|
||||||
|
|
||||||
|
Fixes: https://issues.redhat.com/browse/RHEL-106490
|
||||||
|
(cherry picked from commit 217823da95aad095a1c86a90aa4b1db8d46319e4)
|
||||||
|
---
|
||||||
|
appliance/init | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/appliance/init b/appliance/init
|
||||||
|
index dae06dbb..241928ef 100755
|
||||||
|
--- a/appliance/init
|
||||||
|
+++ b/appliance/init
|
||||||
|
@@ -164,6 +164,8 @@ if test "$guestfs_verbose" = 1 && test "$guestfs_boot_analysis" != 1; then
|
||||||
|
ls -lR /dev
|
||||||
|
cat /proc/mounts
|
||||||
|
cat /proc/mdstat
|
||||||
|
+ lsblk
|
||||||
|
+ blkid
|
||||||
|
lvm config
|
||||||
|
lvm pvs
|
||||||
|
lvm vgs
|
@ -0,0 +1,74 @@
|
|||||||
|
From cbd75c201754ff1c27911e63c92a82e1bcd21661 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 14 Aug 2025 14:56:47 +0100
|
||||||
|
Subject: [PATCH] daemon/inspect_fs_windows.ml: Add debugging for MBR drive
|
||||||
|
mappings
|
||||||
|
|
||||||
|
The function 'map_registry_disk_blob_gpt' immediately below this one
|
||||||
|
has a debugging statement. Add the equivalent to the function
|
||||||
|
'map_registry_disk_blob_mbr'.
|
||||||
|
|
||||||
|
The output looks like:
|
||||||
|
|
||||||
|
map_registry_disk_blob_mbr: searching for MBR disk ID 31 32 33 34
|
||||||
|
map_registry_disk_blob_mbr: searching for MBR partition offset 00 00 00 10 00 00 00 00
|
||||||
|
|
||||||
|
(cherry picked from commit e18bd72c8edce1f7227ea625031df1f36db1a793)
|
||||||
|
---
|
||||||
|
daemon/inspect_fs_windows.ml | 8 ++++++++
|
||||||
|
daemon/utils.ml | 4 ++++
|
||||||
|
daemon/utils.mli | 4 ++++
|
||||||
|
3 files changed, 16 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/inspect_fs_windows.ml b/daemon/inspect_fs_windows.ml
|
||||||
|
index 6537481e..18893e86 100644
|
||||||
|
--- a/daemon/inspect_fs_windows.ml
|
||||||
|
+++ b/daemon/inspect_fs_windows.ml
|
||||||
|
@@ -376,6 +376,10 @@ and map_registry_disk_blob_mbr devices blob =
|
||||||
|
* disk with this disk ID.
|
||||||
|
*)
|
||||||
|
let diskid = String.sub blob 0 4 in
|
||||||
|
+ if verbose () then
|
||||||
|
+ eprintf "map_registry_disk_blob_mbr: searching for MBR disk ID %s\n%!"
|
||||||
|
+ (hex_of_string diskid);
|
||||||
|
+
|
||||||
|
let device =
|
||||||
|
List.find (
|
||||||
|
fun dev ->
|
||||||
|
@@ -388,6 +392,10 @@ and map_registry_disk_blob_mbr devices blob =
|
||||||
|
* partition byte offset from Parted.part_list.
|
||||||
|
*)
|
||||||
|
let offset = String.sub blob 4 8 in
|
||||||
|
+ if verbose () then
|
||||||
|
+ eprintf "map_registry_disk_blob_mbr: searching for MBR partition offset \
|
||||||
|
+ %s\n%!"
|
||||||
|
+ (hex_of_string offset);
|
||||||
|
let offset = int_of_le64 offset in
|
||||||
|
let partitions = Parted.part_list device in
|
||||||
|
let partition =
|
||||||
|
diff --git a/daemon/utils.ml b/daemon/utils.ml
|
||||||
|
index 3b5c957c..bfaab3b0 100644
|
||||||
|
--- a/daemon/utils.ml
|
||||||
|
+++ b/daemon/utils.ml
|
||||||
|
@@ -296,3 +296,7 @@ let parse_key_value_strings ?unquote lines =
|
||||||
|
match unquote with
|
||||||
|
| None -> lines
|
||||||
|
| Some f -> List.map (fun (k, v) -> (k, f v)) lines
|
||||||
|
+
|
||||||
|
+let hex_of_string s =
|
||||||
|
+ let bytes = String.map_chars (fun c -> sprintf "%02x" (Char.code c)) s in
|
||||||
|
+ String.concat " " bytes
|
||||||
|
diff --git a/daemon/utils.mli b/daemon/utils.mli
|
||||||
|
index e721f28f..250f2f81 100644
|
||||||
|
--- a/daemon/utils.mli
|
||||||
|
+++ b/daemon/utils.mli
|
||||||
|
@@ -121,5 +121,9 @@ val parse_key_value_strings : ?unquote:(string -> string) -> string list -> (str
|
||||||
|
it is applied on the values as unquote function. Empty lines,
|
||||||
|
or that start with a comment character [#], are ignored. *)
|
||||||
|
|
||||||
|
+val hex_of_string : string -> string
|
||||||
|
+(** Return a string as a list of hex bytes.
|
||||||
|
+ Use this for debugging msgs only. *)
|
||||||
|
+
|
||||||
|
(**/**)
|
||||||
|
val get_verbose_flag : unit -> bool
|
@ -0,0 +1,31 @@
|
|||||||
|
From 3720994fca930e5cd685e6380ac5cd3068081bb3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 14 Aug 2025 14:57:45 +0100
|
||||||
|
Subject: [PATCH] daemon/inspect_fs_windows.ml: Add debugging when we start
|
||||||
|
registry analysis
|
||||||
|
|
||||||
|
Add some debugging when we begin the process of analyzing the Windows
|
||||||
|
registry of a guest.
|
||||||
|
|
||||||
|
(cherry picked from commit 5c7e15cfae7c91bb2e5685d657695a2d87d88bcd)
|
||||||
|
---
|
||||||
|
daemon/inspect_fs_windows.ml | 6 ++++++
|
||||||
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/inspect_fs_windows.ml b/daemon/inspect_fs_windows.ml
|
||||||
|
index 18893e86..f4e3b998 100644
|
||||||
|
--- a/daemon/inspect_fs_windows.ml
|
||||||
|
+++ b/daemon/inspect_fs_windows.ml
|
||||||
|
@@ -207,6 +207,12 @@ and check_windows_registry systemroot data =
|
||||||
|
if Is.is_file system_hive then Some system_hive else None in
|
||||||
|
data.windows_system_hive <- system_hive;
|
||||||
|
|
||||||
|
+ if verbose () then
|
||||||
|
+ eprintf "check_windows_registry: software hive: %s\n\
|
||||||
|
+ check_windows_registry: system hive: %s\n%!"
|
||||||
|
+ (Option.value ~default:"None" software_hive)
|
||||||
|
+ (Option.value ~default:"None" system_hive);
|
||||||
|
+
|
||||||
|
match software_hive, system_hive with
|
||||||
|
| None, _ | Some _, None -> ()
|
||||||
|
| Some software_hive, Some system_hive ->
|
@ -0,0 +1,76 @@
|
|||||||
|
From 98d94d847f9041df79c446d5c149bca626545eb0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 14 Aug 2025 15:17:59 +0100
|
||||||
|
Subject: [PATCH] daemon/inspect_fs_windows.ml: Ignore blank disks in drive
|
||||||
|
mapping
|
||||||
|
|
||||||
|
If HKLM\System\MountedDevices references a blank disk, then when we
|
||||||
|
try to search for the actual backing device we will get an error from
|
||||||
|
parted:
|
||||||
|
|
||||||
|
parted: /dev/sdb: parted exited with status 1: Error: /dev/sdb: unrecognised disk label: Invalid argument
|
||||||
|
|
||||||
|
Just ignore these errors instead of failing inspection.
|
||||||
|
|
||||||
|
Fixes: https://issues.redhat.com/browse/RHEL-108803
|
||||||
|
Reported-by: Ameen Barakat
|
||||||
|
Thanks: Ming Xie
|
||||||
|
(cherry picked from commit 1c00248ac191ab167f54103197a33bb60c3da67d)
|
||||||
|
---
|
||||||
|
daemon/inspect_fs_windows.ml | 35 ++++++++++++++++++++++++++---------
|
||||||
|
1 file changed, 26 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/daemon/inspect_fs_windows.ml b/daemon/inspect_fs_windows.ml
|
||||||
|
index f4e3b998..5d92ca0f 100644
|
||||||
|
--- a/daemon/inspect_fs_windows.ml
|
||||||
|
+++ b/daemon/inspect_fs_windows.ml
|
||||||
|
@@ -389,8 +389,18 @@ and map_registry_disk_blob_mbr devices blob =
|
||||||
|
let device =
|
||||||
|
List.find (
|
||||||
|
fun dev ->
|
||||||
|
- Parted.part_get_parttype dev = "msdos" &&
|
||||||
|
+ try
|
||||||
|
+ Parted.part_get_parttype dev = "msdos" &&
|
||||||
|
pread dev 4 0x01b8 = diskid
|
||||||
|
+ with Unix.Unix_error (EINVAL, "parted", msg) ->
|
||||||
|
+ (* Errors can happen here if the disk is empty. Just ignore
|
||||||
|
+ * them. It means the drive mapping might have missing
|
||||||
|
+ * entries but that's not important. (RHEL-108803)
|
||||||
|
+ *)
|
||||||
|
+ if verbose () then
|
||||||
|
+ eprintf "map_registry_disk_blob_mbr: parted returned: \
|
||||||
|
+ %s (ignored)\n" msg;
|
||||||
|
+ false
|
||||||
|
) devices in
|
||||||
|
|
||||||
|
(* Next 8 bytes are the offset of the partition in bytes(!) given as
|
||||||
|
@@ -428,14 +438,21 @@ and map_registry_disk_blob_gpt partitions blob =
|
||||||
|
let partition =
|
||||||
|
List.find (
|
||||||
|
fun part ->
|
||||||
|
- let partnum = Devsparts.part_to_partnum part in
|
||||||
|
- let device = Devsparts.part_to_dev part in
|
||||||
|
- let typ = Parted.part_get_parttype device in
|
||||||
|
- if typ <> "gpt" then false
|
||||||
|
- else (
|
||||||
|
- let guid = Sfdisk.part_get_gpt_guid device partnum in
|
||||||
|
- String.lowercase_ascii guid = blob_guid
|
||||||
|
- )
|
||||||
|
+ try
|
||||||
|
+ let partnum = Devsparts.part_to_partnum part in
|
||||||
|
+ let device = Devsparts.part_to_dev part in
|
||||||
|
+ let typ = Parted.part_get_parttype device in
|
||||||
|
+ if typ <> "gpt" then false
|
||||||
|
+ else (
|
||||||
|
+ let guid = Sfdisk.part_get_gpt_guid device partnum in
|
||||||
|
+ String.lowercase_ascii guid = blob_guid
|
||||||
|
+ )
|
||||||
|
+ with Unix.Unix_error (EINVAL, "parted", msg) ->
|
||||||
|
+ (* See comment in MBR code above (RHEL-108803) *)
|
||||||
|
+ if verbose () then
|
||||||
|
+ eprintf "map_registry_disk_blob_gpt: parted returned: \
|
||||||
|
+ %s (ignored)\n" msg;
|
||||||
|
+ false
|
||||||
|
) partitions in
|
||||||
|
Some partition
|
||||||
|
with
|
@ -7,7 +7,7 @@ set -e
|
|||||||
# ./copy-patches.sh
|
# ./copy-patches.sh
|
||||||
|
|
||||||
project=libguestfs
|
project=libguestfs
|
||||||
rhel_version=9.6
|
rhel_version=9.7
|
||||||
|
|
||||||
# Check we're in the right directory.
|
# Check we're in the right directory.
|
||||||
if [ ! -f $project.spec ]; then
|
if [ ! -f $project.spec ]; then
|
||||||
|
@ -37,7 +37,7 @@ Summary: Access and modify virtual machine disk images
|
|||||||
Name: libguestfs
|
Name: libguestfs
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
Version: 1.54.0
|
Version: 1.54.0
|
||||||
Release: 4%{?dist}
|
Release: 11%{?dist}
|
||||||
License: LGPL-2.1-or-later
|
License: LGPL-2.1-or-later
|
||||||
|
|
||||||
# Build only for architectures that have a kernel
|
# Build only for architectures that have a kernel
|
||||||
@ -72,7 +72,7 @@ Source7: libguestfs.keyring
|
|||||||
Source8: copy-patches.sh
|
Source8: copy-patches.sh
|
||||||
|
|
||||||
# Patches are maintained in the following repository:
|
# Patches are maintained in the following repository:
|
||||||
# https://github.com/libguestfs/libguestfs/commits/rhel-9.6
|
# https://github.com/libguestfs/libguestfs/commits/rhel-9.7
|
||||||
|
|
||||||
# Patches.
|
# Patches.
|
||||||
Patch0001: 0001-website-Add-links-for-1.54-and-1.55-download-locatio.patch
|
Patch0001: 0001-website-Add-links-for-1.54-and-1.55-download-locatio.patch
|
||||||
@ -92,6 +92,25 @@ Patch0014: 0014-website-Fix-link-to-latest-development-version.patch
|
|||||||
Patch0015: 0015-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch
|
Patch0015: 0015-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch
|
||||||
Patch0016: 0016-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch
|
Patch0016: 0016-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch
|
||||||
Patch0017: 0017-daemon-New-command_out-and-sh_out-APIs.patch
|
Patch0017: 0017-daemon-New-command_out-and-sh_out-APIs.patch
|
||||||
|
Patch0018: 0018-lib-Print-kernel-utsname-in-debug-output.patch
|
||||||
|
Patch0019: 0019-daemon-Fix-loongarch64-detection-on-RHEL-9.patch
|
||||||
|
Patch0020: 0020-daemon-inspect-Add-some-debugging-of-usr-merging.patch
|
||||||
|
Patch0021: 0021-generator-Implement-struct-FDevice-type.patch
|
||||||
|
Patch0022: 0022-generator-Use-new-FDevice-type-for-the-pvs-full-pv_n.patch
|
||||||
|
Patch0023: 0023-daemon-inspect-Resolve-Ubuntu-22-dev-disk-by-uuid-in.patch
|
||||||
|
Patch0024: 0024-generator-Fix-implementation-of-FUUID-for-OCaml-func.patch
|
||||||
|
Patch0025: 0025-Update-common-submodule.patch
|
||||||
|
Patch0026: 0026-daemon-Rewrite-pvs-vgs-lvs-full-APIs-in-OCaml.patch
|
||||||
|
Patch0027: 0027-daemon-inspect-Resolve-Ubuntu-22-dev-disk-by-id-dm-u.patch
|
||||||
|
Patch0028: 0028-RHEL-9-daemon-fstrim.c-Run-the-fstrim-command-twice.patch
|
||||||
|
Patch0029: 0029-daemon-fstrim.c-Issue-sync_disks-after-fstrim.patch
|
||||||
|
Patch0030: 0030-daemon-inspect-Remove-duplicate-root-mountpoints-in-.patch
|
||||||
|
Patch0031: 0031-lib-inspect-osinfo.c-Generate-new-osinfo-shortname-f.patch
|
||||||
|
Patch0032: 0032-daemon-Add-contents-of-etc-fstab-to-verbose-log.patch
|
||||||
|
Patch0033: 0033-appliance-init-Add-lsblk-and-blkid-output-to-verbose.patch
|
||||||
|
Patch0034: 0034-daemon-inspect_fs_windows.ml-Add-debugging-for-MBR-d.patch
|
||||||
|
Patch0035: 0035-daemon-inspect_fs_windows.ml-Add-debugging-when-we-s.patch
|
||||||
|
Patch0036: 0036-daemon-inspect_fs_windows.ml-Ignore-blank-disks-in-d.patch
|
||||||
|
|
||||||
BuildRequires: autoconf, automake, libtool, gettext-devel
|
BuildRequires: autoconf, automake, libtool, gettext-devel
|
||||||
|
|
||||||
@ -1101,6 +1120,30 @@ rm ocaml/html/.gitignore
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Aug 14 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-11
|
||||||
|
- Ignore blank disks in Windows drive mapping
|
||||||
|
resolves: RHEL-108803
|
||||||
|
|
||||||
|
* Tue Jun 17 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-9
|
||||||
|
- Generate correct osinfo for SLES >= 15
|
||||||
|
resolves: RHEL-95791
|
||||||
|
|
||||||
|
* Thu May 08 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-8
|
||||||
|
- Remove duplicate root mountpoints in /etc/fstab
|
||||||
|
resolves: RHEL-90168
|
||||||
|
|
||||||
|
* Fri Apr 25 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-7
|
||||||
|
- Run the fstrim command twice
|
||||||
|
resolves: RHEL-88508
|
||||||
|
|
||||||
|
* Wed Apr 16 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-6
|
||||||
|
- Fix virt-v2v conversion of split /usr Ubuntu 22+
|
||||||
|
resolves: RHEL-87493
|
||||||
|
|
||||||
|
* Tue Mar 11 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-5
|
||||||
|
- Include host kernel information in libguestfs debugging output
|
||||||
|
resolves: RHEL-83025
|
||||||
|
|
||||||
* Mon Feb 24 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-4
|
* Mon Feb 24 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-4
|
||||||
- Add new APIs to allow command output > 4MB
|
- Add new APIs to allow command output > 4MB
|
||||||
resolves: RHEL-80159
|
resolves: RHEL-80159
|
||||||
|
Loading…
Reference in New Issue
Block a user