Commit 94c80a43 authored by Chrysostomos Nanakos's avatar Chrysostomos Nanakos Committed by Kevin Wolf
Browse files

block/archipelago: Implement bdrv_truncate()

parent 5366d0c8
Loading
Loading
Loading
Loading
+61 −2
Original line number Diff line number Diff line
@@ -63,8 +63,6 @@
#include <xseg/xseg.h>
#include <xseg/protocol.h>

#define ARCHIP_FD_READ      0
#define ARCHIP_FD_WRITE     1
#define MAX_REQUEST_SIZE    524288

#define ARCHIPELAGO_OPT_VOLUME      "volume"
@@ -84,6 +82,7 @@ typedef enum {
    ARCHIP_OP_WRITE,
    ARCHIP_OP_FLUSH,
    ARCHIP_OP_VOLINFO,
    ARCHIP_OP_TRUNCATE,
} ARCHIPCmd;

typedef struct ArchipelagoAIOCB {
@@ -248,6 +247,7 @@ static void xseg_request_handler(void *state)
                }
                break;
            case ARCHIP_OP_VOLINFO:
            case ARCHIP_OP_TRUNCATE:
                s->is_signaled = true;
                qemu_cond_signal(&s->archip_cond);
                break;
@@ -995,6 +995,64 @@ static int64_t qemu_archipelago_getlength(BlockDriverState *bs)
    return ret;
}

static int qemu_archipelago_truncate(BlockDriverState *bs, int64_t offset)
{
    int ret, targetlen;
    struct xseg_request *req;
    BDRVArchipelagoState *s = bs->opaque;
    AIORequestData *reqdata = g_new(AIORequestData, 1);

    const char *volname = s->volname;
    targetlen = strlen(volname);
    req = xseg_get_request(s->xseg, s->srcport, s->mportno, X_ALLOC);
    if (!req) {
        archipelagolog("Cannot get XSEG request\n");
        return err_exit2;
    }

    ret = xseg_prep_request(s->xseg, req, targetlen, 0);
    if (ret < 0) {
        archipelagolog("Cannot prepare XSEG request\n");
        goto err_exit;
    }
    char *target = xseg_get_target(s->xseg, req);
    if (!target) {
        archipelagolog("Cannot get XSEG target\n");
        goto err_exit;
    }
    memcpy(target, volname, targetlen);
    req->offset = offset;
    req->op = X_TRUNCATE;

    reqdata->op = ARCHIP_OP_TRUNCATE;
    reqdata->volname = volname;

    xseg_set_req_data(s->xseg, req, reqdata);

    xport p = xseg_submit(s->xseg, req, s->srcport, X_ALLOC);
    if (p == NoPort) {
        archipelagolog("Cannot submit XSEG request\n");
        goto err_exit;
    }

    xseg_signal(s->xseg, p);
    qemu_mutex_lock(&s->archip_mutex);
    while (!s->is_signaled) {
        qemu_cond_wait(&s->archip_cond, &s->archip_mutex);
    }
    s->is_signaled = false;
    qemu_mutex_unlock(&s->archip_mutex);
    xseg_put_request(s->xseg, req, s->srcport);
    g_free(reqdata);
    return 0;

err_exit:
    xseg_put_request(s->xseg, req, s->srcport);
err_exit2:
    g_free(reqdata);
    return -EIO;
}

static QemuOptsList qemu_archipelago_create_opts = {
    .name = "archipelago-create-opts",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_archipelago_create_opts.head),
@@ -1024,6 +1082,7 @@ static BlockDriver bdrv_archipelago = {
    .bdrv_close          = qemu_archipelago_close,
    .bdrv_create         = qemu_archipelago_create,
    .bdrv_getlength      = qemu_archipelago_getlength,
    .bdrv_truncate       = qemu_archipelago_truncate,
    .bdrv_aio_readv      = qemu_archipelago_aio_readv,
    .bdrv_aio_writev     = qemu_archipelago_aio_writev,
    .bdrv_aio_flush      = qemu_archipelago_aio_flush,