]> Git Repo - qemu.git/blobdiff - block/archipelago.c
iotests: Send the correct fd in socket_scm_helper
[qemu.git] / block / archipelago.c
index 6629d03a1dfb98339563f621286c72b3b51fc3b0..40e5f76ae66c88ddfd3954cac505c3010968e0ad 100644 (file)
 #include "qapi/qmp/qint.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/qmp/qjson.h"
+#include "qemu/atomic.h"
 
 #include <inttypes.h>
 #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"
@@ -83,6 +82,7 @@ typedef enum {
     ARCHIP_OP_WRITE,
     ARCHIP_OP_FLUSH,
     ARCHIP_OP_VOLINFO,
+    ARCHIP_OP_TRUNCATE,
 } ARCHIPCmd;
 
 typedef struct ArchipelagoAIOCB {
@@ -214,7 +214,7 @@ static void xseg_request_handler(void *state)
 
                 xseg_put_request(s->xseg, req, s->srcport);
 
-                if ((__sync_add_and_fetch(&segreq->ref, -1)) == 0) {
+                if (atomic_fetch_dec(&segreq->ref) == 1) {
                     if (!segreq->failed) {
                         reqdata->aio_cb->ret = segreq->count;
                         archipelago_finish_aiocb(reqdata);
@@ -233,7 +233,7 @@ static void xseg_request_handler(void *state)
                 segreq->count += req->serviced;
                 xseg_put_request(s->xseg, req, s->srcport);
 
-                if ((__sync_add_and_fetch(&segreq->ref, -1)) == 0) {
+                if (atomic_fetch_dec(&segreq->ref) == 1) {
                     if (!segreq->failed) {
                         reqdata->aio_cb->ret = segreq->count;
                         archipelago_finish_aiocb(reqdata);
@@ -247,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;
@@ -750,7 +751,7 @@ static int archipelago_submit_request(BDRVArchipelagoState *s,
     char *target;
     void *data = NULL;
     struct xseg_request *req;
-    AIORequestData *reqdata = g_malloc(sizeof(AIORequestData));
+    AIORequestData *reqdata = g_new(AIORequestData, 1);
 
     targetlen = strlen(s->volname);
     req = xseg_get_request(s->xseg, s->srcport, s->vportno, X_ALLOC);
@@ -824,78 +825,47 @@ static int archipelago_aio_segmented_rw(BDRVArchipelagoState *s,
                                         ArchipelagoAIOCB *aio_cb,
                                         int op)
 {
-    int i, ret, segments_nr, last_segment_size;
+    int ret, segments_nr;
+    size_t pos = 0;
     ArchipelagoSegmentedRequest *segreq;
 
-    segreq = g_malloc(sizeof(ArchipelagoSegmentedRequest));
+    segreq = g_new0(ArchipelagoSegmentedRequest, 1);
 
     if (op == ARCHIP_OP_FLUSH) {
         segments_nr = 1;
-        segreq->ref = segments_nr;
-        segreq->total = count;
-        segreq->count = 0;
-        segreq->failed = 0;
-        ret = archipelago_submit_request(s, 0, count, offset, aio_cb,
-                                           segreq, ARCHIP_OP_FLUSH);
-        if (ret < 0) {
-            goto err_exit;
-        }
-        return 0;
+    } else {
+        segments_nr = (int)(count / MAX_REQUEST_SIZE) + \
+                      ((count % MAX_REQUEST_SIZE) ? 1 : 0);
     }
-
-    segments_nr = (int)(count / MAX_REQUEST_SIZE) + \
-                  ((count % MAX_REQUEST_SIZE) ? 1 : 0);
-    last_segment_size = (int)(count % MAX_REQUEST_SIZE);
-
-    segreq->ref = segments_nr;
     segreq->total = count;
-    segreq->count = 0;
-    segreq->failed = 0;
+    atomic_mb_set(&segreq->ref, segments_nr);
 
-    for (i = 0; i < segments_nr - 1; i++) {
-        ret = archipelago_submit_request(s, i * MAX_REQUEST_SIZE,
-                                           MAX_REQUEST_SIZE,
-                                           offset + i * MAX_REQUEST_SIZE,
-                                           aio_cb, segreq, op);
+    while (segments_nr > 1) {
+        ret = archipelago_submit_request(s, pos,
+                                            MAX_REQUEST_SIZE,
+                                            offset + pos,
+                                            aio_cb, segreq, op);
 
         if (ret < 0) {
             goto err_exit;
         }
+        count -= MAX_REQUEST_SIZE;
+        pos += MAX_REQUEST_SIZE;
+        segments_nr--;
     }
-
-    if ((segments_nr > 1) && last_segment_size) {
-        ret = archipelago_submit_request(s, i * MAX_REQUEST_SIZE,
-                                           last_segment_size,
-                                           offset + i * MAX_REQUEST_SIZE,
-                                           aio_cb, segreq, op);
-    } else if ((segments_nr > 1) && !last_segment_size) {
-        ret = archipelago_submit_request(s, i * MAX_REQUEST_SIZE,
-                                           MAX_REQUEST_SIZE,
-                                           offset + i * MAX_REQUEST_SIZE,
-                                           aio_cb, segreq, op);
-    } else if (segments_nr == 1) {
-            ret = archipelago_submit_request(s, 0, count, offset, aio_cb,
-                                               segreq, op);
-    }
+    ret = archipelago_submit_request(s, pos, count, offset + pos,
+                                     aio_cb, segreq, op);
 
     if (ret < 0) {
         goto err_exit;
     }
-
     return 0;
 
 err_exit:
-    __sync_add_and_fetch(&segreq->failed, 1);
-    if (segments_nr == 1) {
-        if (__sync_add_and_fetch(&segreq->ref, -1) == 0) {
-            g_free(segreq);
-        }
-    } else {
-        if ((__sync_add_and_fetch(&segreq->ref, -segments_nr + i)) == 0) {
-            g_free(segreq);
-        }
+    segreq->failed = 1;
+    if (atomic_fetch_sub(&segreq->ref, segments_nr) == segments_nr) {
+        g_free(segreq);
     }
-
     return ret;
 }
 
@@ -960,7 +930,7 @@ static int64_t archipelago_volume_info(BDRVArchipelagoState *s)
     int ret, targetlen;
     struct xseg_request *req;
     struct xseg_reply_info *xinfo;
-    AIORequestData *reqdata = g_malloc(sizeof(AIORequestData));
+    AIORequestData *reqdata = g_new(AIORequestData, 1);
 
     const char *volname = s->volname;
     targetlen = strlen(volname);
@@ -1025,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),
@@ -1054,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,
This page took 0.028094 seconds and 4 git commands to generate.