diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/archipelago.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/block/archipelago.c b/block/archipelago.c index 22a7daaa41..40e5f76ae6 100644 --- a/block/archipelago.c +++ b/block/archipelago.c @@ -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, |