Commit 195ed8cb authored by Stefan Hajnoczi's avatar Stefan Hajnoczi
Browse files

qemu/queue.h: add QLIST_SAFE_REMOVE()



QLIST_REMOVE() assumes the element is in a list.  It also leaves the
element's linked list pointers dangling.

Introduce a safe version of QLIST_REMOVE() and convert open-coded
instances of this pattern.

Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: default avatarSergio Lopez <slp@redhat.com>
Message-id: 20200214171712.541358-4-stefanha@redhat.com
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent ca8c6b22
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -2636,10 +2636,7 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,

static void bdrv_detach_child(BdrvChild *child)
{
    if (child->next.le_prev) {
        QLIST_REMOVE(child, next);
        child->next.le_prev = NULL;
    }
    QLIST_SAFE_REMOVE(child, next);

    bdrv_replace_child(child, NULL);

+1 −3
Original line number Diff line number Diff line
@@ -216,9 +216,7 @@ static void char_spice_finalize(Object *obj)

    vmc_unregister_interface(s);

    if (s->next.le_prev) {
        QLIST_REMOVE(s, next);
    }
    QLIST_SAFE_REMOVE(s, next);

    g_free((char *)s->sin.subtype);
    g_free((char *)s->sin.portname);
+14 −0
Original line number Diff line number Diff line
@@ -144,6 +144,20 @@ struct { \
        *(elm)->field.le_prev = (elm)->field.le_next;                   \
} while (/*CONSTCOND*/0)

/*
 * Like QLIST_REMOVE() but safe to call when elm is not in a list
 */
#define QLIST_SAFE_REMOVE(elm, field) do {                              \
        if ((elm)->field.le_prev != NULL) {                             \
                if ((elm)->field.le_next != NULL)                       \
                        (elm)->field.le_next->field.le_prev =           \
                            (elm)->field.le_prev;                       \
                *(elm)->field.le_prev = (elm)->field.le_next;           \
                (elm)->field.le_next = NULL;                            \
                (elm)->field.le_prev = NULL;                            \
        }                                                               \
} while (/*CONSTCOND*/0)

#define QLIST_FOREACH(var, head, field)                                 \
        for ((var) = ((head)->lh_first);                                \
                (var);                                                  \