|
Philipp Rudo |
90da03 |
commit feae3d1754d2b0788ce1f18b0cd4b40098ff52ff
|
|
Philipp Rudo |
90da03 |
Author: Philipp Rudo <prudo@redhat.com>
|
|
Philipp Rudo |
90da03 |
Date: Mon Mar 14 17:04:29 2022 +0100
|
|
Philipp Rudo |
90da03 |
|
|
Philipp Rudo |
90da03 |
[PATCH v2 1/3] add generic cycle detection
|
|
Philipp Rudo |
90da03 |
|
|
Philipp Rudo |
90da03 |
In order to work makedumpfile needs to interpret data read from the
|
|
Philipp Rudo |
90da03 |
dump. This can cause problems as the data from the dump cannot be
|
|
Philipp Rudo |
90da03 |
trusted (otherwise the kernel wouldn't have panicked in the first
|
|
Philipp Rudo |
90da03 |
place). This also means that every loop which stop condition depend on
|
|
Philipp Rudo |
90da03 |
data read from the dump has a chance to loop forever. Thus add a generic
|
|
Philipp Rudo |
90da03 |
cycle detection mechanism that allows to detect and handle such
|
|
Philipp Rudo |
90da03 |
situations appropriately.
|
|
Philipp Rudo |
90da03 |
|
|
Philipp Rudo |
90da03 |
For cycle detection use Brent's algorithm [1] as it has constant memory
|
|
Philipp Rudo |
90da03 |
usage. With this it can also be used in the kdump kernel without the
|
|
Philipp Rudo |
90da03 |
danger that it runs oom when iterating large data structures.
|
|
Philipp Rudo |
90da03 |
Furthermore it only depends on some pointer arithmetic. Thus the
|
|
Philipp Rudo |
90da03 |
performance impact (as long as no cycle was detected) should be
|
|
Philipp Rudo |
90da03 |
comparatively small.
|
|
Philipp Rudo |
90da03 |
|
|
Philipp Rudo |
90da03 |
[1] https://en.wikipedia.org/wiki/Cycle_detection#Brent's_algorithm
|
|
Philipp Rudo |
90da03 |
|
|
Philipp Rudo |
90da03 |
Suggested-by: Dave Wysochanski <dwysocha@redhat.com>
|
|
Philipp Rudo |
90da03 |
Signed-off-by: Philipp Rudo <prudo@redhat.com>
|
|
Philipp Rudo |
90da03 |
Reviewed-and-tested-by: Dave Wysochanski <dwysocha@redhat.com>
|
|
Philipp Rudo |
90da03 |
|
|
Philipp Rudo |
90da03 |
diff --git a/makedumpfile-1.7.0/Makefile b/makedumpfile-1.7.0/Makefile
|
|
Philipp Rudo |
90da03 |
index f118b31e45989d9590ae075fb9b8ed2f27353a92..3441364cb6c7103a20072bd50ec58f1eed01ab69 100644
|
|
Philipp Rudo |
90da03 |
--- a/makedumpfile-1.7.0/Makefile
|
|
Philipp Rudo |
90da03 |
+++ b/makedumpfile-1.7.0/Makefile
|
|
Philipp Rudo |
90da03 |
@@ -45,7 +45,7 @@ CFLAGS_ARCH += -m32
|
|
Philipp Rudo |
90da03 |
endif
|
|
Philipp Rudo |
90da03 |
|
|
Philipp Rudo |
90da03 |
SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h
|
|
Philipp Rudo |
90da03 |
-SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c printk.c
|
|
Philipp Rudo |
90da03 |
+SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c printk.c detect_cycle.c
|
|
Philipp Rudo |
90da03 |
OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
|
|
Philipp Rudo |
90da03 |
SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c arch/mips64.c
|
|
Philipp Rudo |
90da03 |
OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
|
|
Philipp Rudo |
90da03 |
diff --git a/makedumpfile-1.7.0/detect_cycle.c b/makedumpfile-1.7.0/detect_cycle.c
|
|
Philipp Rudo |
90da03 |
new file mode 100644
|
|
Philipp Rudo |
90da03 |
index 0000000000000000000000000000000000000000..6b551a75d1c83d64fba2c078be8133efbc791fbe
|
|
Philipp Rudo |
90da03 |
--- /dev/null
|
|
Philipp Rudo |
90da03 |
+++ b/makedumpfile-1.7.0/detect_cycle.c
|
|
Philipp Rudo |
90da03 |
@@ -0,0 +1,99 @@
|
|
Philipp Rudo |
90da03 |
+/*
|
|
Philipp Rudo |
90da03 |
+ * detect_cycle.c -- Generic cycle detection using Brent's algorithm
|
|
Philipp Rudo |
90da03 |
+ *
|
|
Philipp Rudo |
90da03 |
+ * Created by: Philipp Rudo <prudo@redhat.com>
|
|
Philipp Rudo |
90da03 |
+ *
|
|
Philipp Rudo |
90da03 |
+ * Copyright (c) 2022 Red Hat, Inc. All rights reserved.
|
|
Philipp Rudo |
90da03 |
+ *
|
|
Philipp Rudo |
90da03 |
+ * This program is free software; you can redistribute it and/or modify
|
|
Philipp Rudo |
90da03 |
+ * it under the terms of the GNU General Public License as published by
|
|
Philipp Rudo |
90da03 |
+ * the Free Software Foundation; either version 2 of the License, or
|
|
Philipp Rudo |
90da03 |
+ * (at your option) any later version.
|
|
Philipp Rudo |
90da03 |
+ *
|
|
Philipp Rudo |
90da03 |
+ * This program is distributed in the hope that it will be useful,
|
|
Philipp Rudo |
90da03 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Philipp Rudo |
90da03 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Philipp Rudo |
90da03 |
+ * GNU General Public License for more details.
|
|
Philipp Rudo |
90da03 |
+ */
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+#include <stdlib.h>
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+#include "detect_cycle.h"
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+struct detect_cycle {
|
|
Philipp Rudo |
90da03 |
+ /* First entry of the list */
|
|
Philipp Rudo |
90da03 |
+ void *head;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ /* Variables required by Brent's algorithm */
|
|
Philipp Rudo |
90da03 |
+ void *fast_p;
|
|
Philipp Rudo |
90da03 |
+ void *slow_p;
|
|
Philipp Rudo |
90da03 |
+ unsigned long length;
|
|
Philipp Rudo |
90da03 |
+ unsigned long power;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ /* Function to get the next entry in the list */
|
|
Philipp Rudo |
90da03 |
+ dc_next_t next;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ /* Private data passed to next */
|
|
Philipp Rudo |
90da03 |
+ void *data;
|
|
Philipp Rudo |
90da03 |
+};
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+struct detect_cycle *dc_init(void *head, void *data, dc_next_t next)
|
|
Philipp Rudo |
90da03 |
+{
|
|
Philipp Rudo |
90da03 |
+ struct detect_cycle *new;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ new = malloc(sizeof(*new));
|
|
Philipp Rudo |
90da03 |
+ if (!new)
|
|
Philipp Rudo |
90da03 |
+ return NULL;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ new->next = next;
|
|
Philipp Rudo |
90da03 |
+ new->data = data;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ new->head = head;
|
|
Philipp Rudo |
90da03 |
+ new->slow_p = head;
|
|
Philipp Rudo |
90da03 |
+ new->fast_p = head;
|
|
Philipp Rudo |
90da03 |
+ new->length = 0;
|
|
Philipp Rudo |
90da03 |
+ new->power = 2;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ return new;
|
|
Philipp Rudo |
90da03 |
+}
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+int dc_next(struct detect_cycle *dc, void **next)
|
|
Philipp Rudo |
90da03 |
+{
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ if (dc->length == dc->power) {
|
|
Philipp Rudo |
90da03 |
+ dc->length = 0;
|
|
Philipp Rudo |
90da03 |
+ dc->power *= 2;
|
|
Philipp Rudo |
90da03 |
+ dc->slow_p = dc->fast_p;
|
|
Philipp Rudo |
90da03 |
+ }
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ dc->fast_p = dc->next(dc->fast_p, dc->data);
|
|
Philipp Rudo |
90da03 |
+ dc->length++;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ if (dc->slow_p == dc->fast_p)
|
|
Philipp Rudo |
90da03 |
+ return 1;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ *next = dc->fast_p;
|
|
Philipp Rudo |
90da03 |
+ return 0;
|
|
Philipp Rudo |
90da03 |
+}
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+void dc_find_start(struct detect_cycle *dc, void **first, unsigned long *len)
|
|
Philipp Rudo |
90da03 |
+{
|
|
Philipp Rudo |
90da03 |
+ void *slow_p, *fast_p;
|
|
Philipp Rudo |
90da03 |
+ unsigned long tmp;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ slow_p = fast_p = dc->head;
|
|
Philipp Rudo |
90da03 |
+ tmp = dc->length;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ while (tmp) {
|
|
Philipp Rudo |
90da03 |
+ fast_p = dc->next(fast_p, dc->data);
|
|
Philipp Rudo |
90da03 |
+ tmp--;
|
|
Philipp Rudo |
90da03 |
+ }
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ while (slow_p != fast_p) {
|
|
Philipp Rudo |
90da03 |
+ slow_p = dc->next(slow_p, dc->data);
|
|
Philipp Rudo |
90da03 |
+ fast_p = dc->next(fast_p, dc->data);
|
|
Philipp Rudo |
90da03 |
+ }
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+ *first = slow_p;
|
|
Philipp Rudo |
90da03 |
+ *len = dc->length;
|
|
Philipp Rudo |
90da03 |
+}
|
|
Philipp Rudo |
90da03 |
diff --git a/makedumpfile-1.7.0/detect_cycle.h b/makedumpfile-1.7.0/detect_cycle.h
|
|
Philipp Rudo |
90da03 |
new file mode 100644
|
|
Philipp Rudo |
90da03 |
index 0000000000000000000000000000000000000000..2ca75c78b59a98274fc5a98666b1be74f7bbfc2c
|
|
Philipp Rudo |
90da03 |
--- /dev/null
|
|
Philipp Rudo |
90da03 |
+++ b/makedumpfile-1.7.0/detect_cycle.h
|
|
Philipp Rudo |
90da03 |
@@ -0,0 +1,40 @@
|
|
Philipp Rudo |
90da03 |
+/*
|
|
Philipp Rudo |
90da03 |
+ * detect_cycle.h -- Generic cycle detection using Brent's algorithm
|
|
Philipp Rudo |
90da03 |
+ *
|
|
Philipp Rudo |
90da03 |
+ * Created by: Philipp Rudo <prudo@redhat.com>
|
|
Philipp Rudo |
90da03 |
+ *
|
|
Philipp Rudo |
90da03 |
+ * Copyright (c) 2022 Red Hat, Inc. All rights reserved.
|
|
Philipp Rudo |
90da03 |
+ *
|
|
Philipp Rudo |
90da03 |
+ * This program is free software; you can redistribute it and/or modify
|
|
Philipp Rudo |
90da03 |
+ * it under the terms of the GNU General Public License as published by
|
|
Philipp Rudo |
90da03 |
+ * the Free Software Foundation; either version 2 of the License, or
|
|
Philipp Rudo |
90da03 |
+ * (at your option) any later version.
|
|
Philipp Rudo |
90da03 |
+ *
|
|
Philipp Rudo |
90da03 |
+ * This program is distributed in the hope that it will be useful,
|
|
Philipp Rudo |
90da03 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Philipp Rudo |
90da03 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Philipp Rudo |
90da03 |
+ * GNU General Public License for more details.
|
|
Philipp Rudo |
90da03 |
+ */
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+struct detect_cycle;
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+typedef void *(*dc_next_t)(void *prev, void *data);
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+/*
|
|
Philipp Rudo |
90da03 |
+ * Initialize cycle detection.
|
|
Philipp Rudo |
90da03 |
+ * Returns a pointer to allocated struct detect_cycle. The caller is
|
|
Philipp Rudo |
90da03 |
+ * responsible to free the memory after use.
|
|
Philipp Rudo |
90da03 |
+ */
|
|
Philipp Rudo |
90da03 |
+struct detect_cycle *dc_init(void *head, void *data, dc_next_t next);
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+/*
|
|
Philipp Rudo |
90da03 |
+ * Get next entry in the list using dc->next.
|
|
Philipp Rudo |
90da03 |
+ * Returns 1 when cycle was detected, 0 otherwise.
|
|
Philipp Rudo |
90da03 |
+ */
|
|
Philipp Rudo |
90da03 |
+int dc_next(struct detect_cycle *dc, void **next);
|
|
Philipp Rudo |
90da03 |
+
|
|
Philipp Rudo |
90da03 |
+/*
|
|
Philipp Rudo |
90da03 |
+ * Get the start and length of the cycle. Must only be called after cycle was
|
|
Philipp Rudo |
90da03 |
+ * detected by dc_next.
|
|
Philipp Rudo |
90da03 |
+ */
|
|
Philipp Rudo |
90da03 |
+void dc_find_start(struct detect_cycle *dc, void **first, unsigned long *len);
|