]> git.proxmox.com Git - qemu.git/blobdiff - block/sheepdog.c
VMDK: open/read/write for monolithicFlat image
[qemu.git] / block / sheepdog.c
index 2180299bddb6612b8621c2df58184280d46546f0..77a4de5100c5d393618eea079c7efc862802e561 100644 (file)
@@ -444,7 +444,7 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
 static int sd_schedule_bh(QEMUBHFunc *cb, SheepdogAIOCB *acb)
 {
     if (acb->bh) {
-        error_report("bug: %d %d\n", acb->aiocb_type, acb->aiocb_type);
+        error_report("bug: %d %d", acb->aiocb_type, acb->aiocb_type);
         return -EIO;
     }
 
@@ -592,7 +592,7 @@ static int connect_to_sdog(const char *addr, const char *port)
 
     ret = getaddrinfo(addr, port, &hints, &res0);
     if (ret) {
-        error_report("unable to get address info %s, %s\n",
+        error_report("unable to get address info %s, %s",
                      addr, strerror(errno));
         return -1;
     }
@@ -622,7 +622,7 @@ static int connect_to_sdog(const char *addr, const char *port)
         goto success;
     }
     fd = -1;
-    error_report("failed connect to %s:%s\n", addr, port);
+    error_report("failed connect to %s:%s", addr, port);
 success:
     freeaddrinfo(res0);
     return fd;
@@ -638,7 +638,7 @@ again:
         if (errno == EINTR || errno == EAGAIN) {
             goto again;
         }
-        error_report("failed to recv a rsp, %s\n", strerror(errno));
+        error_report("failed to recv a rsp, %s", strerror(errno));
         return 1;
     }
 
@@ -697,7 +697,7 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data,
 
     ret = do_writev(sockfd, iov, sizeof(*hdr) + *wlen, 0);
     if (ret) {
-        error_report("failed to send a req, %s\n", strerror(errno));
+        error_report("failed to send a req, %s", strerror(errno));
         ret = -1;
     }
 
@@ -717,7 +717,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
 
     ret = do_read(sockfd, hdr, sizeof(*hdr));
     if (ret) {
-        error_report("failed to get a rsp, %s\n", strerror(errno));
+        error_report("failed to get a rsp, %s", strerror(errno));
         ret = -1;
         goto out;
     }
@@ -729,7 +729,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
     if (*rlen) {
         ret = do_read(sockfd, data, *rlen);
         if (ret) {
-            error_report("failed to get the data, %s\n", strerror(errno));
+            error_report("failed to get the data, %s", strerror(errno));
             ret = -1;
             goto out;
         }
@@ -766,7 +766,7 @@ static void send_pending_req(BDRVSheepdogState *s, uint64_t oid, uint32_t id)
         ret = add_aio_request(s, aio_req, acb->qiov->iov,
                               acb->qiov->niov, 0, acb->aiocb_type);
         if (ret < 0) {
-            error_report("add_aio_request is failed\n");
+            error_report("add_aio_request is failed");
             free_aio_req(s, aio_req);
             if (QLIST_EMPTY(&acb->aioreq_head)) {
                 sd_finish_aiocb(acb);
@@ -799,7 +799,7 @@ static void aio_read_response(void *opaque)
     /* read a header */
     ret = do_read(fd, &rsp, sizeof(rsp));
     if (ret) {
-        error_report("failed to get the header, %s\n", strerror(errno));
+        error_report("failed to get the header, %s", strerror(errno));
         return;
     }
 
@@ -810,7 +810,7 @@ static void aio_read_response(void *opaque)
         }
     }
     if (!aio_req) {
-        error_report("cannot find aio_req %x\n", rsp.id);
+        error_report("cannot find aio_req %x", rsp.id);
         return;
     }
 
@@ -846,7 +846,7 @@ static void aio_read_response(void *opaque)
         ret = do_readv(fd, acb->qiov->iov, rsp.data_length,
                        aio_req->iov_offset);
         if (ret) {
-            error_report("failed to get the data, %s\n", strerror(errno));
+            error_report("failed to get the data, %s", strerror(errno));
             return;
         }
         break;
@@ -854,7 +854,7 @@ static void aio_read_response(void *opaque)
 
     if (rsp.result != SD_RES_SUCCESS) {
         acb->ret = -EIO;
-        error_report("%s\n", sd_strerror(rsp.result));
+        error_report("%s", sd_strerror(rsp.result));
     }
 
     rest = free_aio_req(s, aio_req);
@@ -911,7 +911,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        error_report("%s\n", strerror(errno));
+        error_report("%s", strerror(errno));
         return -1;
     }
 
@@ -919,7 +919,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
 
     ret = set_nodelay(fd);
     if (ret) {
-        error_report("%s\n", strerror(errno));
+        error_report("%s", strerror(errno));
         closesocket(fd);
         return -1;
     }
@@ -1035,7 +1035,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
     }
 
     if (rsp->result != SD_RES_SUCCESS) {
-        error_report("cannot get vdi info, %s, %s %d %s\n",
+        error_report("cannot get vdi info, %s, %s %d %s",
                      sd_strerror(rsp->result), filename, snapid, tag);
         ret = -1;
         goto out;
@@ -1063,7 +1063,7 @@ static int add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
     uint64_t old_oid = aio_req->base_oid;
 
     if (!nr_copies) {
-        error_report("bug\n");
+        error_report("bug");
     }
 
     memset(&hdr, 0, sizeof(hdr));
@@ -1096,14 +1096,14 @@ static int add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
     /* send a header */
     ret = do_write(s->fd, &hdr, sizeof(hdr));
     if (ret) {
-        error_report("failed to send a req, %s\n", strerror(errno));
+        error_report("failed to send a req, %s", strerror(errno));
         return -EIO;
     }
 
     if (wlen) {
         ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset);
         if (ret) {
-            error_report("failed to send a data, %s\n", strerror(errno));
+            error_report("failed to send a data, %s", strerror(errno));
             return -EIO;
         }
     }
@@ -1145,7 +1145,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
 
     ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
     if (ret) {
-        error_report("failed to send a request to the sheep\n");
+        error_report("failed to send a request to the sheep");
         return -1;
     }
 
@@ -1153,7 +1153,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
     case SD_RES_SUCCESS:
         return 0;
     default:
-        error_report("%s\n", sd_strerror(rsp->result));
+        error_report("%s", sd_strerror(rsp->result));
         return -1;
     }
 }
@@ -1206,7 +1206,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        error_report("failed to connect\n");
+        error_report("failed to connect");
         goto out;
     }
 
@@ -1275,7 +1275,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
     }
 
     if (rsp->result != SD_RES_SUCCESS) {
-        error_report("%s, %s\n", sd_strerror(rsp->result), filename);
+        error_report("%s, %s", sd_strerror(rsp->result), filename);
         return -EIO;
     }
 
@@ -1286,6 +1286,49 @@ static int do_sd_create(char *filename, int64_t vdi_size,
     return 0;
 }
 
+static int sd_prealloc(const char *filename)
+{
+    BlockDriverState *bs = NULL;
+    uint32_t idx, max_idx;
+    int64_t vdi_size;
+    void *buf = qemu_mallocz(SD_DATA_OBJ_SIZE);
+    int ret;
+
+    ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
+    if (ret < 0) {
+        goto out;
+    }
+
+    vdi_size = bdrv_getlength(bs);
+    if (vdi_size < 0) {
+        ret = vdi_size;
+        goto out;
+    }
+    max_idx = DIV_ROUND_UP(vdi_size, SD_DATA_OBJ_SIZE);
+
+    for (idx = 0; idx < max_idx; idx++) {
+        /*
+         * The created image can be a cloned image, so we need to read
+         * a data from the source image.
+         */
+        ret = bdrv_pread(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
+        if (ret < 0) {
+            goto out;
+        }
+        ret = bdrv_pwrite(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
+        if (ret < 0) {
+            goto out;
+        }
+    }
+out:
+    if (bs) {
+        bdrv_delete(bs);
+    }
+    qemu_free(buf);
+
+    return ret;
+}
+
 static int sd_create(const char *filename, QEMUOptionParameter *options)
 {
     int ret;
@@ -1295,14 +1338,16 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
     BDRVSheepdogState s;
     char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
     uint32_t snapid;
+    int prealloc = 0;
+    const char *vdiname;
 
-    strstart(filename, "sheepdog:", (const char **)&filename);
+    strstart(filename, "sheepdog:", &vdiname);
 
     memset(&s, 0, sizeof(s));
     memset(vdi, 0, sizeof(vdi));
     memset(tag, 0, sizeof(tag));
-    if (parse_vdiname(&s, filename, vdi, &snapid, tag) < 0) {
-        error_report("invalid filename\n");
+    if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) {
+        error_report("invalid filename");
         return -EINVAL;
     }
 
@@ -1311,12 +1356,22 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
             vdi_size = options->value.n;
         } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
             backing_file = options->value.s;
+        } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
+            if (!options->value.s || !strcmp(options->value.s, "off")) {
+                prealloc = 0;
+            } else if (!strcmp(options->value.s, "full")) {
+                prealloc = 1;
+            } else {
+                error_report("Invalid preallocation mode: '%s'",
+                             options->value.s);
+                return -EINVAL;
+            }
         }
         options++;
     }
 
     if (vdi_size > SD_MAX_VDI_SIZE) {
-        error_report("too big image size\n");
+        error_report("too big image size");
         return -EINVAL;
     }
 
@@ -1328,7 +1383,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
         /* Currently, only Sheepdog backing image is supported. */
         drv = bdrv_find_protocol(backing_file);
         if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
-            error_report("backing_file must be a sheepdog image\n");
+            error_report("backing_file must be a sheepdog image");
             return -EINVAL;
         }
 
@@ -1339,7 +1394,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
         s = bs->opaque;
 
         if (!is_snapshot(&s->inode)) {
-            error_report("cannot clone from a non snapshot vdi\n");
+            error_report("cannot clone from a non snapshot vdi");
             bdrv_delete(bs);
             return -EINVAL;
         }
@@ -1348,7 +1403,12 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
         bdrv_delete(bs);
     }
 
-    return do_sd_create((char *)vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
+    ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
+    if (!prealloc || ret) {
+        return ret;
+    }
+
+    return sd_prealloc(filename);
 }
 
 static void sd_close(BlockDriverState *bs)
@@ -1379,7 +1439,7 @@ static void sd_close(BlockDriverState *bs)
 
     if (!ret && rsp->result != SD_RES_SUCCESS &&
         rsp->result != SD_RES_VDI_NOT_LOCKED) {
-        error_report("%s, %s\n", sd_strerror(rsp->result), s->name);
+        error_report("%s, %s", sd_strerror(rsp->result), s->name);
     }
 
     qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL, NULL);
@@ -1401,10 +1461,10 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
     unsigned int datalen;
 
     if (offset < s->inode.vdi_size) {
-        error_report("shrinking is not supported\n");
+        error_report("shrinking is not supported");
         return -EINVAL;
     } else if (offset > SD_MAX_VDI_SIZE) {
-        error_report("too big image size\n");
+        error_report("too big image size");
         return -EINVAL;
     }
 
@@ -1421,7 +1481,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
     close(fd);
 
     if (ret < 0) {
-        error_report("failed to update an inode.\n");
+        error_report("failed to update an inode.");
         return -EIO;
     }
 
@@ -1494,7 +1554,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        error_report("failed to connect\n");
+        error_report("failed to connect");
         goto out;
     }
 
@@ -1612,7 +1672,7 @@ static void sd_readv_writev_bh_cb(void *p)
         ret = add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
                               create, acb->aiocb_type);
         if (ret < 0) {
-            error_report("add_aio_request is failed\n");
+            error_report("add_aio_request is failed");
             free_aio_req(s, aio_req);
             acb->ret = -EIO;
             goto out;
@@ -1689,7 +1749,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
 
     if (s->is_snapshot) {
         error_report("You can't create a snapshot of a snapshot VDI, "
-                     "%s (%" PRIu32 ").\n", s->name, s->inode.vdi_id);
+                     "%s (%" PRIu32 ").", s->name, s->inode.vdi_id);
 
         return -EINVAL;
     }
@@ -1712,7 +1772,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
                        s->inode.nr_copies, datalen, 0, 0);
     if (ret < 0) {
-        error_report("failed to write snapshot's inode.\n");
+        error_report("failed to write snapshot's inode.");
         ret = -EIO;
         goto cleanup;
     }
@@ -1720,7 +1780,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     ret = do_sd_create(s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid, 1,
                        s->addr, s->port);
     if (ret < 0) {
-        error_report("failed to create inode for snapshot. %s\n",
+        error_report("failed to create inode for snapshot. %s",
                      strerror(errno));
         ret = -EIO;
         goto cleanup;
@@ -1732,7 +1792,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
                       s->inode.nr_copies, datalen, 0);
 
     if (ret < 0) {
-        error_report("failed to read new inode info. %s\n", strerror(errno));
+        error_report("failed to read new inode info. %s", strerror(errno));
         ret = -EIO;
         goto cleanup;
     }
@@ -1771,14 +1831,14 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 
     ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
     if (ret) {
-        error_report("Failed to find_vdi_name\n");
+        error_report("Failed to find_vdi_name");
         ret = -ENOENT;
         goto out;
     }
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        error_report("failed to connect\n");
+        error_report("failed to connect");
         goto out;
     }
 
@@ -1796,7 +1856,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     memcpy(&s->inode, buf, sizeof(s->inode));
 
     if (!s->inode.vm_state_size) {
-        error_report("Invalid snapshot\n");
+        error_report("Invalid snapshot");
         ret = -ENOENT;
         goto out;
     }
@@ -1813,7 +1873,7 @@ out:
     qemu_free(buf);
     qemu_free(old_s);
 
-    error_report("failed to open. recover old bdrv_sd_state.\n");
+    error_report("failed to open. recover old bdrv_sd_state.");
 
     return ret;
 }
@@ -1868,7 +1928,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        error_report("failed to connect\n");
+        error_report("failed to connect");
         goto out;
     }
 
@@ -1942,7 +2002,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
         }
 
         if (ret < 0) {
-            error_report("failed to save vmstate %s\n", strerror(errno));
+            error_report("failed to save vmstate %s", strerror(errno));
             ret = -EIO;
             goto cleanup;
         }
@@ -1984,6 +2044,11 @@ static QEMUOptionParameter sd_create_options[] = {
         .type = OPT_STRING,
         .help = "File name of a base image"
     },
+    {
+        .name = BLOCK_OPT_PREALLOC,
+        .type = OPT_STRING,
+        .help = "Preallocation mode (allowed values: off, full)"
+    },
     { NULL }
 };