Revision 3b698f52f9fabb4fb7844f57160c65cd6ce6513c authored by Peter Maydell on 09 October 2018, 17:24:59 UTC, committed by Kevin Wolf on 05 November 2018, 14:09:54 UTC
Taking the address of a field in a packed struct is a bad idea, because
it might not be actually aligned enough for that pointer type (and
thus cause a crash on dereference on some host architectures). Newer
versions of clang warn about this. Avoid the bug by not using the
"modify in place" byte swapping functions.

There are a few places where the in-place swap function is
used on something other than a packed struct field; we convert
those anyway, for consistency.

This patch was produced with the following spatch script
(and hand-editing to fold a few resulting overlength lines):

@@
expression E;
@@
-be16_to_cpus(&E);
+E = be16_to_cpu(E);
@@
expression E;
@@
-be32_to_cpus(&E);
+E = be32_to_cpu(E);
@@
expression E;
@@
-be64_to_cpus(&E);
+E = be64_to_cpu(E);
@@
expression E;
@@
-cpu_to_be16s(&E);
+E = cpu_to_be16(E);
@@
expression E;
@@
-cpu_to_be32s(&E);
+E = cpu_to_be32(E);
@@
expression E;
@@
-cpu_to_be64s(&E);
+E = cpu_to_be64(E);

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: John Snow <jsnow@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1 parent cf67b69
Raw File
replication.h
/*
 * Replication filter
 *
 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
 * Copyright (c) 2016 Intel Corporation
 * Copyright (c) 2016 FUJITSU LIMITED
 *
 * Author:
 *   Changlong Xie <xiecl.fnst@cn.fujitsu.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#ifndef REPLICATION_H
#define REPLICATION_H

#include "qapi/qapi-types-block-core.h"
#include "qemu/queue.h"

typedef struct ReplicationOps ReplicationOps;
typedef struct ReplicationState ReplicationState;

/**
 * SECTION:replication.h
 * @title:Base Replication System
 * @short_description: interfaces for handling replication
 *
 * The Replication Model provides a framework for handling Replication
 *
 * <example>
 *   <title>How to use replication interfaces</title>
 *   <programlisting>
 * #include "replication.h"
 *
 * typedef struct BDRVReplicationState {
 *     ReplicationState *rs;
 * } BDRVReplicationState;
 *
 * static void replication_start(ReplicationState *rs, ReplicationMode mode,
 *                               Error **errp);
 * static void replication_do_checkpoint(ReplicationState *rs, Error **errp);
 * static void replication_get_error(ReplicationState *rs, Error **errp);
 * static void replication_stop(ReplicationState *rs, bool failover,
 *                              Error **errp);
 *
 * static ReplicationOps replication_ops = {
 *     .start = replication_start,
 *     .checkpoint = replication_do_checkpoint,
 *     .get_error = replication_get_error,
 *     .stop = replication_stop,
 * }
 *
 * static int replication_open(BlockDriverState *bs, QDict *options,
 *                             int flags, Error **errp)
 * {
 *     BDRVReplicationState *s = bs->opaque;
 *     s->rs = replication_new(bs, &replication_ops);
 *     return 0;
 * }
 *
 * static void replication_close(BlockDriverState *bs)
 * {
 *     BDRVReplicationState *s = bs->opaque;
 *     replication_remove(s->rs);
 * }
 *
 * BlockDriver bdrv_replication = {
 *     .format_name                = "replication",
 *     .instance_size              = sizeof(BDRVReplicationState),
 *
 *     .bdrv_open                  = replication_open,
 *     .bdrv_close                 = replication_close,
 * };
 *
 * static void bdrv_replication_init(void)
 * {
 *     bdrv_register(&bdrv_replication);
 * }
 *
 * block_init(bdrv_replication_init);
 *   </programlisting>
 * </example>
 *
 * We create an example about how to use replication interfaces in above.
 * Then in migration, we can use replication_(start/stop/do_checkpoint/
 * get_error)_all to handle all replication operations.
 */

/**
 * ReplicationState:
 * @opaque: opaque pointer value passed to this ReplicationState
 * @ops: replication operation of this ReplicationState
 * @node: node that we will insert into @replication_states QLIST
 */
struct ReplicationState {
    void *opaque;
    ReplicationOps *ops;
    QLIST_ENTRY(ReplicationState) node;
};

/**
 * ReplicationOps:
 * @start: callback to start replication
 * @stop: callback to stop replication
 * @checkpoint: callback to do checkpoint
 * @get_error: callback to check if error occurred during replication
 */
struct ReplicationOps {
    void (*start)(ReplicationState *rs, ReplicationMode mode, Error **errp);
    void (*stop)(ReplicationState *rs, bool failover, Error **errp);
    void (*checkpoint)(ReplicationState *rs, Error **errp);
    void (*get_error)(ReplicationState *rs, Error **errp);
};

/**
 * replication_new:
 * @opaque: opaque pointer value passed to ReplicationState
 * @ops: replication operation of the new relevant ReplicationState
 *
 * Called to create a new ReplicationState instance, and then insert it
 * into @replication_states QLIST
 *
 * Returns: the new ReplicationState instance
 */
ReplicationState *replication_new(void *opaque, ReplicationOps *ops);

/**
 * replication_remove:
 * @rs: the ReplicationState instance to remove
 *
 * Called to remove a ReplicationState instance, and then delete it from
 * @replication_states QLIST
 */
void replication_remove(ReplicationState *rs);

/**
 * replication_start_all:
 * @mode: replication mode that could be "primary" or "secondary"
 * @errp: returns an error if this function fails
 *
 * Start replication, called in migration/checkpoint thread
 *
 * Note: the caller of the function MUST make sure vm stopped
 */
void replication_start_all(ReplicationMode mode, Error **errp);

/**
 * replication_do_checkpoint_all:
 * @errp: returns an error if this function fails
 *
 * This interface is called after all VM state is transferred to Secondary QEMU
 */
void replication_do_checkpoint_all(Error **errp);

/**
 * replication_get_error_all:
 * @errp: returns an error if this function fails
 *
 * This interface is called to check if error occurred during replication
 */
void replication_get_error_all(Error **errp);

/**
 * replication_stop_all:
 * @failover: boolean value that indicates if we need do failover or not
 * @errp: returns an error if this function fails
 *
 * It is called on failover. The vm should be stopped before calling it, if you
 * use this API to shutdown the guest, or other things except failover
 */
void replication_stop_all(bool failover, Error **errp);

#endif /* REPLICATION_H */
back to top