When `gd` is relocated during `spl_relocate_stack_gd()` the
doubly-linked circular list in the `log_head` member is broken.

The last element of the list should point back to the initial
`list_head`, but as the initial `list_head` is moved the pointer becomes
stale. As a result the loop in `log_dispatch` would never finish.

Migrate the list to a singly-linked non-circular one which is
easily relocatable.

This should also remove the special handling introduced in
commit e7595aa350ae ("x86: Allow logging to be used in SPL reliably").

Signed-off-by: Thomas Weißschuh <thomas.weisssc...@linutronix.de>
---
 common/log.c                      | 15 +++++++++------
 include/asm-generic/global_data.h |  2 +-
 include/log.h                     |  2 +-
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/common/log.c b/common/log.c
index b2de57fcb3b8..098d40c86d81 100644
--- a/common/log.c
+++ b/common/log.c
@@ -109,7 +109,7 @@ struct log_device *log_device_find_by_name(const char 
*drv_name)
 {
        struct log_device *ldev;
 
-       list_for_each_entry(ldev, &gd->log_head, sibling_node) {
+       for (ldev = gd->log_head; ldev; ldev = ldev->sibling_node) {
                if (!strcmp(drv_name, ldev->drv->name))
                        return ldev;
        }
@@ -218,7 +218,7 @@ static int log_dispatch(struct log_rec *rec, const char 
*fmt, va_list args)
 
        /* Emit message */
        gd->processing_msg = true;
-       list_for_each_entry(ldev, &gd->log_head, sibling_node) {
+       for (ldev = gd->log_head; ldev; ldev = ldev->sibling_node) {
                if ((ldev->flags & LOGDF_ENABLE) &&
                    log_passes_filters(ldev, rec)) {
                        if (!rec->msg) {
@@ -400,7 +400,7 @@ static struct log_device *log_find_device_by_drv(struct 
log_driver *drv)
 {
        struct log_device *ldev;
 
-       list_for_each_entry(ldev, &gd->log_head, sibling_node) {
+       for (ldev = gd->log_head; ldev; ldev = ldev->sibling_node) {
                if (ldev->drv == drv)
                        return ldev;
        }
@@ -433,13 +433,16 @@ int log_init(void)
        struct log_driver *drv = ll_entry_start(struct log_driver, log_driver);
        const int count = ll_entry_count(struct log_driver, log_driver);
        struct log_driver *end = drv + count;
+       struct log_device **log_head;
+
+       gd->log_head = NULL;
+       log_head = (struct log_device **)&gd->log_head;
 
        /*
         * We cannot add runtime data to the driver since it is likely stored
         * in rodata. Instead, set up a 'device' corresponding to each driver.
         * We only support having a single device for each driver.
         */
-       INIT_LIST_HEAD((struct list_head *)&gd->log_head);
        while (drv < end) {
                struct log_device *ldev;
 
@@ -451,8 +454,8 @@ int log_init(void)
                INIT_LIST_HEAD(&ldev->filter_head);
                ldev->drv = drv;
                ldev->flags = drv->flags;
-               list_add_tail(&ldev->sibling_node,
-                             (struct list_head *)&gd->log_head);
+               *log_head = ldev;
+               log_head = &ldev->sibling_node;
                drv++;
        }
        gd->flags |= GD_FLG_LOG_READY;
diff --git a/include/asm-generic/global_data.h 
b/include/asm-generic/global_data.h
index fcc3c6e14ca3..a9a407b801c2 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -404,7 +404,7 @@ struct global_data {
        /**
         * @log_head: list of logging devices
         */
-       struct list_head log_head;
+       struct log_device *log_head;
        /**
         * @log_fmt: bit mask for logging format
         *
diff --git a/include/log.h b/include/log.h
index 6e84f080ef3d..961233684d2a 100644
--- a/include/log.h
+++ b/include/log.h
@@ -455,7 +455,7 @@ struct log_device {
        unsigned short flags;
        struct log_driver *drv;
        struct list_head filter_head;
-       struct list_head sibling_node;
+       struct log_device *sibling_node;
 };
 
 enum {

---
base-commit: e8f2404e093daf6cc3ac2b3233e3c6770d13e371
change-id: 20240208-spl-logging-14a1257c3147

Best regards,
-- 
Thomas Weißschuh <thomas.weisssc...@linutronix.de>

Reply via email to