static int raw_reopen_prepare(BDRVReopenState *state,

                              BlockReopenQueue *queue, Error **errp)

{

    BDRVRawState *s;

    BDRVRawReopenState *raw_s;

    int ret = 0;

    Error *local_err = NULL;



    assert(state != NULL);

    assert(state->bs != NULL);



    s = state->bs->opaque;



    state->opaque = g_new0(BDRVRawReopenState, 1);

    raw_s = state->opaque;



#ifdef CONFIG_LINUX_AIO

    raw_s->use_aio = s->use_aio;



    /* we can use s->aio_ctx instead of a copy, because the use_aio flag is

     * valid in the 'false' condition even if aio_ctx is set, and raw_set_aio()

     * won't override aio_ctx if aio_ctx is non-NULL */

    if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) {

        error_setg(errp, "Could not set AIO state");

        return -1;

    }

#endif



    if (s->type == FTYPE_FD || s->type == FTYPE_CD) {

        raw_s->open_flags |= O_NONBLOCK;

    }



    raw_parse_flags(state->flags, &raw_s->open_flags);



    raw_s->fd = -1;



    int fcntl_flags = O_APPEND | O_NONBLOCK;

#ifdef O_NOATIME

    fcntl_flags |= O_NOATIME;

#endif



#ifdef O_ASYNC

    /* Not all operating systems have O_ASYNC, and those that don't

     * will not let us track the state into raw_s->open_flags (typically

     * you achieve the same effect with an ioctl, for example I_SETSIG

     * on Solaris). But we do not use O_ASYNC, so that's fine.

     */

    assert((s->open_flags & O_ASYNC) == 0);

#endif



    if ((raw_s->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) {

        /* dup the original fd */

        /* TODO: use qemu fcntl wrapper */

#ifdef F_DUPFD_CLOEXEC

        raw_s->fd = fcntl(s->fd, F_DUPFD_CLOEXEC, 0);

#else

        raw_s->fd = dup(s->fd);

        if (raw_s->fd != -1) {

            qemu_set_cloexec(raw_s->fd);

        }

#endif

        if (raw_s->fd >= 0) {

            ret = fcntl_setfl(raw_s->fd, raw_s->open_flags);

            if (ret) {

                qemu_close(raw_s->fd);

                raw_s->fd = -1;

            }

        }

    }



    /* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */

    if (raw_s->fd == -1) {

        assert(!(raw_s->open_flags & O_CREAT));

        raw_s->fd = qemu_open(state->bs->filename, raw_s->open_flags);

        if (raw_s->fd == -1) {

            error_setg_errno(errp, errno, "Could not reopen file");

            ret = -1;

        }

    }



    /* Fail already reopen_prepare() if we can't get a working O_DIRECT

     * alignment with the new fd. */

    if (raw_s->fd != -1) {

        raw_probe_alignment(state->bs, raw_s->fd, &local_err);

        if (local_err) {

            qemu_close(raw_s->fd);

            raw_s->fd = -1;

            error_propagate(errp, local_err);

            ret = -EINVAL;

        }

    }



    return ret;

}
