/*
 * Copyright (c) 2021-2024 Oracle and/or its affiliates.
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/vfio/vfio-device.h"
#include "migration/cpr.h"
#include "migration/misc.h"
#include "migration/options.h"
#include "migration/qemu-file.h"
#include "migration/savevm.h"
#include "migration/vmstate.h"
#include "monitor/monitor.h"
#include "system/runstate.h"
#include "trace.h"

/*************************************************************************/
/* cpr state container for all information to be saved. */

CprState cpr_state;

/****************************************************************************/

typedef struct CprFd {
    char *name;
    unsigned int namelen;
    int id;
    int fd;
    QLIST_ENTRY(CprFd) next;
} CprFd;

static const VMStateDescription vmstate_cpr_fd = {
    .name = "cpr fd",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(namelen, CprFd),
        VMSTATE_VBUFFER_ALLOC_UINT32(name, CprFd, 0, NULL, namelen),
        VMSTATE_INT32(id, CprFd),
        VMSTATE_FD(fd, CprFd),
        VMSTATE_END_OF_LIST()
    }
};

void cpr_save_fd(const char *name, int id, int fd)
{
    CprFd *elem = g_new0(CprFd, 1);

    trace_cpr_save_fd(name, id, fd);
    elem->name = g_strdup(name);
    elem->namelen = strlen(name) + 1;
    elem->id = id;
    elem->fd = fd;
    QLIST_INSERT_HEAD(&cpr_state.fds, elem, next);
}

static CprFd *find_fd(CprFdList *head, const char *name, int id)
{
    CprFd *elem;

    QLIST_FOREACH(elem, head, next) {
        if (!strcmp(elem->name, name) && elem->id == id) {
            return elem;
        }
    }
    return NULL;
}

void cpr_delete_fd(const char *name, int id)
{
    CprFd *elem = find_fd(&cpr_state.fds, name, id);

    if (elem) {
        QLIST_REMOVE(elem, next);
        g_free(elem->name);
        g_free(elem);
    }

    trace_cpr_delete_fd(name, id);
}

int cpr_find_fd(const char *name, int id)
{
    CprFd *elem = find_fd(&cpr_state.fds, name, id);
    int fd = elem ? elem->fd : -1;

    trace_cpr_find_fd(name, id, fd);
    return fd;
}

void cpr_resave_fd(const char *name, int id, int fd)
{
    CprFd *elem = find_fd(&cpr_state.fds, name, id);
    int old_fd = elem ? elem->fd : -1;

    if (old_fd < 0) {
        cpr_save_fd(name, id, fd);
    } else if (old_fd != fd) {
        error_setg(&error_fatal,
                   "internal error: cpr fd '%s' id %d value %d "
                   "already saved with a different value %d",
                   name, id, fd, old_fd);
    }
}

int cpr_open_fd(const char *path, int flags, const char *name, int id,
                Error **errp)
{
    int fd = cpr_find_fd(name, id);

    if (fd < 0) {
        fd = qemu_open(path, flags, errp);
        if (fd >= 0) {
            cpr_save_fd(name, id, fd);
        }
    }
    return fd;
}

/*************************************************************************/
static const VMStateDescription vmstate_cpr_state = {
    .name = CPR_STATE,
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_QLIST_V(fds, CprState, 1, vmstate_cpr_fd, CprFd, next),
        VMSTATE_END_OF_LIST()
    },
    .subsections = (const VMStateDescription * const []) {
        &vmstate_cpr_vfio_devices,
        NULL
    }
};
/*************************************************************************/

static QEMUFile *cpr_state_file;

QIOChannel *cpr_state_ioc(void)
{
    return qemu_file_get_ioc(cpr_state_file);
}

static MigMode incoming_mode = MIG_MODE_NONE;

MigMode cpr_get_incoming_mode(void)
{
    return incoming_mode;
}

void cpr_set_incoming_mode(MigMode mode)
{
    incoming_mode = mode;
}

bool cpr_is_incoming(void)
{
    return incoming_mode != MIG_MODE_NONE;
}

int cpr_state_save(MigrationChannel *channel, Error **errp)
{
    int ret;
    QEMUFile *f;
    MigMode mode = migrate_mode();

    trace_cpr_state_save(MigMode_str(mode));

    if (mode == MIG_MODE_CPR_TRANSFER) {
        g_assert(channel);
        f = cpr_transfer_output(channel, errp);
    } else {
        return 0;
    }
    if (!f) {
        return -1;
    }

    qemu_put_be32(f, QEMU_CPR_FILE_MAGIC);
    qemu_put_be32(f, QEMU_CPR_FILE_VERSION);

    ret = vmstate_save_state(f, &vmstate_cpr_state, &cpr_state, 0);
    if (ret) {
        error_setg(errp, "vmstate_save_state error %d", ret);
        qemu_fclose(f);
        return ret;
    }

    /*
     * Close the socket only partially so we can later detect when the other
     * end closes by getting a HUP event.
     */
    qemu_fflush(f);
    qio_channel_shutdown(qemu_file_get_ioc(f), QIO_CHANNEL_SHUTDOWN_WRITE,
                         NULL);
    cpr_state_file = f;
    return 0;
}

int cpr_state_load(MigrationChannel *channel, Error **errp)
{
    int ret;
    uint32_t v;
    QEMUFile *f;
    MigMode mode = 0;

    if (channel) {
        mode = MIG_MODE_CPR_TRANSFER;
        cpr_set_incoming_mode(mode);
        f = cpr_transfer_input(channel, errp);
    } else {
        return 0;
    }
    if (!f) {
        return -1;
    }

    trace_cpr_state_load(MigMode_str(mode));

    v = qemu_get_be32(f);
    if (v != QEMU_CPR_FILE_MAGIC) {
        error_setg(errp, "Not a migration stream (bad magic %x)", v);
        qemu_fclose(f);
        return -EINVAL;
    }
    v = qemu_get_be32(f);
    if (v != QEMU_CPR_FILE_VERSION) {
        error_setg(errp, "Unsupported migration stream version %d", v);
        qemu_fclose(f);
        return -ENOTSUP;
    }

    ret = vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1);
    if (ret) {
        error_setg(errp, "vmstate_load_state error %d", ret);
        qemu_fclose(f);
        return ret;
    }

    /*
     * Let the caller decide when to close the socket (and generate a HUP event
     * for the sending side).
     */
    cpr_state_file = f;

    return ret;
}

void cpr_state_close(void)
{
    if (cpr_state_file) {
        qemu_fclose(cpr_state_file);
        cpr_state_file = NULL;
    }
}

bool cpr_incoming_needed(void *opaque)
{
    MigMode mode = migrate_mode();
    return mode == MIG_MODE_CPR_TRANSFER;
}

/*
 * cpr_get_fd_param: find a descriptor and return its value.
 *
 * @name: CPR name for the descriptor
 * @fdname: An integer-valued string, or a name passed to a getfd command
 * @index: CPR index of the descriptor
 * @errp: returned error message
 *
 * If CPR is not being performed, then use @fdname to find the fd.
 * If CPR is being performed, then ignore @fdname, and look for @name
 * and @index in CPR state.
 *
 * On success returns the fd value, else returns -1.
 */
int cpr_get_fd_param(const char *name, const char *fdname, int index,
                     Error **errp)
{
    ERRP_GUARD();
    int fd;

    if (cpr_is_incoming()) {
        fd = cpr_find_fd(name, index);
        if (fd < 0) {
            error_setg(errp, "cannot find saved value for fd %s", fdname);
        }
    } else {
        fd = monitor_fd_param(monitor_cur(), fdname, errp);
        if (fd >= 0) {
            cpr_save_fd(name, index, fd);
        } else {
            error_prepend(errp, "Could not parse object fd %s:", fdname);
        }
    }
    return fd;
}
