Commit d746427a authored by Paolo Bonzini's avatar Paolo Bonzini Committed by Fam Zheng
Browse files

nfs: use BDRV_POLL_WHILE



This will make it possible to use nfs_get_allocated_file_size on
a file that is not in the main AioContext.

Reviewed-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: default avatarFam Zheng <famz@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Message-Id: <1477565348-5458-10-git-send-email-pbonzini@redhat.com>
Signed-off-by: default avatarFam Zheng <famz@redhat.com>
parent aa92d6c4
Loading
Loading
Loading
Loading
+28 −18
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ typedef struct NFSClient {
} NFSClient;

typedef struct NFSRPC {
    BlockDriverState *bs;
    int ret;
    int complete;
    QEMUIOVector *iov;
@@ -90,11 +91,12 @@ static void nfs_process_write(void *arg)
    nfs_set_events(client);
}

static void nfs_co_init_task(NFSClient *client, NFSRPC *task)
static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task)
{
    *task = (NFSRPC) {
        .co             = qemu_coroutine_self(),
        .client         = client,
        .bs             = bs,
        .client         = bs->opaque,
    };
}

@@ -111,6 +113,7 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
{
    NFSRPC *task = private_data;
    task->ret = ret;
    assert(!task->st);
    if (task->ret > 0 && task->iov) {
        if (task->ret <= task->iov->size) {
            qemu_iovec_from_buf(task->iov, 0, data, task->ret);
@@ -118,18 +121,11 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
            task->ret = -EIO;
        }
    }
    if (task->ret == 0 && task->st) {
        memcpy(task->st, data, sizeof(struct stat));
    }
    if (task->ret < 0) {
        error_report("NFS Error: %s", nfs_get_error(nfs));
    }
    if (task->co) {
    aio_bh_schedule_oneshot(task->client->aio_context,
                            nfs_co_generic_bh_cb, task);
    } else {
        task->complete = 1;
    }
}

static int coroutine_fn nfs_co_readv(BlockDriverState *bs,
@@ -139,7 +135,7 @@ static int coroutine_fn nfs_co_readv(BlockDriverState *bs,
    NFSClient *client = bs->opaque;
    NFSRPC task;

    nfs_co_init_task(client, &task);
    nfs_co_init_task(bs, &task);
    task.iov = iov;

    if (nfs_pread_async(client->context, client->fh,
@@ -174,7 +170,7 @@ static int coroutine_fn nfs_co_writev(BlockDriverState *bs,
    NFSRPC task;
    char *buf = NULL;

    nfs_co_init_task(client, &task);
    nfs_co_init_task(bs, &task);

    buf = g_try_malloc(nb_sectors * BDRV_SECTOR_SIZE);
    if (nb_sectors && buf == NULL) {
@@ -210,7 +206,7 @@ static int coroutine_fn nfs_co_flush(BlockDriverState *bs)
    NFSClient *client = bs->opaque;
    NFSRPC task;

    nfs_co_init_task(client, &task);
    nfs_co_init_task(bs, &task);

    if (nfs_fsync_async(client->context, client->fh, nfs_co_generic_cb,
                        &task) != 0) {
@@ -496,6 +492,21 @@ static int nfs_has_zero_init(BlockDriverState *bs)
    return client->has_zero_init;
}

static void
nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data,
                               void *private_data)
{
    NFSRPC *task = private_data;
    task->ret = ret;
    if (task->ret == 0) {
        memcpy(task->st, data, sizeof(struct stat));
    }
    if (task->ret < 0) {
        error_report("NFS Error: %s", nfs_get_error(nfs));
    }
    task->complete = 1;
}

static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
{
    NFSClient *client = bs->opaque;
@@ -507,16 +518,15 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
        return client->st_blocks * 512;
    }

    task.bs = bs;
    task.st = &st;
    if (nfs_fstat_async(client->context, client->fh, nfs_co_generic_cb,
    if (nfs_fstat_async(client->context, client->fh, nfs_get_allocated_file_size_cb,
                        &task) != 0) {
        return -ENOMEM;
    }

    nfs_set_events(client);
    while (!task.complete) {
        aio_poll(client->aio_context, true);
    }
    BDRV_POLL_WHILE(bs, !task.complete);

    return (task.ret < 0 ? task.ret : st.st_blocks * 512);
}