Compare commits
8 Commits
imports/c8
...
c8
| Author | SHA1 | Date | |
|---|---|---|---|
| 19b514f4e3 | |||
| e03146b602 | |||
|
|
6dcb8bd912 | ||
| a3a7bc4e2c | |||
|
|
496de50291 | ||
|
|
f0aa7ae1fb | ||
|
|
1018f5c7f7 | ||
|
|
2850fa7006 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
SOURCES/libblockdev-2.24.tar.gz
|
||||
SOURCES/libblockdev-2.28.tar.gz
|
||||
|
||||
@ -1 +1 @@
|
||||
17e84346cae1ba0fa4cedeada2f8aa10b5000bd3 SOURCES/libblockdev-2.24.tar.gz
|
||||
d32fce132c75d94ad9c033a636906d63027ffba5 SOURCES/libblockdev-2.28.tar.gz
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
From 7a0e344d0642f76992c943158621d8ee7e5caea3 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 15 Nov 2022 13:21:25 +0100
|
||||
Subject: [PATCH 1/2] crypto: Fix GError overwrite from libvolume_key
|
||||
|
||||
---
|
||||
src/plugins/crypto.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c
|
||||
index 35c38410..9064c8e3 100644
|
||||
--- a/src/plugins/crypto.c
|
||||
+++ b/src/plugins/crypto.c
|
||||
@@ -2552,13 +2552,14 @@ static gboolean write_escrow_data_file (struct libvk_volume *volume, struct libv
|
||||
GIOChannel *out_file = NULL;
|
||||
GIOStatus status = G_IO_STATUS_ERROR;
|
||||
gsize bytes_written = 0;
|
||||
+ GError *l_error = NULL;
|
||||
|
||||
packet_data = libvk_volume_create_packet_asymmetric_with_format (volume, &packet_data_size, secret_type, cert,
|
||||
- ui, LIBVK_PACKET_FORMAT_ASYMMETRIC_WRAP_SECRET_ONLY, error);
|
||||
-
|
||||
+ ui, LIBVK_PACKET_FORMAT_ASYMMETRIC_WRAP_SECRET_ONLY, &l_error);
|
||||
if (!packet_data) {
|
||||
g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_ESCROW_FAILED,
|
||||
- "Failed to get escrow data");
|
||||
+ "Failed to get escrow data: %s", l_error->message);
|
||||
+ g_clear_error (&l_error);
|
||||
libvk_volume_free (volume);
|
||||
return FALSE;
|
||||
}
|
||||
--
|
||||
2.38.1
|
||||
|
||||
|
||||
From 25bf34c4c03e37eb3782dfccf459b9a3f795ddb3 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Wed, 16 Nov 2022 10:26:06 +0100
|
||||
Subject: [PATCH 2/2] crypto: Fix double free in write_escrow_data_file
|
||||
|
||||
---
|
||||
src/plugins/crypto.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c
|
||||
index 9064c8e3..2086209e 100644
|
||||
--- a/src/plugins/crypto.c
|
||||
+++ b/src/plugins/crypto.c
|
||||
@@ -2560,7 +2560,6 @@ static gboolean write_escrow_data_file (struct libvk_volume *volume, struct libv
|
||||
g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_ESCROW_FAILED,
|
||||
"Failed to get escrow data: %s", l_error->message);
|
||||
g_clear_error (&l_error);
|
||||
- libvk_volume_free (volume);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
--
|
||||
2.38.1
|
||||
|
||||
@ -1,119 +0,0 @@
|
||||
From d9571c2f1cf612ce0d479e428f7b1ae24944d140 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Wed, 10 Jun 2020 17:03:28 +0200
|
||||
Subject: [PATCH] exec: Fix setting locale for util calls
|
||||
|
||||
This actually fixes two issue. The _utils_exec_and_report_progress
|
||||
function didn't set the LC_ALL=C environment variable to make sure
|
||||
we get output in English. And also we shouldn't use setenv in the
|
||||
GSpawnChildSetupFunc, it's actually example of what not to do in
|
||||
g_spawn_async documentation. This fix uses g_environ_setenv and
|
||||
passes the new environment to the g_spawn call.
|
||||
---
|
||||
src/utils/exec.c | 26 +++++++++++++++++---------
|
||||
tests/utils_test.py | 7 +++++++
|
||||
2 files changed, 24 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/utils/exec.c b/src/utils/exec.c
|
||||
index 9293930..37bd960 100644
|
||||
--- a/src/utils/exec.c
|
||||
+++ b/src/utils/exec.c
|
||||
@@ -140,11 +140,6 @@ static void log_done (guint64 task_id, gint exit_code) {
|
||||
return;
|
||||
}
|
||||
|
||||
-static void set_c_locale(gpointer user_data __attribute__((unused))) {
|
||||
- if (setenv ("LC_ALL", "C", 1) != 0)
|
||||
- g_warning ("Failed to set LC_ALL=C for a child process!");
|
||||
-}
|
||||
-
|
||||
/**
|
||||
* bd_utils_exec_and_report_error:
|
||||
* @argv: (array zero-terminated=1): the argv array for the call
|
||||
@@ -194,6 +189,8 @@ gboolean bd_utils_exec_and_report_status_error (const gchar **argv, const BDExtr
|
||||
const BDExtraArg **extra_p = NULL;
|
||||
gint exit_status = 0;
|
||||
guint i = 0;
|
||||
+ gchar **old_env = NULL;
|
||||
+ gchar **new_env = NULL;
|
||||
|
||||
if (extra) {
|
||||
args_len = g_strv_length ((gchar **) argv);
|
||||
@@ -219,16 +216,20 @@ gboolean bd_utils_exec_and_report_status_error (const gchar **argv, const BDExtr
|
||||
args[i] = NULL;
|
||||
}
|
||||
|
||||
+ old_env = g_get_environ ();
|
||||
+ new_env = g_environ_setenv (old_env, "LC_ALL", "C", TRUE);
|
||||
+
|
||||
task_id = log_running (args ? args : argv);
|
||||
- success = g_spawn_sync (NULL, args ? (gchar **) args : (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH,
|
||||
- (GSpawnChildSetupFunc) set_c_locale, NULL,
|
||||
- &stdout_data, &stderr_data, &exit_status, error);
|
||||
+ success = g_spawn_sync (NULL, args ? (gchar **) args : (gchar **) argv, new_env, G_SPAWN_SEARCH_PATH,
|
||||
+ NULL, NULL, &stdout_data, &stderr_data, &exit_status, error);
|
||||
if (!success) {
|
||||
/* error is already populated from the call */
|
||||
+ g_strfreev (new_env);
|
||||
g_free (stdout_data);
|
||||
g_free (stderr_data);
|
||||
return FALSE;
|
||||
}
|
||||
+ g_strfreev (new_env);
|
||||
|
||||
/* g_spawn_sync set the status in the same way waitpid() does, we need
|
||||
to get the process exit code manually (this is similar to calling
|
||||
@@ -297,6 +298,8 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
gboolean err_done = FALSE;
|
||||
GString *stdout_data = g_string_new (NULL);
|
||||
GString *stderr_data = g_string_new (NULL);
|
||||
+ gchar **old_env = NULL;
|
||||
+ gchar **new_env = NULL;
|
||||
|
||||
/* TODO: share this code between functions */
|
||||
if (extra) {
|
||||
@@ -325,7 +328,10 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
|
||||
task_id = log_running (args ? args : argv);
|
||||
|
||||
- ret = g_spawn_async_with_pipes (NULL, args ? (gchar**) args : (gchar**) argv, NULL,
|
||||
+ old_env = g_get_environ ();
|
||||
+ new_env = g_environ_setenv (old_env, "LC_ALL", "C", TRUE);
|
||||
+
|
||||
+ ret = g_spawn_async_with_pipes (NULL, args ? (gchar**) args : (gchar**) argv, new_env,
|
||||
G_SPAWN_DEFAULT|G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
|
||||
NULL, NULL, &pid, NULL, &out_fd, &err_fd, error);
|
||||
|
||||
@@ -333,9 +339,11 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
/* error is already populated */
|
||||
g_string_free (stdout_data, TRUE);
|
||||
g_string_free (stderr_data, TRUE);
|
||||
+ g_strfreev (new_env);
|
||||
g_free (args);
|
||||
return FALSE;
|
||||
}
|
||||
+ g_strfreev (new_env);
|
||||
|
||||
args_str = g_strjoinv (" ", args ? (gchar **) args : (gchar **) argv);
|
||||
msg = g_strdup_printf ("Started '%s'", args_str);
|
||||
diff --git a/tests/utils_test.py b/tests/utils_test.py
|
||||
index 4bec3db..2bec5ed 100644
|
||||
--- a/tests/utils_test.py
|
||||
+++ b/tests/utils_test.py
|
||||
@@ -170,6 +170,13 @@ class UtilsExecLoggingTest(UtilsTestCase):
|
||||
# exit code != 0
|
||||
self.assertTrue(BlockDev.utils_check_util_version("libblockdev-fake-util-fail", "1.1", "version", "Version:\\s(.*)"))
|
||||
|
||||
+ @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
|
||||
+ def test_exec_locale(self):
|
||||
+ """Verify that setting locale for exec functions works as expected"""
|
||||
+
|
||||
+ succ, out = BlockDev.utils_exec_and_capture_output(["locale"])
|
||||
+ self.assertTrue(succ)
|
||||
+ self.assertIn("LC_ALL=C", out)
|
||||
|
||||
class UtilsDevUtilsTestCase(UtilsTestCase):
|
||||
@tag_test(TestTags.NOSTORAGE, TestTags.CORE)
|
||||
--
|
||||
2.26.2
|
||||
|
||||
@ -1,792 +0,0 @@
|
||||
From 592820b7a4300cfdc4f85ecd9548f7c2321689fc Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Bzatek <tbzatek@redhat.com>
|
||||
Date: Wed, 16 Sep 2020 17:45:07 +0200
|
||||
Subject: [PATCH 1/5] exec: Fix polling for stdout and stderr
|
||||
|
||||
The condition of having both the stdout and the stderr fds ready
|
||||
may never be satisfied in the case of a full stdout buffer waiting
|
||||
to be read with no output on stderr yet while both fds being still
|
||||
open. In such case the old code got stuck in an endless loop and
|
||||
the spawned process being stuck on writing to stdout/stderr. Let's
|
||||
read data from any fd once available and only react on EOF/HUP.
|
||||
|
||||
This change also makes use of POSIX poll() instead of g_poll()
|
||||
as it's more clear what the return values mean - Glib docs are
|
||||
vague in this regard and one can only guess.
|
||||
---
|
||||
src/utils/exec.c | 32 ++++++++++++++++++--------------
|
||||
1 file changed, 18 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/utils/exec.c b/src/utils/exec.c
|
||||
index 37bd960..ebbcaf2 100644
|
||||
--- a/src/utils/exec.c
|
||||
+++ b/src/utils/exec.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "extra_arg.h"
|
||||
#include <syslog.h>
|
||||
#include <stdlib.h>
|
||||
+#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -293,7 +294,7 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
gint poll_status = 0;
|
||||
guint i = 0;
|
||||
guint8 completion = 0;
|
||||
- GPollFD fds[2] = {ZERO_INIT, ZERO_INIT};
|
||||
+ struct pollfd fds[2] = { ZERO_INIT, ZERO_INIT };
|
||||
gboolean out_done = FALSE;
|
||||
gboolean err_done = FALSE;
|
||||
GString *stdout_data = g_string_new (NULL);
|
||||
@@ -360,13 +361,16 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
|
||||
fds[0].fd = out_fd;
|
||||
fds[1].fd = err_fd;
|
||||
- fds[0].events = G_IO_IN | G_IO_HUP | G_IO_ERR;
|
||||
- fds[1].events = G_IO_IN | G_IO_HUP | G_IO_ERR;
|
||||
+ fds[0].events = POLLIN | POLLHUP | POLLERR;
|
||||
+ fds[1].events = POLLIN | POLLHUP | POLLERR;
|
||||
while (!out_done || !err_done) {
|
||||
- poll_status = g_poll (fds, 2, -1);
|
||||
+ poll_status = poll (fds, 2, -1);
|
||||
+ g_warn_if_fail (poll_status != 0); /* no timeout specified, zero should never be returned */
|
||||
if (poll_status < 0) {
|
||||
+ if (errno == EAGAIN || errno == EINTR)
|
||||
+ continue;
|
||||
g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
- "Failed to poll output FDs.");
|
||||
+ "Failed to poll output FDs: %m");
|
||||
bd_utils_report_finished (progress_id, (*error)->message);
|
||||
g_io_channel_shutdown (out_pipe, FALSE, NULL);
|
||||
g_io_channel_unref (out_pipe);
|
||||
@@ -375,12 +379,9 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
g_string_free (stdout_data, TRUE);
|
||||
g_string_free (stderr_data, TRUE);
|
||||
return FALSE;
|
||||
- } else if (poll_status != 2)
|
||||
- /* both revents fields were not filled yet */
|
||||
- continue;
|
||||
- if (!(fds[0].revents & G_IO_IN))
|
||||
- out_done = TRUE;
|
||||
- while (!out_done) {
|
||||
+ }
|
||||
+
|
||||
+ while (!out_done && (fds[0].revents & POLLIN)) {
|
||||
io_status = g_io_channel_read_line (out_pipe, &line, NULL, NULL, error);
|
||||
if (io_status == G_IO_STATUS_NORMAL) {
|
||||
if (prog_extract && prog_extract (line, &completion))
|
||||
@@ -401,9 +402,10 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
- if (!(fds[1].revents & G_IO_IN))
|
||||
- err_done = TRUE;
|
||||
- while (!err_done) {
|
||||
+ if (fds[0].revents & POLLHUP || fds[0].revents & POLLERR || fds[0].revents & POLLNVAL)
|
||||
+ out_done = TRUE;
|
||||
+
|
||||
+ while (!err_done && (fds[1].revents & POLLIN)) {
|
||||
io_status = g_io_channel_read_line (err_pipe, &line, NULL, NULL, error);
|
||||
if (io_status == G_IO_STATUS_NORMAL) {
|
||||
g_string_append (stderr_data, line);
|
||||
@@ -421,6 +423,8 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
+ if (fds[1].revents & POLLHUP || fds[1].revents & POLLERR || fds[1].revents & POLLNVAL)
|
||||
+ err_done = TRUE;
|
||||
}
|
||||
|
||||
child_ret = waitpid (pid, &status, 0);
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 3025deda9ab670a454bfe373166e49f2acd1c151 Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Bzatek <tbzatek@redhat.com>
|
||||
Date: Fri, 25 Sep 2020 18:19:46 +0200
|
||||
Subject: [PATCH 2/5] exec: Use non-blocking read and process the buffer
|
||||
manually
|
||||
|
||||
Waiting for data or a newline character on one fd may create a deadlock
|
||||
while the other fd is being filled with data, exhausting the pipe buffer.
|
||||
Setting both stdout and stderr fds non-blocking allows us to get indication
|
||||
of an empty pipe, continuing with the read cycle over remaining watched fds.
|
||||
|
||||
This also gets rid of GIOChannel as no extended functionality like GSource
|
||||
notifications were used, degrading GIOChannel in a simple GObject wrapper
|
||||
over an fd with just a convenience read_line method that we had to get rid of
|
||||
anyway. Let's use standard POSIX calls and split the read buffer manually
|
||||
by matching the newline character. NULL bytes should be handled gracefully
|
||||
however the stack higher up is not ready for that anyway.
|
||||
---
|
||||
src/utils/exec.c | 277 +++++++++++++++++++++++++++--------------------
|
||||
1 file changed, 159 insertions(+), 118 deletions(-)
|
||||
|
||||
diff --git a/src/utils/exec.c b/src/utils/exec.c
|
||||
index ebbcaf2..317fb55 100644
|
||||
--- a/src/utils/exec.c
|
||||
+++ b/src/utils/exec.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <syslog.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
+#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -272,6 +273,87 @@ gboolean bd_utils_exec_and_report_status_error (const gchar **argv, const BDExtr
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+/* buffer size in bytes used to read from stdout and stderr */
|
||||
+#define _EXEC_BUF_SIZE 64*1024
|
||||
+
|
||||
+/* similar to g_strstr_len() yet treats 'null' byte as @needle. */
|
||||
+static gchar *bd_strchr_len_null (const gchar *haystack, gssize haystack_len, const gchar needle) {
|
||||
+ gchar *ret;
|
||||
+ gchar *ret_null;
|
||||
+
|
||||
+ ret = memchr (haystack, needle, haystack_len);
|
||||
+ ret_null = memchr (haystack, 0, haystack_len);
|
||||
+ if (ret && ret_null)
|
||||
+ return MIN (ret, ret_null);
|
||||
+ else
|
||||
+ return MAX (ret, ret_null);
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+_process_fd_event (gint fd, struct pollfd *poll_fd, GString *read_buffer, GString *filtered_buffer, gsize *read_buffer_pos, gboolean *done,
|
||||
+ guint64 progress_id, guint8 *progress, BDUtilsProgExtract prog_extract, GError **error) {
|
||||
+ gchar buf[_EXEC_BUF_SIZE] = { 0 };
|
||||
+ ssize_t num_read;
|
||||
+ gchar *line;
|
||||
+ gchar *newline_pos;
|
||||
+ int errno_saved;
|
||||
+ gboolean eof = FALSE;
|
||||
+
|
||||
+ if (! *done && (poll_fd->revents & POLLIN)) {
|
||||
+ /* read until we get EOF (0) or error (-1), expecting EAGAIN */
|
||||
+ while ((num_read = read (fd, buf, _EXEC_BUF_SIZE)) > 0)
|
||||
+ g_string_append_len (read_buffer, buf, num_read);
|
||||
+ errno_saved = errno;
|
||||
+
|
||||
+ /* process the fresh data by lines */
|
||||
+ if (read_buffer->len > *read_buffer_pos) {
|
||||
+ gchar *buf_ptr;
|
||||
+ gsize buf_len;
|
||||
+
|
||||
+ while ((buf_ptr = read_buffer->str + *read_buffer_pos,
|
||||
+ buf_len = read_buffer->len - *read_buffer_pos,
|
||||
+ newline_pos = bd_strchr_len_null (buf_ptr, buf_len, '\n'))) {
|
||||
+ line = g_strndup (buf_ptr, newline_pos - buf_ptr + 1);
|
||||
+ if (prog_extract && prog_extract (line, progress))
|
||||
+ bd_utils_report_progress (progress_id, *progress, NULL);
|
||||
+ else
|
||||
+ g_string_append (filtered_buffer, line);
|
||||
+ g_free (line);
|
||||
+ *read_buffer_pos = newline_pos - read_buffer->str + 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* read error */
|
||||
+ if (num_read < 0 && errno_saved != EAGAIN && errno_saved != EINTR) {
|
||||
+ g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
+ "Error reading from pipe: %s", g_strerror (errno_saved));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ /* EOF */
|
||||
+ if (num_read == 0)
|
||||
+ eof = TRUE;
|
||||
+ }
|
||||
+
|
||||
+ if (poll_fd->revents & POLLHUP || poll_fd->revents & POLLERR || poll_fd->revents & POLLNVAL)
|
||||
+ eof = TRUE;
|
||||
+
|
||||
+ if (eof) {
|
||||
+ *done = TRUE;
|
||||
+ /* process the remaining buffer */
|
||||
+ line = read_buffer->str + *read_buffer_pos;
|
||||
+ /* GString guarantees the buffer is always NULL-terminated. */
|
||||
+ if (strlen (line) > 0) {
|
||||
+ if (prog_extract && prog_extract (line, progress))
|
||||
+ bd_utils_report_progress (progress_id, *progress, NULL);
|
||||
+ else
|
||||
+ g_string_append (filtered_buffer, line);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExtraArg **extra, BDUtilsProgExtract prog_extract, gint *proc_status, gchar **stdout, gchar **stderr, GError **error) {
|
||||
const gchar **args = NULL;
|
||||
guint args_len = 0;
|
||||
@@ -283,24 +365,26 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
gchar *msg = NULL;
|
||||
GPid pid = 0;
|
||||
gint out_fd = 0;
|
||||
- GIOChannel *out_pipe = NULL;
|
||||
gint err_fd = 0;
|
||||
- GIOChannel *err_pipe = NULL;
|
||||
- gchar *line = NULL;
|
||||
gint child_ret = -1;
|
||||
gint status = 0;
|
||||
gboolean ret = FALSE;
|
||||
- GIOStatus io_status = G_IO_STATUS_NORMAL;
|
||||
gint poll_status = 0;
|
||||
guint i = 0;
|
||||
guint8 completion = 0;
|
||||
struct pollfd fds[2] = { ZERO_INIT, ZERO_INIT };
|
||||
+ int flags;
|
||||
gboolean out_done = FALSE;
|
||||
gboolean err_done = FALSE;
|
||||
- GString *stdout_data = g_string_new (NULL);
|
||||
- GString *stderr_data = g_string_new (NULL);
|
||||
+ GString *stdout_data;
|
||||
+ GString *stdout_buffer;
|
||||
+ GString *stderr_data;
|
||||
+ GString *stderr_buffer;
|
||||
+ gsize stdout_buffer_pos = 0;
|
||||
+ gsize stderr_buffer_pos = 0;
|
||||
gchar **old_env = NULL;
|
||||
gchar **new_env = NULL;
|
||||
+ gboolean success = TRUE;
|
||||
|
||||
/* TODO: share this code between functions */
|
||||
if (extra) {
|
||||
@@ -336,15 +420,13 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
G_SPAWN_DEFAULT|G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
|
||||
NULL, NULL, &pid, NULL, &out_fd, &err_fd, error);
|
||||
|
||||
+ g_strfreev (new_env);
|
||||
+
|
||||
if (!ret) {
|
||||
/* error is already populated */
|
||||
- g_string_free (stdout_data, TRUE);
|
||||
- g_string_free (stderr_data, TRUE);
|
||||
- g_strfreev (new_env);
|
||||
g_free (args);
|
||||
return FALSE;
|
||||
}
|
||||
- g_strfreev (new_env);
|
||||
|
||||
args_str = g_strjoinv (" ", args ? (gchar **) args : (gchar **) argv);
|
||||
msg = g_strdup_printf ("Started '%s'", args_str);
|
||||
@@ -353,18 +435,25 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
g_free (args);
|
||||
g_free (msg);
|
||||
|
||||
- out_pipe = g_io_channel_unix_new (out_fd);
|
||||
- err_pipe = g_io_channel_unix_new (err_fd);
|
||||
+ /* set both fds for non-blocking read */
|
||||
+ flags = fcntl (out_fd, F_GETFL, 0);
|
||||
+ if (fcntl (out_fd, F_SETFL, flags | O_NONBLOCK))
|
||||
+ g_warning ("_utils_exec_and_report_progress: Failed to set out_fd non-blocking: %m");
|
||||
+ flags = fcntl (err_fd, F_GETFL, 0);
|
||||
+ if (fcntl (err_fd, F_SETFL, flags | O_NONBLOCK))
|
||||
+ g_warning ("_utils_exec_and_report_progress: Failed to set err_fd non-blocking: %m");
|
||||
|
||||
- g_io_channel_set_encoding (out_pipe, NULL, NULL);
|
||||
- g_io_channel_set_encoding (err_pipe, NULL, NULL);
|
||||
+ stdout_data = g_string_new (NULL);
|
||||
+ stdout_buffer = g_string_new (NULL);
|
||||
+ stderr_data = g_string_new (NULL);
|
||||
+ stderr_buffer = g_string_new (NULL);
|
||||
|
||||
fds[0].fd = out_fd;
|
||||
fds[1].fd = err_fd;
|
||||
fds[0].events = POLLIN | POLLHUP | POLLERR;
|
||||
fds[1].events = POLLIN | POLLHUP | POLLERR;
|
||||
- while (!out_done || !err_done) {
|
||||
- poll_status = poll (fds, 2, -1);
|
||||
+ while (! (out_done && err_done)) {
|
||||
+ poll_status = poll (fds, 2, -1 /* timeout */);
|
||||
g_warn_if_fail (poll_status != 0); /* no timeout specified, zero should never be returned */
|
||||
if (poll_status < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
@@ -372,140 +461,90 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
||||
g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
"Failed to poll output FDs: %m");
|
||||
bd_utils_report_finished (progress_id, (*error)->message);
|
||||
- g_io_channel_shutdown (out_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (out_pipe);
|
||||
- g_io_channel_shutdown (err_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (err_pipe);
|
||||
- g_string_free (stdout_data, TRUE);
|
||||
- g_string_free (stderr_data, TRUE);
|
||||
- return FALSE;
|
||||
+ success = FALSE;
|
||||
+ break;
|
||||
}
|
||||
|
||||
- while (!out_done && (fds[0].revents & POLLIN)) {
|
||||
- io_status = g_io_channel_read_line (out_pipe, &line, NULL, NULL, error);
|
||||
- if (io_status == G_IO_STATUS_NORMAL) {
|
||||
- if (prog_extract && prog_extract (line, &completion))
|
||||
- bd_utils_report_progress (progress_id, completion, NULL);
|
||||
- else
|
||||
- g_string_append (stdout_data, line);
|
||||
- g_free (line);
|
||||
- } else if (io_status == G_IO_STATUS_EOF) {
|
||||
- out_done = TRUE;
|
||||
- } else if (error && (*error)) {
|
||||
+ if (!out_done) {
|
||||
+ if (! _process_fd_event (out_fd, &fds[0], stdout_buffer, stdout_data, &stdout_buffer_pos, &out_done, progress_id, &completion, prog_extract, error)) {
|
||||
bd_utils_report_finished (progress_id, (*error)->message);
|
||||
- g_io_channel_shutdown (out_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (out_pipe);
|
||||
- g_io_channel_shutdown (err_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (err_pipe);
|
||||
- g_string_free (stdout_data, TRUE);
|
||||
- g_string_free (stderr_data, TRUE);
|
||||
- return FALSE;
|
||||
+ success = FALSE;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
- if (fds[0].revents & POLLHUP || fds[0].revents & POLLERR || fds[0].revents & POLLNVAL)
|
||||
- out_done = TRUE;
|
||||
|
||||
- while (!err_done && (fds[1].revents & POLLIN)) {
|
||||
- io_status = g_io_channel_read_line (err_pipe, &line, NULL, NULL, error);
|
||||
- if (io_status == G_IO_STATUS_NORMAL) {
|
||||
- g_string_append (stderr_data, line);
|
||||
- g_free (line);
|
||||
- } else if (io_status == G_IO_STATUS_EOF) {
|
||||
- err_done = TRUE;
|
||||
- } else if (error && (*error)) {
|
||||
+ if (!err_done) {
|
||||
+ if (! _process_fd_event (err_fd, &fds[1], stderr_buffer, stderr_data, &stderr_buffer_pos, &err_done, progress_id, &completion, prog_extract, error)) {
|
||||
bd_utils_report_finished (progress_id, (*error)->message);
|
||||
- g_io_channel_shutdown (out_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (out_pipe);
|
||||
- g_io_channel_shutdown (err_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (err_pipe);
|
||||
- g_string_free (stdout_data, TRUE);
|
||||
- g_string_free (stderr_data, TRUE);
|
||||
- return FALSE;
|
||||
+ success = FALSE;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
- if (fds[1].revents & POLLHUP || fds[1].revents & POLLERR || fds[1].revents & POLLNVAL)
|
||||
- err_done = TRUE;
|
||||
}
|
||||
|
||||
+ g_string_free (stdout_buffer, TRUE);
|
||||
+ g_string_free (stderr_buffer, TRUE);
|
||||
+ close (out_fd);
|
||||
+ close (err_fd);
|
||||
+
|
||||
child_ret = waitpid (pid, &status, 0);
|
||||
- *proc_status = WEXITSTATUS(status);
|
||||
- if (child_ret > 0) {
|
||||
- if (*proc_status != 0) {
|
||||
- if (stderr_data->str && (g_strcmp0 ("", stderr_data->str) != 0))
|
||||
- msg = stderr_data->str;
|
||||
- else
|
||||
- msg = stdout_data->str;
|
||||
- g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
- "Process reported exit code %d: %s", *proc_status, msg);
|
||||
- bd_utils_report_finished (progress_id, (*error)->message);
|
||||
- g_io_channel_shutdown (out_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (out_pipe);
|
||||
- g_io_channel_shutdown (err_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (err_pipe);
|
||||
- g_string_free (stdout_data, TRUE);
|
||||
- g_string_free (stderr_data, TRUE);
|
||||
- return FALSE;
|
||||
- }
|
||||
- if (WIFSIGNALED(status)) {
|
||||
- g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
- "Process killed with a signal");
|
||||
- bd_utils_report_finished (progress_id, (*error)->message);
|
||||
- g_io_channel_shutdown (out_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (out_pipe);
|
||||
- g_io_channel_shutdown (err_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (err_pipe);
|
||||
- g_string_free (stdout_data, TRUE);
|
||||
- g_string_free (stderr_data, TRUE);
|
||||
- return FALSE;
|
||||
- }
|
||||
- } else if (child_ret == -1) {
|
||||
- if (errno != ECHILD) {
|
||||
- errno = 0;
|
||||
- g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
- "Failed to wait for the process");
|
||||
- bd_utils_report_finished (progress_id, (*error)->message);
|
||||
- g_io_channel_shutdown (out_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (out_pipe);
|
||||
- g_io_channel_shutdown (err_pipe, FALSE, NULL);
|
||||
- g_io_channel_unref (err_pipe);
|
||||
- g_string_free (stdout_data, TRUE);
|
||||
- g_string_free (stderr_data, TRUE);
|
||||
- return FALSE;
|
||||
+ *proc_status = WEXITSTATUS (status);
|
||||
+ if (success) {
|
||||
+ if (child_ret > 0) {
|
||||
+ if (*proc_status != 0) {
|
||||
+ msg = stderr_data->len > 0 ? stderr_data->str : stdout_data->str;
|
||||
+ g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
+ "Process reported exit code %d: %s", *proc_status, msg);
|
||||
+ bd_utils_report_finished (progress_id, (*error)->message);
|
||||
+ success = FALSE;
|
||||
+ } else if (WIFSIGNALED (status)) {
|
||||
+ g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
+ "Process killed with a signal");
|
||||
+ bd_utils_report_finished (progress_id, (*error)->message);
|
||||
+ success = FALSE;
|
||||
+ }
|
||||
+ } else if (child_ret == -1) {
|
||||
+ if (errno != ECHILD) {
|
||||
+ errno = 0;
|
||||
+ g_set_error (error, BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED,
|
||||
+ "Failed to wait for the process");
|
||||
+ bd_utils_report_finished (progress_id, (*error)->message);
|
||||
+ success = FALSE;
|
||||
+ } else {
|
||||
+ /* no such process (the child exited before we tried to wait for it) */
|
||||
+ errno = 0;
|
||||
+ }
|
||||
}
|
||||
- /* no such process (the child exited before we tried to wait for it) */
|
||||
- errno = 0;
|
||||
+ if (success)
|
||||
+ bd_utils_report_finished (progress_id, "Completed");
|
||||
}
|
||||
-
|
||||
- bd_utils_report_finished (progress_id, "Completed");
|
||||
log_out (task_id, stdout_data->str, stderr_data->str);
|
||||
log_done (task_id, *proc_status);
|
||||
|
||||
- /* we don't care about the status here */
|
||||
- g_io_channel_shutdown (out_pipe, FALSE, error);
|
||||
- g_io_channel_unref (out_pipe);
|
||||
- g_io_channel_shutdown (err_pipe, FALSE, error);
|
||||
- g_io_channel_unref (err_pipe);
|
||||
-
|
||||
- if (stdout)
|
||||
+ if (success && stdout)
|
||||
*stdout = g_string_free (stdout_data, FALSE);
|
||||
else
|
||||
g_string_free (stdout_data, TRUE);
|
||||
- if (stderr)
|
||||
+ if (success && stderr)
|
||||
*stderr = g_string_free (stderr_data, FALSE);
|
||||
else
|
||||
g_string_free (stderr_data, TRUE);
|
||||
|
||||
- return TRUE;
|
||||
+ return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* bd_utils_exec_and_report_progress:
|
||||
* @argv: (array zero-terminated=1): the argv array for the call
|
||||
* @extra: (allow-none) (array zero-terminated=1): extra arguments
|
||||
- * @prog_extract: (scope notified): function for extracting progress information
|
||||
+ * @prog_extract: (scope notified) (nullable): function for extracting progress information
|
||||
* @proc_status: (out): place to store the process exit status
|
||||
* @error: (out): place to store error (if any)
|
||||
*
|
||||
+ * Note that any NULL bytes read from standard output and standard error
|
||||
+ * output are treated as separators similar to newlines and @prog_extract
|
||||
+ * will be called with the respective chunk.
|
||||
+ *
|
||||
* Returns: whether the @argv was successfully executed (no error and exit code 0) or not
|
||||
*/
|
||||
gboolean bd_utils_exec_and_report_progress (const gchar **argv, const BDExtraArg **extra, BDUtilsProgExtract prog_extract, gint *proc_status, GError **error) {
|
||||
@@ -519,6 +558,9 @@ gboolean bd_utils_exec_and_report_progress (const gchar **argv, const BDExtraArg
|
||||
* @output: (out): variable to store output to
|
||||
* @error: (out): place to store error (if any)
|
||||
*
|
||||
+ * Note that any NULL bytes read from standard output and standard error
|
||||
+ * output will be discarded.
|
||||
+ *
|
||||
* Returns: whether the @argv was successfully executed capturing the output or not
|
||||
*/
|
||||
gboolean bd_utils_exec_and_capture_output (const gchar **argv, const BDExtraArg **extra, gchar **output, GError **error) {
|
||||
@@ -549,7 +591,6 @@ gboolean bd_utils_exec_and_capture_output (const gchar **argv, const BDExtraArg
|
||||
g_free (stderr);
|
||||
return TRUE;
|
||||
}
|
||||
-
|
||||
}
|
||||
|
||||
/**
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From f5eb61c91ffc6b0d1fd709076a9579105655ff17 Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Bzatek <tbzatek@redhat.com>
|
||||
Date: Fri, 25 Sep 2020 18:27:02 +0200
|
||||
Subject: [PATCH 3/5] exec: Clarify the BDUtilsProgExtract callback
|
||||
documentation
|
||||
|
||||
---
|
||||
src/utils/exec.h | 24 ++++++++++++++++++++++--
|
||||
1 file changed, 22 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/utils/exec.h b/src/utils/exec.h
|
||||
index ad169e4..0e262a2 100644
|
||||
--- a/src/utils/exec.h
|
||||
+++ b/src/utils/exec.h
|
||||
@@ -31,10 +31,30 @@ typedef void (*BDUtilsProgFunc) (guint64 task_id, BDUtilsProgStatus status, guin
|
||||
|
||||
/**
|
||||
* BDUtilsProgExtract:
|
||||
- * @line: line from extract progress from
|
||||
+ * @line: line to extract progress from
|
||||
* @completion: (out): percentage of completion
|
||||
*
|
||||
- * Returns: whether the line was a progress reporting line or not
|
||||
+ * Callback function used to process a line captured from spawned command's standard
|
||||
+ * output and standard error output. Typically used to extract completion percentage
|
||||
+ * of a long-running job.
|
||||
+ *
|
||||
+ * Note that both outputs are read simultaneously with no guarantees of message order
|
||||
+ * this function is called with.
|
||||
+ *
|
||||
+ * The value the @completion points to may contain value previously returned from
|
||||
+ * this callback or zero when called for the first time. This is useful for extractors
|
||||
+ * where only some kind of a tick mark is printed out as a progress and previous value
|
||||
+ * is needed to compute an incremented value. It's important to keep in mind that this
|
||||
+ * function is only called over lines, i.e. progress reporting printing out tick marks
|
||||
+ * (e.g. dots) without a newline character might not work properly.
|
||||
+ *
|
||||
+ * The @line string usually contains trailing newline character, which may be absent
|
||||
+ * however in case the spawned command exits without printing one. It's guaranteed
|
||||
+ * this function is called over remaining buffer no matter what the trailing
|
||||
+ * character is.
|
||||
+ *
|
||||
+ * Returns: whether the line was a progress reporting line and should be excluded
|
||||
+ * from the collected standard output string or not.
|
||||
*/
|
||||
typedef gboolean (*BDUtilsProgExtract) (const gchar *line, guint8 *completion);
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 8a7f0de5f63099a3e8bcaca005c4de04df959113 Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Bzatek <tbzatek@redhat.com>
|
||||
Date: Fri, 25 Sep 2020 18:27:41 +0200
|
||||
Subject: [PATCH 4/5] tests: Add bufferbloat exec tests
|
||||
|
||||
This should test pipe buffer exhaustion as well as potential pipe
|
||||
read starvation while filling the other fd.
|
||||
---
|
||||
tests/utils_test.py | 105 +++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 104 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/utils_test.py b/tests/utils_test.py
|
||||
index 2bec5ed..ed13611 100644
|
||||
--- a/tests/utils_test.py
|
||||
+++ b/tests/utils_test.py
|
||||
@@ -1,8 +1,9 @@
|
||||
import unittest
|
||||
import re
|
||||
import os
|
||||
+import six
|
||||
import overrides_hack
|
||||
-from utils import fake_utils, create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test
|
||||
+from utils import fake_utils, create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test, read_file
|
||||
|
||||
from gi.repository import BlockDev, GLib
|
||||
|
||||
@@ -65,6 +66,9 @@ class UtilsExecLoggingTest(UtilsTestCase):
|
||||
succ = BlockDev.utils_exec_and_report_error(["true"])
|
||||
self.assertTrue(succ)
|
||||
|
||||
+ with six.assertRaisesRegex(self, GLib.GError, r"Process reported exit code 1"):
|
||||
+ succ = BlockDev.utils_exec_and_report_error(["/bin/false"])
|
||||
+
|
||||
succ, out = BlockDev.utils_exec_and_capture_output(["echo", "hi"])
|
||||
self.assertTrue(succ)
|
||||
self.assertEqual(out, "hi\n")
|
||||
@@ -178,6 +182,105 @@ class UtilsExecLoggingTest(UtilsTestCase):
|
||||
self.assertTrue(succ)
|
||||
self.assertIn("LC_ALL=C", out)
|
||||
|
||||
+ @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
|
||||
+ def test_exec_buffer_bloat(self):
|
||||
+ """Verify that very large output from a command is handled properly"""
|
||||
+
|
||||
+ # easy 64kB of data
|
||||
+ cnt = 65536
|
||||
+ succ, out = BlockDev.utils_exec_and_capture_output(["bash", "-c", "for i in {1..%d}; do echo -n .; done" % cnt])
|
||||
+ self.assertTrue(succ)
|
||||
+ self.assertEquals(len(out), cnt)
|
||||
+
|
||||
+ succ, out = BlockDev.utils_exec_and_capture_output(["bash", "-c", "for i in {1..%d}; do echo -n .; echo -n \# >&2; done" % cnt])
|
||||
+ self.assertTrue(succ)
|
||||
+ self.assertEquals(len(out), cnt)
|
||||
+
|
||||
+ # now exceed the system pipe buffer size
|
||||
+ # pipe(7): The maximum size (in bytes) of individual pipes that can be set by users without the CAP_SYS_RESOURCE capability.
|
||||
+ cnt = int(read_file("/proc/sys/fs/pipe-max-size")) + 100
|
||||
+ self.assertGreater(cnt, 0)
|
||||
+
|
||||
+ succ, out = BlockDev.utils_exec_and_capture_output(["bash", "-c", "for i in {1..%d}; do echo -n .; done" % cnt])
|
||||
+ self.assertTrue(succ)
|
||||
+ self.assertEquals(len(out), cnt)
|
||||
+
|
||||
+ succ, out = BlockDev.utils_exec_and_capture_output(["bash", "-c", "for i in {1..%d}; do echo -n .; echo -n \# >&2; done" % cnt])
|
||||
+ self.assertTrue(succ)
|
||||
+ self.assertEquals(len(out), cnt)
|
||||
+
|
||||
+ # make use of some newlines
|
||||
+ succ, out = BlockDev.utils_exec_and_capture_output(["bash", "-c", "for i in {1..%d}; do echo -n .; if [ $(($i%%500)) -eq 0 ]; then echo ''; fi; done" % cnt])
|
||||
+ self.assertTrue(succ)
|
||||
+ self.assertGreater(len(out), cnt)
|
||||
+
|
||||
+ succ, out = BlockDev.utils_exec_and_capture_output(["bash", "-c", "for i in {1..%d}; do echo -n .; echo -n \# >&2; if [ $(($i%%500)) -eq 0 ]; then echo ''; echo '' >&2; fi; done" % cnt])
|
||||
+ self.assertTrue(succ)
|
||||
+ self.assertGreater(len(out), cnt)
|
||||
+
|
||||
+
|
||||
+ EXEC_PROGRESS_MSG = "Aloha, I'm the progress line you should match."
|
||||
+
|
||||
+ def my_exec_progress_func_concat(self, line):
|
||||
+ """Expect an concatenated string"""
|
||||
+ s = ""
|
||||
+ for i in range(10):
|
||||
+ s += self.EXEC_PROGRESS_MSG
|
||||
+ self.assertEqual(line, s)
|
||||
+ self.num_matches += 1
|
||||
+ return 0
|
||||
+
|
||||
+ def my_exec_progress_func(self, line):
|
||||
+ self.assertTrue(re.match(r".*%s.*" % self.EXEC_PROGRESS_MSG, line))
|
||||
+ self.num_matches += 1
|
||||
+ return 0
|
||||
+
|
||||
+ def test_exec_buffer_bloat_progress(self):
|
||||
+ """Verify that progress reporting can handle large output"""
|
||||
+
|
||||
+ # no newlines, should match just a single occurrence on EOF
|
||||
+ cnt = 10
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..10}; do echo -n \"%s\"; done" % self.EXEC_PROGRESS_MSG], None, self.my_exec_progress_func_concat)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, 1)
|
||||
+
|
||||
+ # ten matches
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo \"%s\"; done" % (cnt, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, cnt)
|
||||
+
|
||||
+ # 100k matches
|
||||
+ cnt = 100000
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo \"%s\"; done" % (cnt, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, cnt)
|
||||
+
|
||||
+ # 100k matches on stderr
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo \"%s\" >&2; done" % (cnt, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, cnt)
|
||||
+
|
||||
+ # 100k matches on stderr and stdout
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo \"%s\"; echo \"%s\" >&2; done" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, cnt * 2)
|
||||
+
|
||||
+ # stdout and stderr output, non-zero return from the command and very long exception message
|
||||
+ self.num_matches = 0
|
||||
+ with six.assertRaisesRegex(self, GLib.GError, r"Process reported exit code 66"):
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo \"%s\"; echo \"%s\" >&2; done; exit 66" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertEqual(self.num_matches, cnt * 2)
|
||||
+
|
||||
+ # no progress reporting callback given, tests slightly different code path
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo \"%s\"; echo \"%s\" >&2; done" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, None)
|
||||
+ self.assertTrue(status)
|
||||
+
|
||||
+
|
||||
class UtilsDevUtilsTestCase(UtilsTestCase):
|
||||
@tag_test(TestTags.NOSTORAGE, TestTags.CORE)
|
||||
def test_resolve_device(self):
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 7a3fd3d32dd325fb5188bcba74966e414e33c343 Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Bzatek <tbzatek@redhat.com>
|
||||
Date: Wed, 30 Sep 2020 14:52:27 +0200
|
||||
Subject: [PATCH 5/5] tests: Add null-byte exec tests
|
||||
|
||||
Some commands may print out NULL bytes in the middle of their output,
|
||||
make sure everything works correctly.
|
||||
---
|
||||
tests/utils_test.py | 48 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 48 insertions(+)
|
||||
|
||||
diff --git a/tests/utils_test.py b/tests/utils_test.py
|
||||
index ed13611..1235be3 100644
|
||||
--- a/tests/utils_test.py
|
||||
+++ b/tests/utils_test.py
|
||||
@@ -280,6 +280,54 @@ class UtilsExecLoggingTest(UtilsTestCase):
|
||||
status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo \"%s\"; echo \"%s\" >&2; done" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, None)
|
||||
self.assertTrue(status)
|
||||
|
||||
+ def test_exec_null_bytes(self):
|
||||
+ """Verify that null bytes in the output are processed properly"""
|
||||
+
|
||||
+ TEST_DATA = ["First line", "Second line", "Third line"]
|
||||
+
|
||||
+ status, out = BlockDev.utils_exec_and_capture_output(["bash", "-c", "echo -e \"%s\\0%s\\n%s\"" % (TEST_DATA[0], TEST_DATA[1], TEST_DATA[2])])
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertTrue(TEST_DATA[0] in out)
|
||||
+ self.assertTrue(TEST_DATA[1] in out)
|
||||
+ self.assertTrue(TEST_DATA[2] in out)
|
||||
+ self.assertFalse("kuku!" in out)
|
||||
+
|
||||
+ # ten matches
|
||||
+ cnt = 10
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo -e \"%s\\0%s\"; done" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, cnt * 2)
|
||||
+
|
||||
+ # 100k matches
|
||||
+ cnt = 100000
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo -e \"%s\\0%s\"; done" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, cnt * 2)
|
||||
+
|
||||
+ # 100k matches on stderr
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo -e \"%s\\0%s\" >&2; done" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, cnt * 2)
|
||||
+
|
||||
+ # 100k matches on stderr and stdout
|
||||
+ self.num_matches = 0
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo -e \"%s\\0%s\"; echo -e \"%s\\0%s\" >&2; done" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertTrue(status)
|
||||
+ self.assertEqual(self.num_matches, cnt * 4)
|
||||
+
|
||||
+ # stdout and stderr output, non-zero return from the command and very long exception message
|
||||
+ self.num_matches = 0
|
||||
+ with six.assertRaisesRegex(self, GLib.GError, r"Process reported exit code 66"):
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo -e \"%s\\0%s\"; echo -e \"%s\\0%s\" >&2; done; exit 66" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, self.my_exec_progress_func)
|
||||
+ self.assertEqual(self.num_matches, cnt * 4)
|
||||
+
|
||||
+ # no progress reporting callback given, tests slightly different code path
|
||||
+ status = BlockDev.utils_exec_and_report_progress(["bash", "-c", "for i in {1..%d}; do echo -e \"%s\\0%s\"; echo -e \"%s\\0%s\" >&2; done" % (cnt, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG, self.EXEC_PROGRESS_MSG)], None, None)
|
||||
+ self.assertTrue(status)
|
||||
+
|
||||
|
||||
class UtilsDevUtilsTestCase(UtilsTestCase):
|
||||
@tag_test(TestTags.NOSTORAGE, TestTags.CORE)
|
||||
--
|
||||
2.26.2
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
From 6700dfded31219c99fea054aa10fd68b90bace82 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Mon, 31 Oct 2022 12:43:17 +0100
|
||||
Subject: [PATCH] tests: Fix test_swapon_pagesize on systems with 64k pages
|
||||
|
||||
---
|
||||
tests/swap_test.py | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/swap_test.py b/tests/swap_test.py
|
||||
index 0a0f333d..e350f8e8 100644
|
||||
--- a/tests/swap_test.py
|
||||
+++ b/tests/swap_test.py
|
||||
@@ -1,5 +1,6 @@
|
||||
import unittest
|
||||
import os
|
||||
+import resource
|
||||
import overrides_hack
|
||||
|
||||
from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, run_command, run, TestTags, tag_test
|
||||
@@ -102,8 +103,15 @@ class SwapTestCase(SwapTest):
|
||||
def test_swapon_pagesize(self):
|
||||
"""Verify that activating swap with different pagesize fails"""
|
||||
|
||||
- # create swap with 64k pagesize
|
||||
- ret, out, err = run_command("mkswap --pagesize 65536 %s" % self.loop_dev)
|
||||
+ # pick some wrong page size: 8k on 64k and 64k everywhere else
|
||||
+ pagesize = resource.getpagesize()
|
||||
+ if pagesize == 65536:
|
||||
+ wrong_pagesize = 8192
|
||||
+ else:
|
||||
+ wrong_pagesize = 65536
|
||||
+
|
||||
+ # create swap with "wrong" pagesize
|
||||
+ ret, out, err = run_command("mkswap --pagesize %s %s" % (wrong_pagesize, self.loop_dev))
|
||||
if ret != 0:
|
||||
self.fail("Failed to prepare swap for pagesize test: %s %s" % (out, err))
|
||||
|
||||
--
|
||||
2.39.2
|
||||
|
||||
@ -1,914 +0,0 @@
|
||||
From 2bb371937c7ef73f26717e57a5eb78cafe90a9f7 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Fri, 20 Sep 2019 09:58:01 +0200
|
||||
Subject: [PATCH 1/5] Mark all GIR file constants as guint64
|
||||
|
||||
See 9676585e65f69ec1c309f45ba139035408d59b8e for more information.
|
||||
---
|
||||
src/lib/plugin_apis/btrfs.api | 2 +-
|
||||
src/lib/plugin_apis/crypto.api | 2 +-
|
||||
src/lib/plugin_apis/lvm.api | 20 ++++++++++----------
|
||||
src/lib/plugin_apis/mdraid.api | 4 ++--
|
||||
4 files changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/lib/plugin_apis/btrfs.api b/src/lib/plugin_apis/btrfs.api
|
||||
index b52fb4ce..ef0f6c28 100644
|
||||
--- a/src/lib/plugin_apis/btrfs.api
|
||||
+++ b/src/lib/plugin_apis/btrfs.api
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <blockdev/utils.h>
|
||||
|
||||
#define BD_BTRFS_MAIN_VOLUME_ID 5
|
||||
-#define BD_BTRFS_MIN_MEMBER_SIZE (128 MiB)
|
||||
+#define BD_BTRFS_MIN_MEMBER_SIZE G_GUINT64_CONSTANT (134217728ULL) // 128 MiB
|
||||
|
||||
GQuark bd_btrfs_error_quark (void) {
|
||||
return g_quark_from_static_string ("g-bd-btrfs-error-quark");
|
||||
diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api
|
||||
index e3d69986..ef0217fe 100644
|
||||
--- a/src/lib/plugin_apis/crypto.api
|
||||
+++ b/src/lib/plugin_apis/crypto.api
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <glib.h>
|
||||
#include <blockdev/utils.h>
|
||||
|
||||
-#define BD_CRYPTO_LUKS_METADATA_SIZE (2 MiB)
|
||||
+#define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB
|
||||
|
||||
GQuark bd_crypto_error_quark (void) {
|
||||
return g_quark_from_static_string ("g-bd-crypto-error-quark");
|
||||
diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api
|
||||
index 21c8f74d..ea52263b 100644
|
||||
--- a/src/lib/plugin_apis/lvm.api
|
||||
+++ b/src/lib/plugin_apis/lvm.api
|
||||
@@ -15,18 +15,18 @@
|
||||
#define BD_LVM_MAX_LV_SIZE G_GUINT64_CONSTANT (9223372036854775808ULL)
|
||||
|
||||
|
||||
-#define BD_LVM_DEFAULT_PE_START (1 MiB)
|
||||
-#define BD_LVM_DEFAULT_PE_SIZE (4 MiB)
|
||||
-#define BD_LVM_MIN_PE_SIZE (1 KiB)
|
||||
-#define BD_LVM_MAX_PE_SIZE (16 GiB)
|
||||
-#define BD_LVM_MIN_THPOOL_MD_SIZE (2 MiB)
|
||||
-#define BD_LVM_MAX_THPOOL_MD_SIZE (16 GiB)
|
||||
-#define BD_LVM_MIN_THPOOL_CHUNK_SIZE (64 KiB)
|
||||
-#define BD_LVM_MAX_THPOOL_CHUNK_SIZE (1 GiB)
|
||||
-#define BD_LVM_DEFAULT_CHUNK_SIZE (64 KiB)
|
||||
+#define BD_LVM_DEFAULT_PE_START G_GUINT64_CONSTANT (1048576ULL) // 1 MiB
|
||||
+#define BD_LVM_DEFAULT_PE_SIZE G_GUINT64_CONSTANT (4194304ULL) // 4 MiB
|
||||
+#define BD_LVM_MIN_PE_SIZE G_GUINT64_CONSTANT (1024ULL) // 1 KiB
|
||||
+#define BD_LVM_MAX_PE_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB
|
||||
+#define BD_LVM_MIN_THPOOL_MD_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB
|
||||
+#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB
|
||||
+#define BD_LVM_MIN_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB
|
||||
+#define BD_LVM_MAX_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (1073741824ULL) // 1 GiB
|
||||
+#define BD_LVM_DEFAULT_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB
|
||||
|
||||
/* according to lvmcache (7) */
|
||||
-#define BD_LVM_MIN_CACHE_MD_SIZE (8 MiB)
|
||||
+#define BD_LVM_MIN_CACHE_MD_SIZE (8388608ULL) // 8 MiB
|
||||
|
||||
GQuark bd_lvm_error_quark (void) {
|
||||
return g_quark_from_static_string ("g-bd-lvm-error-quark");
|
||||
diff --git a/src/lib/plugin_apis/mdraid.api b/src/lib/plugin_apis/mdraid.api
|
||||
index 3bd9eaf2..02ca9530 100644
|
||||
--- a/src/lib/plugin_apis/mdraid.api
|
||||
+++ b/src/lib/plugin_apis/mdraid.api
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
/* taken from blivet */
|
||||
// these defaults were determined empirically
|
||||
-#define BD_MD_SUPERBLOCK_SIZE (2 MiB)
|
||||
-#define BD_MD_CHUNK_SIZE (512 KiB)
|
||||
+#define BD_MD_SUPERBLOCK_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB
|
||||
+#define BD_MD_CHUNK_SIZE G_GUINT64_CONSTANT (524288ULL) // 512 KiB
|
||||
|
||||
GQuark bd_md_error_quark (void) {
|
||||
return g_quark_from_static_string ("g-bd-md-error-quark");
|
||||
|
||||
From aeedce3bcaa8182c9878cc51d3f85a6c6eb6a01f Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Thu, 3 Dec 2020 14:41:25 +0100
|
||||
Subject: [PATCH 2/5] lvm: Set thin metadata limits to match limits LVM uses in
|
||||
lvcreate
|
||||
|
||||
---
|
||||
src/lib/plugin_apis/lvm.api | 4 ++--
|
||||
src/plugins/lvm.h | 9 +++++++--
|
||||
tests/lvm_dbus_tests.py | 7 ++++---
|
||||
tests/lvm_test.py | 7 ++++---
|
||||
4 files changed, 17 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api
|
||||
index ea52263b..e843c916 100644
|
||||
--- a/src/lib/plugin_apis/lvm.api
|
||||
+++ b/src/lib/plugin_apis/lvm.api
|
||||
@@ -19,8 +19,8 @@
|
||||
#define BD_LVM_DEFAULT_PE_SIZE G_GUINT64_CONSTANT (4194304ULL) // 4 MiB
|
||||
#define BD_LVM_MIN_PE_SIZE G_GUINT64_CONSTANT (1024ULL) // 1 KiB
|
||||
#define BD_LVM_MAX_PE_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB
|
||||
-#define BD_LVM_MIN_THPOOL_MD_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB
|
||||
-#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB
|
||||
+#define BD_LVM_MIN_THPOOL_MD_SIZE G_GUINT64_CONSTANT (4194304ULL) // 4 MiB
|
||||
+#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (33957085184ULL) // 31.62 GiB
|
||||
#define BD_LVM_MIN_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB
|
||||
#define BD_LVM_MAX_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (1073741824ULL) // 1 GiB
|
||||
#define BD_LVM_DEFAULT_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB
|
||||
diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h
|
||||
index 4b970f2e..01c06ca4 100644
|
||||
--- a/src/plugins/lvm.h
|
||||
+++ b/src/plugins/lvm.h
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <glib.h>
|
||||
#include <blockdev/utils.h>
|
||||
+#include <libdevmapper.h>
|
||||
|
||||
#ifndef BD_LVM
|
||||
#define BD_LVM
|
||||
@@ -21,8 +22,12 @@
|
||||
#define USE_DEFAULT_PE_SIZE 0
|
||||
#define RESOLVE_PE_SIZE(size) ((size) == USE_DEFAULT_PE_SIZE ? BD_LVM_DEFAULT_PE_SIZE : (size))
|
||||
|
||||
-#define BD_LVM_MIN_THPOOL_MD_SIZE (2 MiB)
|
||||
-#define BD_LVM_MAX_THPOOL_MD_SIZE (16 GiB)
|
||||
+/* lvm constants for thin pool metadata size are actually half of these
|
||||
+ but when they calculate the actual metadata size they double the limits
|
||||
+ so lets just double the limits here too */
|
||||
+#define BD_LVM_MIN_THPOOL_MD_SIZE (4 MiB)
|
||||
+#define BD_LVM_MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE KiB)
|
||||
+
|
||||
#define BD_LVM_MIN_THPOOL_CHUNK_SIZE (64 KiB)
|
||||
#define BD_LVM_MAX_THPOOL_CHUNK_SIZE (1 GiB)
|
||||
#define BD_LVM_DEFAULT_CHUNK_SIZE (64 KiB)
|
||||
diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py
|
||||
index 47402fc3..b517aae9 100644
|
||||
--- a/tests/lvm_dbus_tests.py
|
||||
+++ b/tests/lvm_dbus_tests.py
|
||||
@@ -160,12 +160,13 @@ def test_get_thpool_meta_size(self):
|
||||
def test_is_valid_thpool_md_size(self):
|
||||
"""Verify that is_valid_thpool_md_size works as expected"""
|
||||
|
||||
- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(2 * 1024**2))
|
||||
- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2))
|
||||
+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(4 * 1024**2))
|
||||
+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(5 * 1024**2))
|
||||
self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3))
|
||||
|
||||
self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2))
|
||||
- self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(17 * 1024**3))
|
||||
+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2))
|
||||
+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(32 * 1024**3))
|
||||
|
||||
@tag_test(TestTags.NOSTORAGE)
|
||||
def test_is_valid_thpool_chunk_size(self):
|
||||
diff --git a/tests/lvm_test.py b/tests/lvm_test.py
|
||||
index 149cf54a..d0085651 100644
|
||||
--- a/tests/lvm_test.py
|
||||
+++ b/tests/lvm_test.py
|
||||
@@ -153,12 +153,13 @@ def test_get_thpool_meta_size(self):
|
||||
def test_is_valid_thpool_md_size(self):
|
||||
"""Verify that is_valid_thpool_md_size works as expected"""
|
||||
|
||||
- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(2 * 1024**2))
|
||||
- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2))
|
||||
+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(4 * 1024**2))
|
||||
+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(5 * 1024**2))
|
||||
self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3))
|
||||
|
||||
self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2))
|
||||
- self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(17 * 1024**3))
|
||||
+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2))
|
||||
+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(32 * 1024**3))
|
||||
|
||||
@tag_test(TestTags.NOSTORAGE)
|
||||
def test_is_valid_thpool_chunk_size(self):
|
||||
|
||||
From 15fcf1bb62865083a3483fc51f45e11cdc2d7386 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Thu, 3 Dec 2020 14:46:00 +0100
|
||||
Subject: [PATCH 3/5] lvm: Do not use thin_metadata_size to recommend thin
|
||||
metadata size
|
||||
|
||||
thin_metadata_size calculates the metadata size differently and
|
||||
recommends smaller metadata than lvcreate so we should use the
|
||||
lvcreate formula instead.
|
||||
|
||||
Resolves: rhbz#1898668
|
||||
---
|
||||
dist/libblockdev.spec.in | 4 --
|
||||
src/lib/plugin_apis/lvm.api | 8 +--
|
||||
src/plugins/lvm-dbus.c | 78 ++++++-----------------------
|
||||
src/plugins/lvm.c | 66 +++++++-----------------
|
||||
src/python/gi/overrides/BlockDev.py | 6 +++
|
||||
tests/library_test.py | 6 +--
|
||||
tests/lvm_dbus_tests.py | 20 ++++----
|
||||
tests/lvm_test.py | 15 ++----
|
||||
tests/utils.py | 2 +-
|
||||
9 files changed, 61 insertions(+), 144 deletions(-)
|
||||
|
||||
diff --git a/dist/libblockdev.spec.in b/dist/libblockdev.spec.in
|
||||
index 7c775174..3e0a53c6 100644
|
||||
--- a/dist/libblockdev.spec.in
|
||||
+++ b/dist/libblockdev.spec.in
|
||||
@@ -387,8 +387,6 @@ BuildRequires: device-mapper-devel
|
||||
Summary: The LVM plugin for the libblockdev library
|
||||
Requires: %{name}-utils%{?_isa} >= 0.11
|
||||
Requires: lvm2
|
||||
-# for thin_metadata_size
|
||||
-Requires: device-mapper-persistent-data
|
||||
|
||||
%description lvm
|
||||
The libblockdev library plugin (and in the same time a standalone library)
|
||||
@@ -411,8 +409,6 @@ BuildRequires: device-mapper-devel
|
||||
Summary: The LVM plugin for the libblockdev library
|
||||
Requires: %{name}-utils%{?_isa} >= 1.4
|
||||
Requires: lvm2-dbusd >= 2.02.156
|
||||
-# for thin_metadata_size
|
||||
-Requires: device-mapper-persistent-data
|
||||
|
||||
%description lvm-dbus
|
||||
The libblockdev library plugin (and in the same time a standalone library)
|
||||
diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api
|
||||
index e843c916..9f25c1ed 100644
|
||||
--- a/src/lib/plugin_apis/lvm.api
|
||||
+++ b/src/lib/plugin_apis/lvm.api
|
||||
@@ -704,11 +704,13 @@ guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean inclu
|
||||
* bd_lvm_get_thpool_meta_size:
|
||||
* @size: size of the thin pool
|
||||
* @chunk_size: chunk size of the thin pool or 0 to use the default (%BD_LVM_DEFAULT_CHUNK_SIZE)
|
||||
- * @n_snapshots: number of snapshots that will be created in the pool
|
||||
+ * @n_snapshots: ignored
|
||||
* @error: (out): place to store error (if any)
|
||||
*
|
||||
- * Returns: recommended size of the metadata space for the specified pool or 0
|
||||
- * in case of error
|
||||
+ * Note: This function will be changed in 3.0: the @n_snapshots parameter
|
||||
+ * is currently not used and will be removed.
|
||||
+ *
|
||||
+ * Returns: recommended size of the metadata space for the specified pool
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
|
||||
*/
|
||||
diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c
|
||||
index 9f821a99..24d54426 100644
|
||||
--- a/src/plugins/lvm-dbus.c
|
||||
+++ b/src/plugins/lvm-dbus.c
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <glib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
-#include <libdevmapper.h>
|
||||
#include <unistd.h>
|
||||
#include <blockdev/utils.h>
|
||||
#include <gio/gio.h>
|
||||
@@ -248,14 +247,6 @@ static volatile guint avail_features = 0;
|
||||
static volatile guint avail_module_deps = 0;
|
||||
static GMutex deps_check_lock;
|
||||
|
||||
-#define DEPS_THMS 0
|
||||
-#define DEPS_THMS_MASK (1 << DEPS_THMS)
|
||||
-#define DEPS_LAST 1
|
||||
-
|
||||
-static const UtilDep deps[DEPS_LAST] = {
|
||||
- {"thin_metadata_size", NULL, NULL, NULL},
|
||||
-};
|
||||
-
|
||||
#define DBUS_DEPS_LVMDBUSD 0
|
||||
#define DBUS_DEPS_LVMDBUSD_MASK (1 << DBUS_DEPS_LVMDBUSD)
|
||||
#define DBUS_DEPS_LAST 1
|
||||
@@ -301,17 +292,6 @@ gboolean bd_lvm_check_deps (void) {
|
||||
check_ret = check_ret && success;
|
||||
}
|
||||
|
||||
- for (i=0; i < DEPS_LAST; i++) {
|
||||
- success = bd_utils_check_util_version (deps[i].name, deps[i].version,
|
||||
- deps[i].ver_arg, deps[i].ver_regexp, &error);
|
||||
- if (!success)
|
||||
- g_warning ("%s", error->message);
|
||||
- else
|
||||
- g_atomic_int_or (&avail_deps, 1 << i);
|
||||
- g_clear_error (&error);
|
||||
- check_ret = check_ret && success;
|
||||
- }
|
||||
-
|
||||
if (!check_ret)
|
||||
g_warning("Cannot load the LVM plugin");
|
||||
|
||||
@@ -386,10 +366,7 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) {
|
||||
g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_TECH_UNAVAIL,
|
||||
"Only 'query' supported for thin calculations");
|
||||
return FALSE;
|
||||
- } else if ((mode & BD_LVM_TECH_MODE_QUERY) &&
|
||||
- !check_deps (&avail_deps, DEPS_THMS_MASK, deps, DEPS_LAST, &deps_check_lock, error))
|
||||
- return FALSE;
|
||||
- else
|
||||
+ } else
|
||||
return TRUE;
|
||||
case BD_LVM_TECH_CALCS:
|
||||
if (mode & ~BD_LVM_TECH_MODE_QUERY) {
|
||||
@@ -1303,53 +1280,28 @@ guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean inclu
|
||||
* bd_lvm_get_thpool_meta_size:
|
||||
* @size: size of the thin pool
|
||||
* @chunk_size: chunk size of the thin pool or 0 to use the default (%BD_LVM_DEFAULT_CHUNK_SIZE)
|
||||
- * @n_snapshots: number of snapshots that will be created in the pool
|
||||
+ * @n_snapshots: ignored
|
||||
* @error: (out): place to store error (if any)
|
||||
*
|
||||
- * Returns: recommended size of the metadata space for the specified pool or 0
|
||||
- * in case of error
|
||||
+ * Note: This function will be changed in 3.0: the @n_snapshots parameter
|
||||
+ * is currently not used and will be removed.
|
||||
+ *
|
||||
+ * Returns: recommended size of the metadata space for the specified pool
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots, GError **error) {
|
||||
- /* ub - output in bytes, n - output just the number */
|
||||
- const gchar* args[7] = {"thin_metadata_size", "-ub", "-n", NULL, NULL, NULL, NULL};
|
||||
- gchar *output = NULL;
|
||||
- gboolean success = FALSE;
|
||||
- guint64 ret = 0;
|
||||
-
|
||||
- if (!check_deps (&avail_deps, DEPS_THMS_MASK, deps, DEPS_LAST, &deps_check_lock, error))
|
||||
- return 0;
|
||||
+guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots UNUSED, GError **error UNUSED) {
|
||||
+ guint64 md_size = 0;
|
||||
|
||||
- /* s - total size, b - chunk size, m - number of snapshots */
|
||||
- args[3] = g_strdup_printf ("-s%"G_GUINT64_FORMAT, size);
|
||||
- args[4] = g_strdup_printf ("-b%"G_GUINT64_FORMAT,
|
||||
- chunk_size != 0 ? chunk_size : (guint64) BD_LVM_DEFAULT_CHUNK_SIZE);
|
||||
- args[5] = g_strdup_printf ("-m%"G_GUINT64_FORMAT, n_snapshots);
|
||||
-
|
||||
- success = bd_utils_exec_and_capture_output (args, NULL, &output, error);
|
||||
- g_free ((gchar*) args[3]);
|
||||
- g_free ((gchar*) args[4]);
|
||||
- g_free ((gchar*) args[5]);
|
||||
-
|
||||
- if (!success) {
|
||||
- /* error is already set */
|
||||
- g_free (output);
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- ret = g_ascii_strtoull (output, NULL, 0);
|
||||
- if (ret == 0) {
|
||||
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_PARSE,
|
||||
- "Failed to parse number from thin_metadata_size's output: '%s'",
|
||||
- output);
|
||||
- g_free (output);
|
||||
- return 0;
|
||||
- }
|
||||
+ /* based on lvcreate metadata size calculation */
|
||||
+ md_size = UINT64_C(64) * size / (chunk_size ? chunk_size : BD_LVM_DEFAULT_CHUNK_SIZE);
|
||||
|
||||
- g_free (output);
|
||||
+ if (md_size > BD_LVM_MAX_THPOOL_MD_SIZE)
|
||||
+ md_size = BD_LVM_MAX_THPOOL_MD_SIZE;
|
||||
+ else if (md_size < BD_LVM_MIN_THPOOL_MD_SIZE)
|
||||
+ md_size = BD_LVM_MIN_THPOOL_MD_SIZE;
|
||||
|
||||
- return MAX (ret, BD_LVM_MIN_THPOOL_MD_SIZE);
|
||||
+ return md_size;
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c
|
||||
index 6bfaa338..74493feb 100644
|
||||
--- a/src/plugins/lvm.c
|
||||
+++ b/src/plugins/lvm.c
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <glib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
-#include <libdevmapper.h>
|
||||
#include <unistd.h>
|
||||
#include <blockdev/utils.h>
|
||||
|
||||
@@ -213,13 +212,10 @@ static GMutex deps_check_lock;
|
||||
|
||||
#define DEPS_LVM 0
|
||||
#define DEPS_LVM_MASK (1 << DEPS_LVM)
|
||||
-#define DEPS_THMS 1
|
||||
-#define DEPS_THMS_MASK (1 << DEPS_THMS)
|
||||
-#define DEPS_LAST 2
|
||||
+#define DEPS_LAST 1
|
||||
|
||||
static const UtilDep deps[DEPS_LAST] = {
|
||||
{"lvm", LVM_MIN_VERSION, "version", "LVM version:\\s+([\\d\\.]+)"},
|
||||
- {"thin_metadata_size", NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
#define FEATURES_VDO 0
|
||||
@@ -236,6 +232,8 @@ static const UtilFeatureDep features[FEATURES_LAST] = {
|
||||
|
||||
static const gchar*const module_deps[MODULE_DEPS_LAST] = { "kvdo" };
|
||||
|
||||
+#define UNUSED __attribute__((unused))
|
||||
+
|
||||
/**
|
||||
* bd_lvm_check_deps:
|
||||
*
|
||||
@@ -317,10 +315,7 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) {
|
||||
g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_TECH_UNAVAIL,
|
||||
"Only 'query' supported for thin calculations");
|
||||
return FALSE;
|
||||
- } else if ((mode & BD_LVM_TECH_MODE_QUERY) &&
|
||||
- !check_deps (&avail_deps, DEPS_THMS_MASK, deps, DEPS_LAST, &deps_check_lock, error))
|
||||
- return FALSE;
|
||||
- else
|
||||
+ } else
|
||||
return TRUE;
|
||||
case BD_LVM_TECH_CALCS:
|
||||
if (mode & ~BD_LVM_TECH_MODE_QUERY) {
|
||||
@@ -820,53 +815,28 @@ guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean inclu
|
||||
* bd_lvm_get_thpool_meta_size:
|
||||
* @size: size of the thin pool
|
||||
* @chunk_size: chunk size of the thin pool or 0 to use the default (%BD_LVM_DEFAULT_CHUNK_SIZE)
|
||||
- * @n_snapshots: number of snapshots that will be created in the pool
|
||||
+ * @n_snapshots: ignored
|
||||
* @error: (out): place to store error (if any)
|
||||
*
|
||||
- * Returns: recommended size of the metadata space for the specified pool or 0
|
||||
- * in case of error
|
||||
+ * Note: This function will be changed in 3.0: the @n_snapshots parameter
|
||||
+ * is currently not used and will be removed.
|
||||
+ *
|
||||
+ * Returns: recommended size of the metadata space for the specified pool
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots, GError **error) {
|
||||
- /* ub - output in bytes, n - output just the number */
|
||||
- const gchar* args[7] = {"thin_metadata_size", "-ub", "-n", NULL, NULL, NULL, NULL};
|
||||
- gchar *output = NULL;
|
||||
- gboolean success = FALSE;
|
||||
- guint64 ret = 0;
|
||||
-
|
||||
- if (!check_deps (&avail_deps, DEPS_THMS_MASK, deps, DEPS_LAST, &deps_check_lock, error))
|
||||
- return 0;
|
||||
+guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots UNUSED, GError **error UNUSED) {
|
||||
+ guint64 md_size = 0;
|
||||
|
||||
- /* s - total size, b - chunk size, m - number of snapshots */
|
||||
- args[3] = g_strdup_printf ("-s%"G_GUINT64_FORMAT, size);
|
||||
- args[4] = g_strdup_printf ("-b%"G_GUINT64_FORMAT,
|
||||
- chunk_size != 0 ? chunk_size : (guint64) BD_LVM_DEFAULT_CHUNK_SIZE);
|
||||
- args[5] = g_strdup_printf ("-m%"G_GUINT64_FORMAT, n_snapshots);
|
||||
+ /* based on lvcreate metadata size calculation */
|
||||
+ md_size = UINT64_C(64) * size / (chunk_size ? chunk_size : BD_LVM_DEFAULT_CHUNK_SIZE);
|
||||
|
||||
- success = bd_utils_exec_and_capture_output (args, NULL, &output, error);
|
||||
- g_free ((gchar*) args[3]);
|
||||
- g_free ((gchar*) args[4]);
|
||||
- g_free ((gchar*) args[5]);
|
||||
-
|
||||
- if (!success) {
|
||||
- /* error is already set */
|
||||
- g_free (output);
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- ret = g_ascii_strtoull (output, NULL, 0);
|
||||
- if (ret == 0) {
|
||||
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_PARSE,
|
||||
- "Failed to parse number from thin_metadata_size's output: '%s'",
|
||||
- output);
|
||||
- g_free (output);
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- g_free (output);
|
||||
+ if (md_size > BD_LVM_MAX_THPOOL_MD_SIZE)
|
||||
+ md_size = BD_LVM_MAX_THPOOL_MD_SIZE;
|
||||
+ else if (md_size < BD_LVM_MIN_THPOOL_MD_SIZE)
|
||||
+ md_size = BD_LVM_MIN_THPOOL_MD_SIZE;
|
||||
|
||||
- return MAX (ret, BD_LVM_MIN_THPOOL_MD_SIZE);
|
||||
+ return md_size;
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py
|
||||
index d78bfaab..f768c8bd 100644
|
||||
--- a/src/python/gi/overrides/BlockDev.py
|
||||
+++ b/src/python/gi/overrides/BlockDev.py
|
||||
@@ -462,6 +462,12 @@ def lvm_get_thpool_padding(size, pe_size=0, included=False):
|
||||
return _lvm_get_thpool_padding(size, pe_size, included)
|
||||
__all__.append("lvm_get_thpool_padding")
|
||||
|
||||
+_lvm_get_thpool_meta_size = BlockDev.lvm_get_thpool_meta_size
|
||||
+@override(BlockDev.lvm_get_thpool_meta_size)
|
||||
+def lvm_get_thpool_meta_size(size, chunk_size=0, n_snapshots=0):
|
||||
+ return _lvm_get_thpool_meta_size(size, chunk_size, n_snapshots)
|
||||
+__all__.append("lvm_get_thpool_meta_size")
|
||||
+
|
||||
_lvm_pvcreate = BlockDev.lvm_pvcreate
|
||||
@override(BlockDev.lvm_pvcreate)
|
||||
def lvm_pvcreate(device, data_alignment=0, metadata_size=0, extra=None, **kwargs):
|
||||
diff --git a/tests/library_test.py b/tests/library_test.py
|
||||
index e8bb175a..08e44fdc 100644
|
||||
--- a/tests/library_test.py
|
||||
+++ b/tests/library_test.py
|
||||
@@ -349,8 +349,7 @@ def test_try_reinit(self):
|
||||
|
||||
# try reinitializing with only some utilities being available and thus
|
||||
# only some plugins able to load
|
||||
- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm",
|
||||
- "thin_metadata_size", "swaplabel"]):
|
||||
+ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", "swaplabel"]):
|
||||
succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None)
|
||||
self.assertFalse(succ)
|
||||
for plug_name in ("swap", "lvm", "crypto"):
|
||||
@@ -361,8 +360,7 @@ def test_try_reinit(self):
|
||||
|
||||
# now the same with a subset of plugins requested
|
||||
plugins = BlockDev.plugin_specs_from_names(["lvm", "swap", "crypto"])
|
||||
- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm",
|
||||
- "thin_metadata_size", "swaplabel"]):
|
||||
+ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm","swaplabel"]):
|
||||
succ, loaded = BlockDev.try_reinit(plugins, True, None)
|
||||
self.assertTrue(succ)
|
||||
self.assertEqual(set(loaded), set(["swap", "lvm", "crypto"]))
|
||||
diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py
|
||||
index b517aae9..c06a480c 100644
|
||||
--- a/tests/lvm_dbus_tests.py
|
||||
+++ b/tests/lvm_dbus_tests.py
|
||||
@@ -141,21 +141,19 @@ def test_get_thpool_padding(self):
|
||||
def test_get_thpool_meta_size(self):
|
||||
"""Verify that getting recommended thin pool metadata size works as expected"""
|
||||
|
||||
- # no idea how thin_metadata_size works, but let's at least check that
|
||||
- # the function works and returns what thin_metadata_size says
|
||||
- out1 = subprocess.check_output(["thin_metadata_size", "-ub", "-n", "-b64k", "-s1t", "-m100"])
|
||||
- self.assertEqual(int(out1), BlockDev.lvm_get_thpool_meta_size (1 * 1024**4, 64 * 1024, 100))
|
||||
+ # metadata size is calculated as 64 * pool_size / chunk_size
|
||||
+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(1 * 1024**4, 64 * 1024), 1 * 1024**3)
|
||||
|
||||
- out2 = subprocess.check_output(["thin_metadata_size", "-ub", "-n", "-b128k", "-s1t", "-m100"])
|
||||
- self.assertEqual(int(out2), BlockDev.lvm_get_thpool_meta_size (1 * 1024**4, 128 * 1024, 100))
|
||||
+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(1 * 1024**4, 128 * 1024), 512 * 1024**2)
|
||||
|
||||
- # twice the chunk_size -> roughly half the metadata needed
|
||||
- self.assertAlmostEqual(float(out1) / float(out2), 2, places=2)
|
||||
-
|
||||
- # unless thin_metadata_size gives a value that is not valid (too small)
|
||||
- self.assertEqual(BlockDev.lvm_get_thpool_meta_size (100 * 1024**2, 128 * 1024, 100),
|
||||
+ # lower limit is 4 MiB
|
||||
+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(100 * 1024**2, 128 * 1024),
|
||||
BlockDev.LVM_MIN_THPOOL_MD_SIZE)
|
||||
|
||||
+ # upper limit is 31.62 GiB
|
||||
+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(100 * 1024**4, 64 * 1024),
|
||||
+ BlockDev.LVM_MAX_THPOOL_MD_SIZE)
|
||||
+
|
||||
@tag_test(TestTags.NOSTORAGE)
|
||||
def test_is_valid_thpool_md_size(self):
|
||||
"""Verify that is_valid_thpool_md_size works as expected"""
|
||||
diff --git a/tests/lvm_test.py b/tests/lvm_test.py
|
||||
index d0085651..b84adece 100644
|
||||
--- a/tests/lvm_test.py
|
||||
+++ b/tests/lvm_test.py
|
||||
@@ -134,19 +134,14 @@ def test_get_thpool_padding(self):
|
||||
def test_get_thpool_meta_size(self):
|
||||
"""Verify that getting recommended thin pool metadata size works as expected"""
|
||||
|
||||
- # no idea how thin_metadata_size works, but let's at least check that
|
||||
- # the function works and returns what thin_metadata_size says
|
||||
- out1 = subprocess.check_output(["thin_metadata_size", "-ub", "-n", "-b64k", "-s1t", "-m100"])
|
||||
- self.assertEqual(int(out1), BlockDev.lvm_get_thpool_meta_size (1 * 1024**4, 64 * 1024, 100))
|
||||
|
||||
- out2 = subprocess.check_output(["thin_metadata_size", "-ub", "-n", "-b128k", "-s1t", "-m100"])
|
||||
- self.assertEqual(int(out2), BlockDev.lvm_get_thpool_meta_size (1 * 1024**4, 128 * 1024, 100))
|
||||
+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(1 * 1024**4, 64 * 1024),
|
||||
+ 1 * 1024**3)
|
||||
|
||||
- # twice the chunk_size -> roughly half the metadata needed
|
||||
- self.assertAlmostEqual(float(out1) / float(out2), 2, places=2)
|
||||
+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(1 * 1024**4, 128 * 1024),
|
||||
+ 512 * 1024**2)
|
||||
|
||||
- # unless thin_metadata_size gives a value that is not valid (too small)
|
||||
- self.assertEqual(BlockDev.lvm_get_thpool_meta_size (100 * 1024**2, 128 * 1024, 100),
|
||||
+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(100 * 1024**2, 128 * 1024),
|
||||
BlockDev.LVM_MIN_THPOOL_MD_SIZE)
|
||||
|
||||
@tag_test(TestTags.NOSTORAGE)
|
||||
diff --git a/tests/utils.py b/tests/utils.py
|
||||
index 182eda6a..584fde5c 100644
|
||||
--- a/tests/utils.py
|
||||
+++ b/tests/utils.py
|
||||
@@ -70,7 +70,7 @@ def fake_utils(path="."):
|
||||
finally:
|
||||
os.environ["PATH"] = old_path
|
||||
|
||||
-ALL_UTILS = {"lvm", "thin_metadata_size", "btrfs", "mkswap", "swaplabel", "multipath", "mpathconf", "dmsetup", "mdadm", "make-bcache", "sgdisk", "sfdisk"}
|
||||
+ALL_UTILS = {"lvm", "btrfs", "mkswap", "swaplabel", "multipath", "mpathconf", "dmsetup", "mdadm", "make-bcache", "sgdisk", "sfdisk"}
|
||||
|
||||
@contextmanager
|
||||
def fake_path(path=None, keep_utils=None, all_but=None):
|
||||
|
||||
From 27961a3fcb205ea51f40668d68765dd8d388777b Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Thu, 3 Dec 2020 14:48:08 +0100
|
||||
Subject: [PATCH 4/5] lvm: Use the UNUSED macro instead of
|
||||
__attribute__((unused))
|
||||
|
||||
for unused attributes. It makes the function definition a little
|
||||
bit more readable.
|
||||
---
|
||||
src/plugins/lvm-dbus.c | 24 ++++++++++++------------
|
||||
src/plugins/lvm.c | 20 ++++++++++----------
|
||||
2 files changed, 22 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c
|
||||
index 24d54426..b7b4480e 100644
|
||||
--- a/src/plugins/lvm-dbus.c
|
||||
+++ b/src/plugins/lvm-dbus.c
|
||||
@@ -959,7 +959,7 @@ static BDLVMPVdata* get_pv_data_from_props (GVariant *props, GError **error) {
|
||||
return data;
|
||||
}
|
||||
|
||||
-static BDLVMVGdata* get_vg_data_from_props (GVariant *props, GError **error __attribute__((unused))) {
|
||||
+static BDLVMVGdata* get_vg_data_from_props (GVariant *props, GError **error UNUSED) {
|
||||
BDLVMVGdata *data = g_new0 (BDLVMVGdata, 1);
|
||||
GVariantDict dict;
|
||||
|
||||
@@ -1061,7 +1061,7 @@ static BDLVMLVdata* get_lv_data_from_props (GVariant *props, GError **error) {
|
||||
return data;
|
||||
}
|
||||
|
||||
-static BDLVMVDOPooldata* get_vdo_data_from_props (GVariant *props, GError **error __attribute__((unused))) {
|
||||
+static BDLVMVDOPooldata* get_vdo_data_from_props (GVariant *props, GError **error UNUSED) {
|
||||
BDLVMVDOPooldata *data = g_new0 (BDLVMVDOPooldata, 1);
|
||||
GVariantDict dict;
|
||||
gchar *value = NULL;
|
||||
@@ -1165,7 +1165,7 @@ static GVariant* create_size_str_param (guint64 size, const gchar *unit) {
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error __attribute__((unused))) {
|
||||
+gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error UNUSED) {
|
||||
return (((size % 2) == 0) && (size >= (BD_LVM_MIN_PE_SIZE)) && (size <= (BD_LVM_MAX_PE_SIZE)));
|
||||
}
|
||||
|
||||
@@ -1177,7 +1177,7 @@ gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error __attribute__
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 *bd_lvm_get_supported_pe_sizes (GError **error __attribute__((unused))) {
|
||||
+guint64 *bd_lvm_get_supported_pe_sizes (GError **error UNUSED) {
|
||||
guint8 i;
|
||||
guint64 val = BD_LVM_MIN_PE_SIZE;
|
||||
guint8 num_items = ((guint8) round (log2 ((double) BD_LVM_MAX_PE_SIZE))) - ((guint8) round (log2 ((double) BD_LVM_MIN_PE_SIZE))) + 2;
|
||||
@@ -1199,7 +1199,7 @@ guint64 *bd_lvm_get_supported_pe_sizes (GError **error __attribute__((unused)))
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 bd_lvm_get_max_lv_size (GError **error __attribute__((unused))) {
|
||||
+guint64 bd_lvm_get_max_lv_size (GError **error UNUSED) {
|
||||
return BD_LVM_MAX_LV_SIZE;
|
||||
}
|
||||
|
||||
@@ -1219,7 +1219,7 @@ guint64 bd_lvm_get_max_lv_size (GError **error __attribute__((unused))) {
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error __attribute__((unused))) {
|
||||
+guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error UNUSED) {
|
||||
pe_size = RESOLVE_PE_SIZE(pe_size);
|
||||
guint64 delta = size % pe_size;
|
||||
if (delta == 0)
|
||||
@@ -1313,7 +1313,7 @@ guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error __attribute__((unused))) {
|
||||
+gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error UNUSED) {
|
||||
return ((BD_LVM_MIN_THPOOL_MD_SIZE <= size) && (size <= BD_LVM_MAX_THPOOL_MD_SIZE));
|
||||
}
|
||||
|
||||
@@ -1327,7 +1327,7 @@ gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error __attribut
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error __attribute__((unused))) {
|
||||
+gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error UNUSED) {
|
||||
gdouble size_log2 = 0.0;
|
||||
|
||||
if ((size < BD_LVM_MIN_THPOOL_CHUNK_SIZE) || (size > BD_LVM_MAX_THPOOL_CHUNK_SIZE))
|
||||
@@ -2616,7 +2616,7 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
|
||||
*/
|
||||
-gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error __attribute__((unused))) {
|
||||
+gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error UNUSED) {
|
||||
/* XXX: the error attribute will likely be used in the future when
|
||||
some validation comes into the game */
|
||||
|
||||
@@ -2641,7 +2641,7 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error __att
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
|
||||
*/
|
||||
-gchar* bd_lvm_get_global_config (GError **error __attribute__((unused))) {
|
||||
+gchar* bd_lvm_get_global_config (GError **error UNUSED) {
|
||||
gchar *ret = NULL;
|
||||
|
||||
g_mutex_lock (&global_config_lock);
|
||||
@@ -2660,7 +2660,7 @@ gchar* bd_lvm_get_global_config (GError **error __attribute__((unused))) {
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CACHE_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error __attribute__((unused))) {
|
||||
+guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error UNUSED) {
|
||||
return MAX ((guint64) cache_size / 1000, BD_LVM_MIN_CACHE_MD_SIZE);
|
||||
}
|
||||
|
||||
@@ -2670,7 +2670,7 @@ guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error __a
|
||||
*
|
||||
* Get LV type string from flags.
|
||||
*/
|
||||
-static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error __attribute__((unused))) {
|
||||
+static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error UNUSED) {
|
||||
if (!meta) {
|
||||
if (flags & BD_LVM_CACHE_POOL_STRIPED)
|
||||
return "striped";
|
||||
diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c
|
||||
index 74493feb..2be1dbdb 100644
|
||||
--- a/src/plugins/lvm.c
|
||||
+++ b/src/plugins/lvm.c
|
||||
@@ -700,7 +700,7 @@ static BDLVMVDOPooldata* get_vdo_data_from_table (GHashTable *table, gboolean fr
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error __attribute__((unused))) {
|
||||
+gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error UNUSED) {
|
||||
return (((size % 2) == 0) && (size >= (BD_LVM_MIN_PE_SIZE)) && (size <= (BD_LVM_MAX_PE_SIZE)));
|
||||
}
|
||||
|
||||
@@ -712,7 +712,7 @@ gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error __attribute__
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 *bd_lvm_get_supported_pe_sizes (GError **error __attribute__((unused))) {
|
||||
+guint64 *bd_lvm_get_supported_pe_sizes (GError **error UNUSED) {
|
||||
guint8 i;
|
||||
guint64 val = BD_LVM_MIN_PE_SIZE;
|
||||
guint8 num_items = ((guint8) round (log2 ((double) BD_LVM_MAX_PE_SIZE))) - ((guint8) round (log2 ((double) BD_LVM_MIN_PE_SIZE))) + 2;
|
||||
@@ -734,7 +734,7 @@ guint64 *bd_lvm_get_supported_pe_sizes (GError **error __attribute__((unused)))
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 bd_lvm_get_max_lv_size (GError **error __attribute__((unused))) {
|
||||
+guint64 bd_lvm_get_max_lv_size (GError **error UNUSED) {
|
||||
return BD_LVM_MAX_LV_SIZE;
|
||||
}
|
||||
|
||||
@@ -754,7 +754,7 @@ guint64 bd_lvm_get_max_lv_size (GError **error __attribute__((unused))) {
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error __attribute__((unused))) {
|
||||
+guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error UNUSED) {
|
||||
pe_size = RESOLVE_PE_SIZE(pe_size);
|
||||
guint64 delta = size % pe_size;
|
||||
if (delta == 0)
|
||||
@@ -848,7 +848,7 @@ guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error __attribute__((unused))) {
|
||||
+gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error UNUSED) {
|
||||
return ((BD_LVM_MIN_THPOOL_MD_SIZE <= size) && (size <= BD_LVM_MAX_THPOOL_MD_SIZE));
|
||||
}
|
||||
|
||||
@@ -862,7 +862,7 @@ gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error __attribut
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error __attribute__((unused))) {
|
||||
+gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error UNUSED) {
|
||||
gdouble size_log2 = 0.0;
|
||||
|
||||
if ((size < BD_LVM_MIN_THPOOL_CHUNK_SIZE) || (size > BD_LVM_MAX_THPOOL_CHUNK_SIZE))
|
||||
@@ -1983,7 +1983,7 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
|
||||
*/
|
||||
-gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error __attribute__((unused))) {
|
||||
+gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error UNUSED) {
|
||||
/* XXX: the error attribute will likely be used in the future when
|
||||
some validation comes into the game */
|
||||
|
||||
@@ -2008,7 +2008,7 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error __att
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
|
||||
*/
|
||||
-gchar* bd_lvm_get_global_config (GError **error __attribute__((unused))) {
|
||||
+gchar* bd_lvm_get_global_config (GError **error UNUSED) {
|
||||
gchar *ret = NULL;
|
||||
|
||||
g_mutex_lock (&global_config_lock);
|
||||
@@ -2027,7 +2027,7 @@ gchar* bd_lvm_get_global_config (GError **error __attribute__((unused))) {
|
||||
*
|
||||
* Tech category: %BD_LVM_TECH_CACHE_CALCS no mode (it is ignored)
|
||||
*/
|
||||
-guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error __attribute__((unused))) {
|
||||
+guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error UNUSED) {
|
||||
return MAX ((guint64) cache_size / 1000, BD_LVM_MIN_CACHE_MD_SIZE);
|
||||
}
|
||||
|
||||
@@ -2037,7 +2037,7 @@ guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error __a
|
||||
*
|
||||
* Get LV type string from flags.
|
||||
*/
|
||||
-static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error __attribute__((unused))) {
|
||||
+static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error UNUSED) {
|
||||
if (!meta) {
|
||||
if (flags & BD_LVM_CACHE_POOL_STRIPED)
|
||||
return "striped";
|
||||
|
||||
From f106e775d3c73e5f97512dd109627e00539b703a Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 15 Dec 2020 14:53:13 +0100
|
||||
Subject: [PATCH 5/5] Fix max size limit for LVM thinpool metadata
|
||||
|
||||
DM_THIN_MAX_METADATA_SIZE is in 512 sectors, not in KiB so the
|
||||
upper limit is 15.81 GiB not 31.62 GiB
|
||||
---
|
||||
src/lib/plugin_apis/lvm.api | 2 +-
|
||||
src/plugins/lvm.h | 10 ++++++----
|
||||
tests/lvm_dbus_tests.py | 3 ++-
|
||||
tests/lvm_test.py | 3 ++-
|
||||
4 files changed, 11 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api
|
||||
index 9f25c1ed..563c1041 100644
|
||||
--- a/src/lib/plugin_apis/lvm.api
|
||||
+++ b/src/lib/plugin_apis/lvm.api
|
||||
@@ -20,7 +20,7 @@
|
||||
#define BD_LVM_MIN_PE_SIZE G_GUINT64_CONSTANT (1024ULL) // 1 KiB
|
||||
#define BD_LVM_MAX_PE_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB
|
||||
#define BD_LVM_MIN_THPOOL_MD_SIZE G_GUINT64_CONSTANT (4194304ULL) // 4 MiB
|
||||
-#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (33957085184ULL) // 31.62 GiB
|
||||
+#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (16978542592ULL) // 15.81 GiB
|
||||
#define BD_LVM_MIN_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB
|
||||
#define BD_LVM_MAX_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (1073741824ULL) // 1 GiB
|
||||
#define BD_LVM_DEFAULT_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB
|
||||
diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h
|
||||
index 01c06ca4..2162d769 100644
|
||||
--- a/src/plugins/lvm.h
|
||||
+++ b/src/plugins/lvm.h
|
||||
@@ -22,11 +22,13 @@
|
||||
#define USE_DEFAULT_PE_SIZE 0
|
||||
#define RESOLVE_PE_SIZE(size) ((size) == USE_DEFAULT_PE_SIZE ? BD_LVM_DEFAULT_PE_SIZE : (size))
|
||||
|
||||
-/* lvm constants for thin pool metadata size are actually half of these
|
||||
- but when they calculate the actual metadata size they double the limits
|
||||
- so lets just double the limits here too */
|
||||
+/* lvm constant for thin pool metadata size is actually half of this
|
||||
+ but when they calculate the actual metadata size they double the limit
|
||||
+ so lets just double the limit here too */
|
||||
#define BD_LVM_MIN_THPOOL_MD_SIZE (4 MiB)
|
||||
-#define BD_LVM_MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE KiB)
|
||||
+
|
||||
+/* DM_THIN_MAX_METADATA_SIZE is in 512 sectors */
|
||||
+#define BD_LVM_MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE * 512)
|
||||
|
||||
#define BD_LVM_MIN_THPOOL_CHUNK_SIZE (64 KiB)
|
||||
#define BD_LVM_MAX_THPOOL_CHUNK_SIZE (1 GiB)
|
||||
diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py
|
||||
index c06a480c..8f2bb95d 100644
|
||||
--- a/tests/lvm_dbus_tests.py
|
||||
+++ b/tests/lvm_dbus_tests.py
|
||||
@@ -160,10 +160,11 @@ def test_is_valid_thpool_md_size(self):
|
||||
|
||||
self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(4 * 1024**2))
|
||||
self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(5 * 1024**2))
|
||||
- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3))
|
||||
+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(15 * 1024**3))
|
||||
|
||||
self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2))
|
||||
self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2))
|
||||
+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3))
|
||||
self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(32 * 1024**3))
|
||||
|
||||
@tag_test(TestTags.NOSTORAGE)
|
||||
diff --git a/tests/lvm_test.py b/tests/lvm_test.py
|
||||
index b84adece..6f80a3ba 100644
|
||||
--- a/tests/lvm_test.py
|
||||
+++ b/tests/lvm_test.py
|
||||
@@ -150,10 +150,11 @@ def test_is_valid_thpool_md_size(self):
|
||||
|
||||
self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(4 * 1024**2))
|
||||
self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(5 * 1024**2))
|
||||
- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3))
|
||||
+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(15 * 1024**3))
|
||||
|
||||
self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2))
|
||||
self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2))
|
||||
+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3))
|
||||
self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(32 * 1024**3))
|
||||
|
||||
@tag_test(TestTags.NOSTORAGE)
|
||||
@ -0,0 +1,32 @@
|
||||
From 9c96e621e9abb0649118d2e1731a09b1fa139579 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Wed, 19 Apr 2023 09:50:38 +0200
|
||||
Subject: [PATCH] part: Fix segfault when adding a partition too big for MSDOS
|
||||
|
||||
Resolves: rhbz#2185564
|
||||
---
|
||||
src/plugins/part.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/src/plugins/part.c b/src/plugins/part.c
|
||||
index 8b2285f5..28e20c28 100644
|
||||
--- a/src/plugins/part.c
|
||||
+++ b/src/plugins/part.c
|
||||
@@ -841,6 +841,14 @@ static gboolean resize_part (PedPartition *part, PedDevice *dev, PedDisk *disk,
|
||||
constr = ped_constraint_any (dev);
|
||||
|
||||
geom = ped_disk_get_max_partition_geometry (disk, part, constr);
|
||||
+ if (!geom) {
|
||||
+ set_parted_error (error, BD_PART_ERROR_FAIL);
|
||||
+ g_prefix_error (error, "Failed to create geometry for partition on device '%s'", dev->path);
|
||||
+ ped_constraint_destroy (constr);
|
||||
+ finish_alignment_constraint (disk, orig_flag_state);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
if (!ped_geometry_set_start (geom, start)) {
|
||||
set_parted_error (error, BD_PART_ERROR_FAIL);
|
||||
g_prefix_error (error, "Failed to set partition start on device '%s'", dev->path);
|
||||
--
|
||||
2.40.1
|
||||
|
||||
@ -0,0 +1,300 @@
|
||||
From ee9c3afec5ef2fe1e9fd50718cd732e267b235ed Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Mon, 24 Apr 2023 11:57:18 +0200
|
||||
Subject: [PATCH] lvm: Add a function to activate LVs in shared mode
|
||||
|
||||
Needed by the new blivet feature to support shared LVM setups.
|
||||
---
|
||||
src/lib/plugin_apis/lvm.api | 16 +++++++++
|
||||
src/plugins/lvm-dbus.c | 51 ++++++++++++++++++++-------
|
||||
src/plugins/lvm.c | 53 ++++++++++++++++++++++-------
|
||||
src/plugins/lvm.h | 1 +
|
||||
src/python/gi/overrides/BlockDev.py | 5 ++-
|
||||
tests/lvm_dbus_tests.py | 18 +++++++---
|
||||
tests/lvm_test.py | 18 +++++++---
|
||||
7 files changed, 124 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api
|
||||
index dc8c1348..bac70a75 100644
|
||||
--- a/src/lib/plugin_apis/lvm.api
|
||||
+++ b/src/lib/plugin_apis/lvm.api
|
||||
@@ -1055,6 +1055,22 @@ gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 si
|
||||
*/
|
||||
gboolean bd_lvm_lvactivate (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, const BDExtraArg **extra, GError **error);
|
||||
|
||||
+/**
|
||||
+ * bd_lvm_lvactivate_shared:
|
||||
+ * @vg_name: name of the VG containing the to-be-activated LV
|
||||
+ * @lv_name: name of the to-be-activated LV
|
||||
+ * @ignore_skip: whether to ignore the skip flag or not
|
||||
+ * @shared: whether to activate the LV in shared mode
|
||||
+ * @extra: (allow-none) (array zero-terminated=1): extra options for the LV activation
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the @vg_name/@lv_name LV was successfully activated or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_lvactivate_shared (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, gboolean shared, const BDExtraArg **extra, GError **error);
|
||||
+
|
||||
/**
|
||||
* bd_lvm_lvdeactivate:
|
||||
* @vg_name: name of the VG containing the to-be-deactivated LV
|
||||
diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c
|
||||
index b7b4480e..d8e997f9 100644
|
||||
--- a/src/plugins/lvm-dbus.c
|
||||
+++ b/src/plugins/lvm-dbus.c
|
||||
@@ -2115,6 +2115,27 @@ gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 si
|
||||
return (*error == NULL);
|
||||
}
|
||||
|
||||
+static gboolean _lvm_lvactivate (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, gboolean shared, const BDExtraArg **extra, GError **error) {
|
||||
+ GVariant *params = NULL;
|
||||
+ GVariantBuilder builder;
|
||||
+ GVariant *extra_params = NULL;
|
||||
+
|
||||
+ if (shared)
|
||||
+ params = g_variant_new ("(t)", (guint64) 1 << 6);
|
||||
+ else
|
||||
+ params = g_variant_new ("(t)", (guint64) 0);
|
||||
+
|
||||
+ if (ignore_skip) {
|
||||
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
|
||||
+ g_variant_builder_add (&builder, "{sv}", "-K", g_variant_new ("s", ""));
|
||||
+ extra_params = g_variant_builder_end (&builder);
|
||||
+ g_variant_builder_clear (&builder);
|
||||
+ }
|
||||
+ call_lv_method_sync (vg_name, lv_name, "Activate", params, extra_params, extra, TRUE, error);
|
||||
+
|
||||
+ return (*error == NULL);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* bd_lvm_lvactivate:
|
||||
* @vg_name: name of the VG containing the to-be-activated LV
|
||||
@@ -2129,19 +2150,25 @@ gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 si
|
||||
* Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
|
||||
*/
|
||||
gboolean bd_lvm_lvactivate (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, const BDExtraArg **extra, GError **error) {
|
||||
- GVariant *params = g_variant_new ("(t)", (guint64) 0);
|
||||
- GVariantBuilder builder;
|
||||
- GVariant *extra_params = NULL;
|
||||
-
|
||||
- if (ignore_skip) {
|
||||
- g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
|
||||
- g_variant_builder_add (&builder, "{sv}", "-K", g_variant_new ("s", ""));
|
||||
- extra_params = g_variant_builder_end (&builder);
|
||||
- g_variant_builder_clear (&builder);
|
||||
- }
|
||||
- call_lv_method_sync (vg_name, lv_name, "Activate", params, extra_params, extra, TRUE, error);
|
||||
+ return _lvm_lvactivate (vg_name, lv_name, ignore_skip, FALSE, extra, error);
|
||||
+}
|
||||
|
||||
- return (*error == NULL);
|
||||
+/**
|
||||
+ * bd_lvm_lvactivate_shared:
|
||||
+ * @vg_name: name of the VG containing the to-be-activated LV
|
||||
+ * @lv_name: name of the to-be-activated LV
|
||||
+ * @ignore_skip: whether to ignore the skip flag or not
|
||||
+ * @shared: whether to activate the LV in shared mode
|
||||
+ * @extra: (allow-none) (array zero-terminated=1): extra options for the LV activation
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the @vg_name/@lv_name LV was successfully activated or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_lvactivate_shared (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, gboolean shared, const BDExtraArg **extra, GError **error) {
|
||||
+ return _lvm_lvactivate (vg_name, lv_name, ignore_skip, shared, extra, error);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c
|
||||
index 50da656c..d7281339 100644
|
||||
--- a/src/plugins/lvm.c
|
||||
+++ b/src/plugins/lvm.c
|
||||
@@ -1594,6 +1594,28 @@ gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 si
|
||||
return success;
|
||||
}
|
||||
|
||||
+static gboolean _lvm_lvactivate (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, gboolean shared, const BDExtraArg **extra, GError **error) {
|
||||
+ const gchar *args[5] = {"lvchange", NULL, NULL, NULL, NULL};
|
||||
+ guint8 next_arg = 2;
|
||||
+ gboolean success = FALSE;
|
||||
+
|
||||
+ if (shared)
|
||||
+ args[1] = "-asy";
|
||||
+ else
|
||||
+ args[1] = "-ay";
|
||||
+
|
||||
+ if (ignore_skip) {
|
||||
+ args[next_arg] = "-K";
|
||||
+ next_arg++;
|
||||
+ }
|
||||
+ args[next_arg] = g_strdup_printf ("%s/%s", vg_name, lv_name);
|
||||
+
|
||||
+ success = call_lvm_and_report_error (args, extra, TRUE, error);
|
||||
+ g_free ((gchar *) args[next_arg]);
|
||||
+
|
||||
+ return success;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* bd_lvm_lvactivate:
|
||||
* @vg_name: name of the VG containing the to-be-activated LV
|
||||
@@ -1608,20 +1630,25 @@ gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 si
|
||||
* Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
|
||||
*/
|
||||
gboolean bd_lvm_lvactivate (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, const BDExtraArg **extra, GError **error) {
|
||||
- const gchar *args[5] = {"lvchange", "-ay", NULL, NULL, NULL};
|
||||
- guint8 next_arg = 2;
|
||||
- gboolean success = FALSE;
|
||||
-
|
||||
- if (ignore_skip) {
|
||||
- args[next_arg] = "-K";
|
||||
- next_arg++;
|
||||
- }
|
||||
- args[next_arg] = g_strdup_printf ("%s/%s", vg_name, lv_name);
|
||||
-
|
||||
- success = call_lvm_and_report_error (args, extra, TRUE, error);
|
||||
- g_free ((gchar *) args[next_arg]);
|
||||
+ return _lvm_lvactivate (vg_name, lv_name, ignore_skip, FALSE, extra, error);
|
||||
+}
|
||||
|
||||
- return success;
|
||||
+/**
|
||||
+ * bd_lvm_lvactivate_shared:
|
||||
+ * @vg_name: name of the VG containing the to-be-activated LV
|
||||
+ * @lv_name: name of the to-be-activated LV
|
||||
+ * @ignore_skip: whether to ignore the skip flag or not
|
||||
+ * @shared: whether to activate the LV in shared mode
|
||||
+ * @extra: (allow-none) (array zero-terminated=1): extra options for the LV activation
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the @vg_name/@lv_name LV was successfully activated or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_lvactivate_shared (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, gboolean shared, const BDExtraArg **extra, GError **error) {
|
||||
+ return _lvm_lvactivate (vg_name, lv_name, ignore_skip, shared, extra, error);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h
|
||||
index 2162d769..244663a4 100644
|
||||
--- a/src/plugins/lvm.h
|
||||
+++ b/src/plugins/lvm.h
|
||||
@@ -275,6 +275,7 @@ gboolean bd_lvm_lvremove (const gchar *vg_name, const gchar *lv_name, gboolean f
|
||||
gboolean bd_lvm_lvrename (const gchar *vg_name, const gchar *lv_name, const gchar *new_name, const BDExtraArg **extra, GError **error);
|
||||
gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 size, const BDExtraArg **extra, GError **error);
|
||||
gboolean bd_lvm_lvactivate (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, const BDExtraArg **extra, GError **error);
|
||||
+gboolean bd_lvm_lvactivate_shared (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, gboolean shared, const BDExtraArg **extra, GError **error);
|
||||
gboolean bd_lvm_lvdeactivate (const gchar *vg_name, const gchar *lv_name, const BDExtraArg **extra, GError **error);
|
||||
gboolean bd_lvm_lvsnapshotcreate (const gchar *vg_name, const gchar *origin_name, const gchar *snapshot_name, guint64 size, const BDExtraArg **extra, GError **error);
|
||||
gboolean bd_lvm_lvsnapshotmerge (const gchar *vg_name, const gchar *snapshot_name, const BDExtraArg **extra, GError **error);
|
||||
diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py
|
||||
index f768c8bd..c7d72f4b 100644
|
||||
--- a/src/python/gi/overrides/BlockDev.py
|
||||
+++ b/src/python/gi/overrides/BlockDev.py
|
||||
@@ -580,11 +580,10 @@ def lvm_lvresize(vg_name, lv_name, size, extra=None, **kwargs):
|
||||
return _lvm_lvresize(vg_name, lv_name, size, extra)
|
||||
__all__.append("lvm_lvresize")
|
||||
|
||||
-_lvm_lvactivate = BlockDev.lvm_lvactivate
|
||||
@override(BlockDev.lvm_lvactivate)
|
||||
-def lvm_lvactivate(vg_name, lv_name, ignore_skip=False, extra=None, **kwargs):
|
||||
+def lvm_lvactivate(vg_name, lv_name, ignore_skip=False, shared=False, extra=None, **kwargs):
|
||||
extra = _get_extra(extra, kwargs)
|
||||
- return _lvm_lvactivate(vg_name, lv_name, ignore_skip, extra)
|
||||
+ return BlockDev.lvm_lvactivate_shared(vg_name, lv_name, ignore_skip, shared, extra)
|
||||
__all__.append("lvm_lvactivate")
|
||||
|
||||
_lvm_lvdeactivate = BlockDev.lvm_lvdeactivate
|
||||
diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py
|
||||
index 4882da88..67eaccd1 100644
|
||||
--- a/tests/lvm_dbus_tests.py
|
||||
+++ b/tests/lvm_dbus_tests.py
|
||||
@@ -799,15 +799,15 @@ class LvmTestLVactivateDeactivate(LvmPVVGLVTestCase):
|
||||
self.assertTrue(succ)
|
||||
|
||||
with self.assertRaises(GLib.GError):
|
||||
- BlockDev.lvm_lvactivate("nonexistingVG", "testLV", True, None)
|
||||
+ BlockDev.lvm_lvactivate("nonexistingVG", "testLV", True)
|
||||
|
||||
with self.assertRaises(GLib.GError):
|
||||
- BlockDev.lvm_lvactivate("testVG", "nonexistingLV", True, None)
|
||||
+ BlockDev.lvm_lvactivate("testVG", "nonexistingLV", True)
|
||||
|
||||
with self.assertRaises(GLib.GError):
|
||||
- BlockDev.lvm_lvactivate("nonexistingVG", "nonexistingLV", True, None)
|
||||
+ BlockDev.lvm_lvactivate("nonexistingVG", "nonexistingLV", True)
|
||||
|
||||
- succ = BlockDev.lvm_lvactivate("testVG", "testLV", True, None)
|
||||
+ succ = BlockDev.lvm_lvactivate("testVG", "testLV", True)
|
||||
self.assertTrue(succ)
|
||||
|
||||
with self.assertRaises(GLib.GError):
|
||||
@@ -822,7 +822,15 @@ class LvmTestLVactivateDeactivate(LvmPVVGLVTestCase):
|
||||
succ = BlockDev.lvm_lvdeactivate("testVG", "testLV", None)
|
||||
self.assertTrue(succ)
|
||||
|
||||
- succ = BlockDev.lvm_lvactivate("testVG", "testLV", True, None)
|
||||
+ succ = BlockDev.lvm_lvactivate("testVG", "testLV", True)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ succ = BlockDev.lvm_lvdeactivate("testVG", "testLV", None)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ # try activating in shared mode, unfortunately no way to check whether it really
|
||||
+ # works or not
|
||||
+ succ = BlockDev.lvm_lvactivate("testVG", "testLV", True, True)
|
||||
self.assertTrue(succ)
|
||||
|
||||
succ = BlockDev.lvm_lvdeactivate("testVG", "testLV", None)
|
||||
diff --git a/tests/lvm_test.py b/tests/lvm_test.py
|
||||
index eb94c917..25e2f109 100644
|
||||
--- a/tests/lvm_test.py
|
||||
+++ b/tests/lvm_test.py
|
||||
@@ -730,15 +730,15 @@ class LvmTestLVactivateDeactivate(LvmPVVGLVTestCase):
|
||||
self.assertTrue(succ)
|
||||
|
||||
with self.assertRaises(GLib.GError):
|
||||
- BlockDev.lvm_lvactivate("nonexistingVG", "testLV", True, None)
|
||||
+ BlockDev.lvm_lvactivate("nonexistingVG", "testLV", True)
|
||||
|
||||
with self.assertRaises(GLib.GError):
|
||||
- BlockDev.lvm_lvactivate("testVG", "nonexistingLV", True, None)
|
||||
+ BlockDev.lvm_lvactivate("testVG", "nonexistingLV", True)
|
||||
|
||||
with self.assertRaises(GLib.GError):
|
||||
- BlockDev.lvm_lvactivate("nonexistingVG", "nonexistingLV", True, None)
|
||||
+ BlockDev.lvm_lvactivate("nonexistingVG", "nonexistingLV", True)
|
||||
|
||||
- succ = BlockDev.lvm_lvactivate("testVG", "testLV", True, None)
|
||||
+ succ = BlockDev.lvm_lvactivate("testVG", "testLV", True)
|
||||
self.assertTrue(succ)
|
||||
|
||||
with self.assertRaises(GLib.GError):
|
||||
@@ -753,7 +753,15 @@ class LvmTestLVactivateDeactivate(LvmPVVGLVTestCase):
|
||||
succ = BlockDev.lvm_lvdeactivate("testVG", "testLV", None)
|
||||
self.assertTrue(succ)
|
||||
|
||||
- succ = BlockDev.lvm_lvactivate("testVG", "testLV", True, None)
|
||||
+ succ = BlockDev.lvm_lvactivate("testVG", "testLV", True)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ succ = BlockDev.lvm_lvdeactivate("testVG", "testLV", None)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ # try activating in shared mode, unfortunately no way to check whether it really
|
||||
+ # works or not
|
||||
+ succ = BlockDev.lvm_lvactivate("testVG", "testLV", True, True)
|
||||
self.assertTrue(succ)
|
||||
|
||||
succ = BlockDev.lvm_lvdeactivate("testVG", "testLV", None)
|
||||
--
|
||||
2.41.0
|
||||
|
||||
@ -0,0 +1,299 @@
|
||||
From 5e8429d004445c6f6e6f16cab67cf14cb4d32a65 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 18 Apr 2023 12:05:35 +0200
|
||||
Subject: [PATCH] lvm: Add support for starting and stopping VG locking
|
||||
|
||||
---
|
||||
docs/libblockdev-sections.txt | 2 ++
|
||||
src/lib/plugin_apis/lvm.api | 27 +++++++++++++++++++
|
||||
src/plugins/lvm-dbus.c | 49 ++++++++++++++++++++++++++++++++++-
|
||||
src/plugins/lvm.c | 41 +++++++++++++++++++++++++++++
|
||||
src/plugins/lvm.h | 3 +++
|
||||
tests/lvm_dbus_tests.py | 33 +++++++++++++++++++++++
|
||||
tests/lvm_test.py | 32 +++++++++++++++++++++++
|
||||
7 files changed, 186 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/libblockdev-sections.txt b/docs/libblockdev-sections.txt
|
||||
index 512820c2..7377dd17 100644
|
||||
--- a/docs/libblockdev-sections.txt
|
||||
+++ b/docs/libblockdev-sections.txt
|
||||
@@ -286,6 +286,8 @@ bd_lvm_vgactivate
|
||||
bd_lvm_vgdeactivate
|
||||
bd_lvm_vgextend
|
||||
bd_lvm_vgreduce
|
||||
+bd_lvm_vglock_start
|
||||
+bd_lvm_vglock_stop
|
||||
bd_lvm_vginfo
|
||||
bd_lvm_vgs
|
||||
bd_lvm_lvorigin
|
||||
diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api
|
||||
index 54c47a93..14f2620a 100644
|
||||
--- a/src/lib/plugin_apis/lvm.api
|
||||
+++ b/src/lib/plugin_apis/lvm.api
|
||||
@@ -601,6 +601,7 @@ typedef enum {
|
||||
BD_LVM_TECH_CACHE_CALCS,
|
||||
BD_LVM_TECH_GLOB_CONF,
|
||||
BD_LVM_TECH_VDO,
|
||||
+ BD_LVM_TECH_SHARED,
|
||||
} BDLVMTech;
|
||||
|
||||
typedef enum {
|
||||
@@ -941,6 +942,32 @@ gboolean bd_lvm_vgextend (const gchar *vg_name, const gchar *device, const BDExt
|
||||
*/
|
||||
gboolean bd_lvm_vgreduce (const gchar *vg_name, const gchar *device, const BDExtraArg **extra, GError **error);
|
||||
|
||||
+/**
|
||||
+ * bd_lvm_vglock_start:
|
||||
+ * @vg_name: a shared VG to start the lockspace in lvmlockd
|
||||
+ * @extra: (nullable) (array zero-terminated=1): extra options for the vgchange command
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the lock was successfully started for @vg_name or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_SHARED-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_vglock_start (const gchar *vg_name, const BDExtraArg **extra, GError **error);
|
||||
+
|
||||
+/**
|
||||
+ * bd_lvm_vglock_stop:
|
||||
+ * @vg_name: a shared VG to stop the lockspace in lvmlockd
|
||||
+ * @extra: (nullable) (array zero-terminated=1): extra options for the vgchange command
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the lock was successfully stopped for @vg_name or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_SHARED-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_vglock_stop (const gchar *vg_name, const BDExtraArg **extra, GError **error);
|
||||
+
|
||||
/**
|
||||
* bd_lvm_vginfo:
|
||||
* @vg_name: a VG to get information about
|
||||
diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c
|
||||
index e1f946fe..ad44dfb3 100644
|
||||
--- a/src/plugins/lvm-dbus.c
|
||||
+++ b/src/plugins/lvm-dbus.c
|
||||
@@ -1848,10 +1848,57 @@ gboolean bd_lvm_vgreduce (const gchar *vg_name, const gchar *device, const BDExt
|
||||
return ((*error) == NULL);
|
||||
}
|
||||
|
||||
+gboolean _vglock_start_stop (const gchar *vg_name, gboolean start, const BDExtraArg **extra, GError **error) {
|
||||
+ GVariantBuilder builder;
|
||||
+ GVariant *params = NULL;
|
||||
+
|
||||
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
|
||||
+ if (start)
|
||||
+ g_variant_builder_add (&builder, "{sv}", "--lockstart", g_variant_new ("s", ""));
|
||||
+ else
|
||||
+ g_variant_builder_add (&builder, "{sv}", "--lockstop", g_variant_new ("s", ""));
|
||||
+ params = g_variant_builder_end (&builder);
|
||||
+ g_variant_builder_clear (&builder);
|
||||
+
|
||||
+ call_lvm_obj_method_sync (vg_name, VG_INTF, "Change", NULL, params, extra, TRUE, error);
|
||||
+
|
||||
+ return ((*error) == NULL);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * bd_lvm_vglock_start:
|
||||
+ * @vg_name: a shared VG to start the lockspace in lvmlockd
|
||||
+ * @extra: (nullable) (array zero-terminated=1): extra options for the vgchange command
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the lock was successfully started for @vg_name or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_vglock_start (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
|
||||
+ return _vglock_start_stop (vg_name, TRUE, extra, error);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * bd_lvm_vglock_stop:
|
||||
+ * @vg_name: a shared VG to stop the lockspace in lvmlockd
|
||||
+ * @extra: (nullable) (array zero-terminated=1): extra options for the vgchange command
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the lock was successfully stopped for @vg_name or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_vglock_stop (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
|
||||
+ return _vglock_start_stop (vg_name, FALSE, extra, error);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* bd_lvm_vginfo:
|
||||
* @vg_name: a VG to get information about
|
||||
- * @error: (out): place to store error (if any)
|
||||
+ * @error: (out) (optional): place to store error (if any)
|
||||
*
|
||||
* Returns: (transfer full): information about the @vg_name VG or %NULL in case
|
||||
* of error (the @error) gets populated in those cases)
|
||||
diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c
|
||||
index 8bb3ae24..1aaf6747 100644
|
||||
--- a/src/plugins/lvm.c
|
||||
+++ b/src/plugins/lvm.c
|
||||
@@ -1316,6 +1316,47 @@ gboolean bd_lvm_vgreduce (const gchar *vg_name, const gchar *device, const BDExt
|
||||
return call_lvm_and_report_error (args, extra, TRUE, error);
|
||||
}
|
||||
|
||||
+gboolean _vglock_start_stop (const gchar *vg_name, gboolean start, const BDExtraArg **extra, GError **error) {
|
||||
+ const gchar *args[4] = {"vgchange", NULL, vg_name, NULL};
|
||||
+
|
||||
+ if (start)
|
||||
+ args[1] = "--lockstart";
|
||||
+ else
|
||||
+ args[1] = "--lockstop";
|
||||
+
|
||||
+ return call_lvm_and_report_error (args, extra, TRUE, error);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * bd_lvm_vglock_start:
|
||||
+ * @vg_name: a shared VG to start the lockspace in lvmlockd
|
||||
+ * @extra: (nullable) (array zero-terminated=1): extra options for the vgchange command
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the lock was successfully started for @vg_name or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_SHARED-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_vglock_start (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
|
||||
+ return _vglock_start_stop (vg_name, TRUE, extra, error);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * bd_lvm_vglock_stop:
|
||||
+ * @vg_name: a shared VG to stop the lockspace in lvmlockd
|
||||
+ * @extra: (nullable) (array zero-terminated=1): extra options for the vgchange command
|
||||
+ * (just passed to LVM as is)
|
||||
+ * @error: (out): place to store error (if any)
|
||||
+ *
|
||||
+ * Returns: whether the lock was successfully stopped for @vg_name or not
|
||||
+ *
|
||||
+ * Tech category: %BD_LVM_TECH_SHARED-%BD_LVM_TECH_MODE_MODIFY
|
||||
+ */
|
||||
+gboolean bd_lvm_vglock_stop (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
|
||||
+ return _vglock_start_stop (vg_name, FALSE, extra, error);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* bd_lvm_vginfo:
|
||||
* @vg_name: a VG to get information about
|
||||
diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h
|
||||
index 244663a4..da14cc1a 100644
|
||||
--- a/src/plugins/lvm.h
|
||||
+++ b/src/plugins/lvm.h
|
||||
@@ -216,6 +216,7 @@ typedef enum {
|
||||
BD_LVM_TECH_CACHE_CALCS,
|
||||
BD_LVM_TECH_GLOB_CONF,
|
||||
BD_LVM_TECH_VDO,
|
||||
+ BD_LVM_TECH_SHARED,
|
||||
} BDLVMTech;
|
||||
|
||||
typedef enum {
|
||||
@@ -266,6 +267,8 @@ gboolean bd_lvm_vgactivate (const gchar *vg_name, const BDExtraArg **extra, GErr
|
||||
gboolean bd_lvm_vgdeactivate (const gchar *vg_name, const BDExtraArg **extra, GError **error);
|
||||
gboolean bd_lvm_vgextend (const gchar *vg_name, const gchar *device, const BDExtraArg **extra, GError **error);
|
||||
gboolean bd_lvm_vgreduce (const gchar *vg_name, const gchar *device, const BDExtraArg **extra, GError **error);
|
||||
+gboolean bd_lvm_vglock_start (const gchar *vg_name, const BDExtraArg **extra, GError **error);
|
||||
+gboolean bd_lvm_vglock_stop (const gchar *vg_name, const BDExtraArg **extra, GError **error);
|
||||
BDLVMVGdata* bd_lvm_vginfo (const gchar *vg_name, GError **error);
|
||||
BDLVMVGdata** bd_lvm_vgs (GError **error);
|
||||
|
||||
diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py
|
||||
index 862a44cf..2a92c7c1 100644
|
||||
--- a/tests/lvm_dbus_tests.py
|
||||
+++ b/tests/lvm_dbus_tests.py
|
||||
@@ -612,6 +612,39 @@ class LvmTestVGs(LvmPVVGTestCase):
|
||||
succ = BlockDev.lvm_pvremove(self.loop_dev, None)
|
||||
self.assertTrue(succ)
|
||||
|
||||
+@unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
|
||||
+class LvmTestVGLocking(LvmPVVGTestCase):
|
||||
+ @tag_test(TestTags.UNSAFE)
|
||||
+ def test_vglock_stop_start(self):
|
||||
+ """Verify that it is possible to start and stop locking on a VG"""
|
||||
+
|
||||
+ # better not do anything if lvmlockd is running, shared VGs have
|
||||
+ # a tendency to wreak havoc on your system if you look at them wrong
|
||||
+ ret, _out, _err = run_command("systemctl is-active lvmlockd")
|
||||
+ if ret == 0:
|
||||
+ self.skipTest("lvmlockd is running, skipping")
|
||||
+
|
||||
+ _ret, out, _err = run_command("lvm config 'global/use_lvmlockd'")
|
||||
+ if "use_lvmlockd=0" not in out:
|
||||
+ self.skipTest("lvmlockd is enabled, skipping")
|
||||
+
|
||||
+ succ = BlockDev.lvm_pvcreate(self.loop_dev, 0, 0, None)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ succ = BlockDev.lvm_pvcreate(self.loop_dev2, 0, 0, None)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ succ = BlockDev.lvm_vgcreate("testVG", [self.loop_dev, self.loop_dev2], 0, None)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ # this actually doesn't "test" anything, the commands will just say lvmlockd is not
|
||||
+ # running and return 0, but that's good enough for us
|
||||
+ succ = BlockDev.lvm_vglock_start("testVG")
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ succ = BlockDev.lvm_vglock_stop("testVG")
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
@unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
|
||||
class LvmPVVGLVTestCase(LvmPVVGTestCase):
|
||||
def _clean_up(self):
|
||||
diff --git a/tests/lvm_test.py b/tests/lvm_test.py
|
||||
index 96f1670d..3ab11f04 100644
|
||||
--- a/tests/lvm_test.py
|
||||
+++ b/tests/lvm_test.py
|
||||
@@ -585,6 +585,38 @@ class LvmTestVGs(LvmPVVGTestCase):
|
||||
succ = BlockDev.lvm_pvremove(self.loop_dev, None)
|
||||
self.assertTrue(succ)
|
||||
|
||||
+class LvmTestVGLocking(LvmPVVGTestCase):
|
||||
+ @tag_test(TestTags.UNSAFE)
|
||||
+ def test_vglock_stop_start(self):
|
||||
+ """Verify that it is possible to start and stop locking on a VG"""
|
||||
+
|
||||
+ # better not do anything if lvmlockd is running, shared VGs have
|
||||
+ # a tendency to wreak havoc on your system if you look at them wrong
|
||||
+ ret, _out, _err = run_command("systemctl is-active lvmlockd")
|
||||
+ if ret == 0:
|
||||
+ self.skipTest("lvmlockd is running, skipping")
|
||||
+
|
||||
+ _ret, out, _err = run_command("lvm config 'global/use_lvmlockd'")
|
||||
+ if "use_lvmlockd=0" not in out:
|
||||
+ self.skipTest("lvmlockd is enabled, skipping")
|
||||
+
|
||||
+ succ = BlockDev.lvm_pvcreate(self.loop_dev, 0, 0, None)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ succ = BlockDev.lvm_pvcreate(self.loop_dev2, 0, 0, None)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ succ = BlockDev.lvm_vgcreate("testVG", [self.loop_dev, self.loop_dev2], 0, None)
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ # this actually doesn't "test" anything, the commands will just say lvmlockd is not
|
||||
+ # running and return 0, but that's good enough for us
|
||||
+ succ = BlockDev.lvm_vglock_start("testVG")
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
+ succ = BlockDev.lvm_vglock_stop("testVG")
|
||||
+ self.assertTrue(succ)
|
||||
+
|
||||
class LvmPVVGLVTestCase(LvmPVVGTestCase):
|
||||
def _clean_up(self):
|
||||
try:
|
||||
--
|
||||
2.41.0
|
||||
|
||||
26
SOURCES/0006-Don-t-allow-suid-and-dev-set-on-fs-resize.patch
Normal file
26
SOURCES/0006-Don-t-allow-suid-and-dev-set-on-fs-resize.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 2508f4842482b87d26f81afecc7d0b584d6a6fa8 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Blume <Thomas.Blume@suse.com>
|
||||
Date: Fri, 16 May 2025 14:27:10 +0200
|
||||
Subject: [PATCH] Don't allow suid and dev set on fs resize
|
||||
|
||||
Fixes: CVE-2025-6019
|
||||
---
|
||||
src/plugins/fs/generic.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/plugins/fs/generic.c b/src/plugins/fs/generic.c
|
||||
index ca08d19a..15b55271 100644
|
||||
--- a/src/plugins/fs/generic.c
|
||||
+++ b/src/plugins/fs/generic.c
|
||||
@@ -409,7 +409,7 @@ static gboolean xfs_resize_device (const gchar *device, guint64 new_size, const
|
||||
"before resizing it.", device);
|
||||
return FALSE;
|
||||
}
|
||||
- ret = bd_fs_mount (device, mountpoint, "xfs", NULL, NULL, error);
|
||||
+ ret = bd_fs_mount (device, mountpoint, "xfs", "nosuid,nodev", NULL, error);
|
||||
if (!ret) {
|
||||
g_prefix_error (error, "Failed to mount '%s' before resizing it: ", device);
|
||||
return FALSE;
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -124,16 +124,20 @@
|
||||
%define configure_opts %{?python2_copts} %{?python3_copts} %{?bcache_copts} %{?lvm_dbus_copts} %{?btrfs_copts} %{?crypto_copts} %{?dm_copts} %{?loop_copts} %{?lvm_copts} %{?lvm_dbus_copts} %{?mdraid_copts} %{?mpath_copts} %{?swap_copts} %{?kbd_copts} %{?part_copts} %{?fs_copts} %{?nvdimm_copts} %{?vdo_copts} %{?tools_copts} %{?gi_copts}
|
||||
|
||||
Name: libblockdev
|
||||
Version: 2.24
|
||||
Release: 5%{?dist}
|
||||
Version: 2.28
|
||||
Release: 7%{?dist}
|
||||
Summary: A library for low-level manipulation with block devices
|
||||
License: LGPLv2+
|
||||
URL: https://github.com/storaged-project/libblockdev
|
||||
Source0: https://github.com/storaged-project/libblockdev/releases/download/%{version}-%{release}/%{name}-%{version}.tar.gz
|
||||
Patch0: 0001-exec-Fix-setting-locale-for-util-calls.patch
|
||||
Patch1: 0002-exec-polling-fixes.patch
|
||||
Patch2: 0003-LVM-thin-metadata-calculation-fix.patch
|
||||
Patch0: 0001-crypto-Fix-GError-overwrite-from-libvolume_key.patch
|
||||
Patch1: 0002-tests-Fix-test_swapon_pagesize-on-systems-with-64k-p.patch
|
||||
Patch2: 0003-part-Fix-segfault-when-adding-a-partition-too-big-fo.patch
|
||||
Patch3: 0004-lvm-Add-a-function-to-activate-LVs-in-shared-mode.patch
|
||||
Patch4: 0005-lvm-Add-support-for-starting-and-stopping-VG-locking.patch
|
||||
Patch5: 0006-Don-t-allow-suid-and-dev-set-on-fs-resize.patch
|
||||
|
||||
BuildRequires: make
|
||||
BuildRequires: glib2-devel
|
||||
%if %{with_gi}
|
||||
BuildRequires: gobject-introspection-devel
|
||||
@ -176,6 +180,7 @@ no information about VGs when creating an LV).
|
||||
Summary: Development files for libblockdev
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
Requires: glib2-devel
|
||||
Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release}
|
||||
|
||||
%description devel
|
||||
This package contains header files and pkg-config files needed for development
|
||||
@ -253,6 +258,7 @@ with the libblockdev-btrfs plugin/library.
|
||||
|
||||
%if %{with_crypto}
|
||||
%package crypto
|
||||
Requires: %{name}-utils%{?_isa} = %{version}-%{release}
|
||||
BuildRequires: cryptsetup-devel
|
||||
BuildRequires: libblkid-devel
|
||||
|
||||
@ -262,7 +268,6 @@ BuildRequires: nss-devel
|
||||
%endif
|
||||
|
||||
Summary: The crypto plugin for the libblockdev library
|
||||
Requires: %{name}-utils%{?_isa} = %{version}-%{release}
|
||||
|
||||
%description crypto
|
||||
The libblockdev library plugin (and in the same time a standalone library)
|
||||
@ -394,8 +399,6 @@ BuildRequires: device-mapper-devel
|
||||
Summary: The LVM plugin for the libblockdev library
|
||||
Requires: %{name}-utils%{?_isa} = %{version}-%{release}
|
||||
Requires: lvm2
|
||||
# for thin_metadata_size
|
||||
Requires: device-mapper-persistent-data
|
||||
|
||||
%description lvm
|
||||
The libblockdev library plugin (and in the same time a standalone library)
|
||||
@ -418,8 +421,6 @@ BuildRequires: device-mapper-devel
|
||||
Summary: The LVM plugin for the libblockdev library
|
||||
Requires: %{name}-utils%{?_isa} = %{version}-%{release}
|
||||
Requires: lvm2-dbusd >= 2.02.156
|
||||
# for thin_metadata_size
|
||||
Requires: device-mapper-persistent-data
|
||||
|
||||
%description lvm-dbus
|
||||
The libblockdev library plugin (and in the same time a standalone library)
|
||||
@ -589,8 +590,8 @@ with the libblockdev-vdo plugin/library.
|
||||
%if %{with_tools}
|
||||
%package tools
|
||||
Summary: Various nice tools based on libblockdev
|
||||
Requires: %{name}
|
||||
Requires: %{name}-lvm
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: %{name}-lvm = %{version}-%{release}
|
||||
BuildRequires: libbytesize-devel
|
||||
%if %{with_lvm_dbus} == 1
|
||||
Recommends: %{name}-lvm-dbus
|
||||
@ -687,10 +688,7 @@ A meta-package that pulls all the libblockdev plugins as dependencies.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
%patch0 -p1
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%autosetup -n %{name}-%{version} -p1
|
||||
|
||||
%build
|
||||
autoreconf -ivf
|
||||
@ -994,6 +992,58 @@ find %{buildroot} -type f -name "*.la" | xargs %{__rm}
|
||||
%files plugins-all
|
||||
|
||||
%changelog
|
||||
* Mon Jun 16 2025 Vojtech Trefny <vtrefny@redhat.com> - 2.28-7
|
||||
- Don't allow suid and dev set on fs resize (CVE-2025-6019)
|
||||
Resolves: RHEL-96034
|
||||
|
||||
* Wed Nov 08 2023 Vojtech Trefny <vtrefny@redhat.com> - 2.28-6
|
||||
- lvm: Add support for starting and stopping VG locking
|
||||
Resolves: RHEL-15923
|
||||
|
||||
* Thu Oct 19 2023 Vojtech Trefny <vtrefny@redhat.com> - 2.28-5
|
||||
- lvm: Add a function to activate LVs in shared mode
|
||||
Resolves: RHEL-14023
|
||||
|
||||
* Tue May 16 2023 Vojtech Trefny <vtrefny@redhat.com> - 2.28-4
|
||||
- Fix segfault when adding a partition too big for MSDOS
|
||||
Resolves: rhbz#2207500
|
||||
|
||||
* Mon Apr 03 2023 Vojtech Trefny <vtrefny@redhat.com> - 2.28-3
|
||||
- Fix test_swapon_pagesize on systems with 64k pages
|
||||
Resolves: rhbz#2138698
|
||||
|
||||
* Wed Nov 30 2022 Vojtech Trefny <vtrefny@redhat.com> - 2.28-2
|
||||
- Fix double free in write_escrow_data_file
|
||||
Resolves: rhbz#2142660
|
||||
|
||||
* Wed Sep 14 2022 Vojtech Trefny <vtrefny@redhat.com> - 2.28-1
|
||||
- Rebase to the latest upstream release 2.28
|
||||
Resolves: rhbz#2123347
|
||||
|
||||
* Mon Aug 08 2022 Vojtech Trefny <vtrefny@redhat.com> - 2.24-11
|
||||
- mdraid: Fix use after free
|
||||
Related: rhbz#2078815
|
||||
|
||||
* Mon Aug 08 2022 Vojtech Trefny <vtrefny@redhat.com> - 2.24-10
|
||||
- mdraid: Fix copy-paste error when checking return value
|
||||
Related: rhbz#2078815
|
||||
|
||||
* Fri Aug 05 2022 Vojtech Trefny <vtrefny@redhat.com> - 2.24-9
|
||||
- Fix getting UUID for DDF containers
|
||||
Resolves: rhbz#2078815
|
||||
|
||||
* Tue Dec 07 2021 Vojtech Trefny <vtrefny@redhat.com> - 2.24-8
|
||||
- Fix vdo stats calculation
|
||||
Resolves: rhbz#2023883
|
||||
|
||||
* Wed Jun 30 2021 Vojtech Trefny <vtrefny@redhat.com> - 2.24-7
|
||||
- Add workarounds for some LVM test issues
|
||||
Resolves: rhbz#1974352
|
||||
|
||||
* Fri May 14 2021 Vojtech Trefny <vtrefny@redhat.com> - 2.24-6
|
||||
- Fix default key size for non XTS ciphers
|
||||
Resolves: rhbz#1931847
|
||||
|
||||
* Mon Jan 11 2021 Vojtech Trefny <vtrefny@redhat.com> - 2.24-5
|
||||
- Fix LVM thin metadata calculation fix
|
||||
Resolves: rhbz#1901714
|
||||
|
||||
Loading…
Reference in New Issue
Block a user