]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virsh: Implement sparse stream to vol-upload
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 27 Apr 2016 12:21:10 +0000 (14:21 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 18 May 2017 05:42:13 +0000 (07:42 +0200)
Similarly to previous commit, implement sparse streams feature
for vol-upload. This is, however, slightly different approach,
because we must implement a function that will tell us whether
we are in a data section or in a hole. But there's no magic
hidden in here.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
tools/virsh-util.c
tools/virsh-util.h
tools/virsh-volume.c
tools/virsh.pod

index 198625bdbffbc214db833ec9060351287616337f..44be3ad64b1f60f7d801b9ae18af07d797e4da63 100644 (file)
@@ -153,6 +153,35 @@ virshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
 }
 
 
+int
+virshStreamSource(virStreamPtr st ATTRIBUTE_UNUSED,
+                  char *bytes,
+                  size_t nbytes,
+                  void *opaque)
+{
+    virshStreamCallbackDataPtr cbData = opaque;
+    int fd = cbData->fd;
+
+    return saferead(fd, bytes, nbytes);
+}
+
+
+int
+virshStreamSourceSkip(virStreamPtr st ATTRIBUTE_UNUSED,
+                      long long offset,
+                      void *opaque)
+{
+    virshStreamCallbackDataPtr cbData = opaque;
+    int fd = cbData->fd;
+    off_t cur;
+
+    if ((cur = lseek(fd, offset, SEEK_CUR)) == (off_t) -1)
+        return -1;
+
+    return 0;
+}
+
+
 int
 virshStreamSkip(virStreamPtr st ATTRIBUTE_UNUSED,
                 long long offset,
@@ -171,6 +200,24 @@ virshStreamSkip(virStreamPtr st ATTRIBUTE_UNUSED,
 }
 
 
+int
+virshStreamInData(virStreamPtr st ATTRIBUTE_UNUSED,
+                  int *inData,
+                  long long *offset,
+                  void *opaque)
+{
+    virshStreamCallbackDataPtr cbData = opaque;
+    vshControl *ctl = cbData->ctl;
+    int fd = cbData->fd;
+    int ret;
+
+    if ((ret = virFileInData(fd, inData, offset)) < 0)
+        vshError(ctl, "%s", _("Unable to get current position in stream"));
+
+    return ret;
+}
+
+
 void
 virshDomainFree(virDomainPtr dom)
 {
index 0aba247f6ee3e5a68a77b6fa7a22260cf0f2eca4..9a0af3513dd3b2201bfb2caad0efe036d63dfbd9 100644 (file)
@@ -57,11 +57,35 @@ virshStreamSink(virStreamPtr st,
                 size_t nbytes,
                 void *opaque);
 
+typedef struct _virshStreamCallbackData virshStreamCallbackData;
+typedef virshStreamCallbackData *virshStreamCallbackDataPtr;
+struct _virshStreamCallbackData {
+    vshControl *ctl;
+    int fd;
+};
+
+int
+virshStreamSource(virStreamPtr st,
+                  char *bytes,
+                  size_t nbytes,
+                  void *opaque);
+
+int
+virshStreamSourceSkip(virStreamPtr st,
+                      long long offset,
+                      void *opaque);
+
 int
 virshStreamSkip(virStreamPtr st,
                 long long offset,
                 void *opaque);
 
+int
+virshStreamInData(virStreamPtr st,
+                  int *inData,
+                  long long *offset,
+                  void *opaque);
+
 int
 virshDomainGetXMLFromDom(vshControl *ctl,
                          virDomainPtr dom,
index 3d19b745e9601ed5e364a5066c83b7a443e8c2a2..0736bdcdb2955432772e5c6b6d567619373c574f 100644 (file)
@@ -660,18 +660,13 @@ static const vshCmdOptDef opts_vol_upload[] = {
      .type = VSH_OT_INT,
      .help = N_("amount of data to upload")
     },
+    {.name = "sparse",
+     .type = VSH_OT_BOOL,
+     .help = N_("preserve sparseness of volume")
+    },
     {.name = NULL}
 };
 
-static int
-cmdVolUploadSource(virStreamPtr st ATTRIBUTE_UNUSED,
-                   char *bytes, size_t nbytes, void *opaque)
-{
-    int *fd = opaque;
-
-    return saferead(*fd, bytes, nbytes);
-}
-
 static bool
 cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
 {
@@ -683,6 +678,8 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
     const char *name = NULL;
     unsigned long long offset = 0, length = 0;
     virshControlPtr priv = ctl->privData;
+    unsigned int flags = 0;
+    virshStreamCallbackData cbData;
 
     if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0)
         return false;
@@ -701,19 +698,34 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
         goto cleanup;
     }
 
+    cbData.ctl = ctl;
+    cbData.fd = fd;
+
+    if (vshCommandOptBool(cmd, "sparse"))
+        flags |= VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM;
+
     if (!(st = virStreamNew(priv->conn, 0))) {
         vshError(ctl, _("cannot create a new stream"));
         goto cleanup;
     }
 
-    if (virStorageVolUpload(vol, st, offset, length, 0) < 0) {
+    if (virStorageVolUpload(vol, st, offset, length, flags) < 0) {
         vshError(ctl, _("cannot upload to volume %s"), name);
         goto cleanup;
     }
 
-    if (virStreamSendAll(st, cmdVolUploadSource, &fd) < 0) {
-        vshError(ctl, _("cannot send data to volume %s"), name);
-        goto cleanup;
+    if (flags & VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM) {
+        if (virStreamSparseSendAll(st, virshStreamSource,
+                                   virshStreamInData,
+                                   virshStreamSourceSkip, &cbData) < 0) {
+            vshError(ctl, _("cannot send data to volume %s"), name);
+            goto cleanup;
+        }
+    } else {
+        if (virStreamSendAll(st, virshStreamSource, &cbData) < 0) {
+            vshError(ctl, _("cannot send data to volume %s"), name);
+            goto cleanup;
+        }
     }
 
     if (VIR_CLOSE(fd) < 0) {
index 8a3ef69194f5e3a9ae086faf1ad15e9ee5513d8a..cbc08bda78ea5cdf53ba7e37c0f5fb37a9a9e6cc 100644 (file)
@@ -3925,13 +3925,14 @@ the storage volume should be deleted as well. Not all storage drivers
 support this option, presently only rbd.
 
 =item B<vol-upload> [I<--pool> I<pool-or-uuid>] [I<--offset> I<bytes>]
-[I<--length> I<bytes>] I<vol-name-or-key-or-path> I<local-file>
+[I<--length> I<bytes>] [I<--sparse>] I<vol-name-or-key-or-path> I<local-file>
 
 Upload the contents of I<local-file> to a storage volume.
 I<--pool> I<pool-or-uuid> is the name or UUID of the storage pool the volume
 is in.
 I<vol-name-or-key-or-path> is the name or key or path of the volume where the
 file will be uploaded.
+If I<--sparse> is specified, this command will preserve volume sparseness.
 I<--offset> is the position in the storage volume at which to start writing
 the data. The value must be 0 or larger. I<--length> is an upper bound
 of the amount of data to be uploaded. A negative value is interpreted