Beispiel #1
0
static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
    IscsiLun *iscsilun = bs->opaque;
    int status;

    switch (req) {
    case SG_GET_VERSION_NUM:
        *(int *)buf = 30000;
        break;
    case SG_GET_SCSI_ID:
        ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type;
        break;
    case SG_IO:
        status = -EINPROGRESS;
        iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);

        while (status == -EINPROGRESS) {
            qemu_aio_wait();
        }

        return 0;
    default:
        return -1;
    }
    return 0;
}
Beispiel #2
0
static int do_co_write_zeroes(int64_t offset, int count, int *total)
{
    Coroutine *co;
    CoWriteZeroes data = {
        .offset = offset,
        .count  = count,
        .total  = total,
        .done   = false,
    };

    co = qemu_coroutine_create(co_write_zeroes_entry);
    qemu_coroutine_enter(co, &data);
    while (!data.done) {
        qemu_aio_wait();
    }
    if (data.ret < 0) {
        return data.ret;
    } else {
        return 1;
    }
}

static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
{
    int ret;

    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
    if (ret < 0) {
        return ret;
    }
    *total = count;
    return 1;
}
static int do_co_write_zeroes(int64_t offset, int count, int *total)
{
    Coroutine *co;
    CoWriteZeroes data = {
        .offset = offset,
        .count  = count,
        .total  = total,
        .done   = false,
    };

    co = qemu_coroutine_create(co_write_zeroes_entry);
    qemu_coroutine_enter(co, &data);
    while (!data.done) {
        qemu_aio_wait();
    }
    if (data.ret < 0) {
        return data.ret;
    } else {
        return 1;
    }
}

static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
{
    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
    if (*total < 0) {
        return *total;
    }
    return 1;
}
Beispiel #4
0
static int wait_break_f(int argc, char **argv)
{
    while (!bdrv_debug_is_suspended(bs, argv[1])) {
        qemu_aio_wait();
    }

    return 0;
}
Beispiel #5
0
static void qemu_gluster_aio_cancel(BlockDriverAIOCB *blockacb)
{
    GlusterAIOCB *acb = (GlusterAIOCB *)blockacb;
    bool finished = false;

    acb->finished = &finished;
    while (!finished) {
        qemu_aio_wait();
    }
}
Beispiel #6
0
int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset)
{
    int ret = -EINPROGRESS;

    qed_read_l2_table(s, request, offset, qed_sync_cb, &ret);
    while (ret == -EINPROGRESS) {
        qemu_aio_wait();
    }

    return ret;
}
Beispiel #7
0
static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
{
    BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb;
    bool finished = false;

    /* Wait until request completes, invokes its callback, and frees itself */
    acb->finished = &finished;
    while (!finished) {
        qemu_aio_wait();
    }
}
Beispiel #8
0
static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
{
    QEDAIOCB *acb = (QEDAIOCB *)blockacb;
    bool finished = false;

    /* Wait for the request to finish */
    acb->finished = &finished;
    while (!finished) {
        qemu_aio_wait();
    }
}
Beispiel #9
0
/*
 * Cancel aio. Since we don't reference acb in a non qemu threads,
 * it is safe to access it here.
 */
static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
{
    RBDAIOCB *acb = (RBDAIOCB *) blockacb;
    acb->cancelled = 1;

    while (acb->status == -EINPROGRESS) {
        qemu_aio_wait();
    }

    qemu_aio_release(acb);
}
Beispiel #10
0
int qed_read_l1_table_sync(BDRVQEDState *s)
{
    int ret = -EINPROGRESS;

    qed_read_table(s, s->header.l1_table_offset,
                   s->l1_table, qed_sync_cb, &ret);
    while (ret == -EINPROGRESS) {
        qemu_aio_wait();
    }

    return ret;
}
Beispiel #11
0
int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
                            unsigned int index, unsigned int n, bool flush)
{
    int ret = -EINPROGRESS;

    qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret);
    while (ret == -EINPROGRESS) {
        qemu_aio_wait();
    }

    return ret;
}
Beispiel #12
0
int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
                            unsigned int n)
{
    int ret = -EINPROGRESS;

    qed_write_l1_table(s, index, n, qed_sync_cb, &ret);
    while (ret == -EINPROGRESS) {
        qemu_aio_wait();
    }

    return ret;
}
static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
{
    int async_ret = NOT_DONE;

    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
                    aio_rw_done, &async_ret);
    while (async_ret == NOT_DONE) {
        qemu_aio_wait();
    }

    *total = qiov->size;
    return async_ret < 0 ? async_ret : 1;
}
Beispiel #14
0
static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
{
    int i, ret;
    struct multiwrite_async_ret async_ret = {
        .num_done = 0,
        .error = 0,
    };

    *total = 0;
    for (i = 0; i < num_reqs; i++) {
        reqs[i].cb = multiwrite_cb;
        reqs[i].opaque = &async_ret;
        *total += reqs[i].qiov->size;
    }

    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
    if (ret < 0) {
        return ret;
    }

    while (async_ret.num_done < num_reqs) {
        qemu_aio_wait();
    }

    return async_ret.error < 0 ? async_ret.error : 1;
}

static void
read_help(void)
{
    printf(
        "\n"
        " reads a range of bytes from the given offset\n"
        "\n"
        " Example:\n"
        " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
        "\n"
        " Reads a segment of the currently open file, optionally dumping it to the\n"
        " standard output stream (with -v option) for subsequent inspection.\n"
        " -b, -- read from the VM state rather than the virtual disk\n"
        " -C, -- report statistics in a machine parsable format\n"
        " -l, -- length for pattern verification (only with -P)\n"
        " -p, -- use bdrv_pread to read the file\n"
        " -P, -- use a pattern to verify read data\n"
        " -q, -- quite mode, do not show I/O statistics\n"
        " -s, -- start offset for pattern verification (only with -P)\n"
        " -v, -- dump buffer to standard output\n"
        "\n");
}
Beispiel #15
0
static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
{
    BlockDriverAIOCB *acb;
    int async_ret = NOT_DONE;

    acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
                          aio_rw_done, &async_ret);
    if (!acb)
        return -EIO;

    while (async_ret == NOT_DONE)
        qemu_aio_wait();

    *total = qiov->size;
    return async_ret < 0 ? async_ret : 1;
}
Beispiel #16
0
static void
iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
{
    IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
    IscsiLun *iscsilun = acb->iscsilun;

    if (acb->status != -EINPROGRESS) {
        return;
    }

    acb->canceled = 1;

    /* send a task mgmt call to the target to cancel the task on the target */
    iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
                                     iscsi_abort_task_cb, acb);

    while (acb->status == -EINPROGRESS) {
        qemu_aio_wait();
    }
}
Beispiel #17
0
int block_job_cancel_sync(BlockJob *job)
{
    struct BlockCancelData data;
    BlockDriverState *bs = job->bs;

    assert(bs->job == job);

    /* Set up our own callback to store the result and chain to
     * the original callback.
     */
    data.job = job;
    data.cb = job->cb;
    data.opaque = job->opaque;
    data.ret = -EINPROGRESS;
    job->cb = block_job_cancel_cb;
    job->opaque = &data;
    block_job_cancel(job);
    while (data.ret == -EINPROGRESS) {
        qemu_aio_wait();
    }
    return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
}
Beispiel #18
0
/* A non-blocking poll of the main AIO context (we cannot use aio_poll
 * because we do not know the AioContext).
 */
static void qemu_aio_wait_nonblocking(void)
{
    qemu_notify_event();
    qemu_aio_wait();
}
Beispiel #19
0
/* Wait until all aio and bh activity has finished */
static void qemu_aio_wait_all(void)
{
    while (qemu_aio_wait()) {
        /* Do nothing */
    }
}
Beispiel #20
0
/*
 * We support iscsi url's on the form
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
 */
static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = NULL;
    struct iscsi_url *iscsi_url = NULL;
    struct IscsiTask task;
    char *initiator_name = NULL;
    int ret;

    if ((BDRV_SECTOR_SIZE % 512) != 0) {
        error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
                     "BDRV_SECTOR_SIZE(%lld) is not a multiple "
                     "of 512", BDRV_SECTOR_SIZE);
        return -EINVAL;
    }

    iscsi_url = iscsi_parse_full_url(iscsi, filename);
    if (iscsi_url == NULL) {
        error_report("Failed to parse URL : %s %s", filename,
                     iscsi_get_error(iscsi));
        ret = -EINVAL;
        goto failed;
    }

    memset(iscsilun, 0, sizeof(IscsiLun));

    initiator_name = parse_initiator_name(iscsi_url->target);

    iscsi = iscsi_create_context(initiator_name);
    if (iscsi == NULL) {
        error_report("iSCSI: Failed to create iSCSI context.");
        ret = -ENOMEM;
        goto failed;
    }

    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
        error_report("iSCSI: Failed to set target name.");
        ret = -EINVAL;
        goto failed;
    }

    if (iscsi_url->user != NULL) {
        ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
                                              iscsi_url->passwd);
        if (ret != 0) {
            error_report("Failed to set initiator username and password");
            ret = -EINVAL;
            goto failed;
        }
    }

    /* check if we got CHAP username/password via the options */
    if (parse_chap(iscsi, iscsi_url->target) != 0) {
        error_report("iSCSI: Failed to set CHAP user/password");
        ret = -EINVAL;
        goto failed;
    }

    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
        error_report("iSCSI: Failed to set session type to normal.");
        ret = -EINVAL;
        goto failed;
    }

    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

    /* check if we got HEADER_DIGEST via the options */
    parse_header_digest(iscsi, iscsi_url->target);

    task.iscsilun = iscsilun;
    task.status = 0;
    task.complete = 0;
    task.bs = bs;

    iscsilun->iscsi = iscsi;
    iscsilun->lun   = iscsi_url->lun;

    if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun,
                                 iscsi_connect_cb, &task)
        != 0) {
        error_report("iSCSI: Failed to start async connect.");
        ret = -EINVAL;
        goto failed;
    }

    while (!task.complete) {
        iscsi_set_events(iscsilun);
        qemu_aio_wait();
    }
    if (task.status != 0) {
        error_report("iSCSI: Failed to connect to LUN : %s",
                     iscsi_get_error(iscsi));
        ret = -EINVAL;
        goto failed;
    }

    if (iscsi_url != NULL) {
        iscsi_destroy_url(iscsi_url);
    }
    return 0;

failed:
    if (initiator_name != NULL) {
        g_free(initiator_name);
    }
    if (iscsi_url != NULL) {
        iscsi_destroy_url(iscsi_url);
    }
    if (iscsi != NULL) {
        iscsi_destroy_context(iscsi);
    }
    memset(iscsilun, 0, sizeof(IscsiLun));
    return ret;
}
Beispiel #21
0
void command_loop(void)
{
    int c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
    char *input;
    char **v;
    const cmdinfo_t *ct;

    for (i = 0; !done && i < ncmdline; i++) {
        input = strdup(cmdline[i]);
        if (!input) {
            fprintf(stderr, _("cannot strdup command '%s': %s\n"),
                    cmdline[i], strerror(errno));
            exit(1);
        }
        v = breakline(input, &c);
        if (c) {
            ct = find_command(v[0]);
            if (ct) {
                if (ct->flags & CMD_FLAG_GLOBAL) {
                    done = command(ct, c, v);
                } else {
                    j = 0;
                    while (!done && (j = args_command(j))) {
                        done = command(ct, c, v);
                    }
                }
            } else {
                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
            }
	}
        doneline(input, v);
    }
    if (cmdline) {
        g_free(cmdline);
        return;
    }

    while (!done) {
        if (!prompted) {
            printf("%s", get_prompt());
            fflush(stdout);
            qemu_aio_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, NULL,
                                    NULL, &fetchable);
            prompted = 1;
        }

        qemu_aio_wait();

        if (!fetchable) {
            continue;
        }
        input = fetchline();
        if (input == NULL) {
            break;
        }
        v = breakline(input, &c);
        if (c) {
            ct = find_command(v[0]);
            if (ct) {
                done = command(ct, c, v);
            } else {
                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
            }
        }
        doneline(input, v);

        prompted = 0;
        fetchable = 0;
    }
    qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
}