提交 7823e256 编写于 作者: M Michal Privoznik

virsh: Implement sparse stream to vol-upload

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: NMichal Privoznik <mprivozn@redhat.com>
上级 f03b44b2
...@@ -153,6 +153,35 @@ virshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED, ...@@ -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 int
virshStreamSkip(virStreamPtr st ATTRIBUTE_UNUSED, virshStreamSkip(virStreamPtr st ATTRIBUTE_UNUSED,
long long offset, long long offset,
...@@ -171,6 +200,24 @@ virshStreamSkip(virStreamPtr st ATTRIBUTE_UNUSED, ...@@ -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 void
virshDomainFree(virDomainPtr dom) virshDomainFree(virDomainPtr dom)
{ {
......
...@@ -57,11 +57,35 @@ virshStreamSink(virStreamPtr st, ...@@ -57,11 +57,35 @@ virshStreamSink(virStreamPtr st,
size_t nbytes, size_t nbytes,
void *opaque); 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 int
virshStreamSkip(virStreamPtr st, virshStreamSkip(virStreamPtr st,
long long offset, long long offset,
void *opaque); void *opaque);
int
virshStreamInData(virStreamPtr st,
int *inData,
long long *offset,
void *opaque);
int int
virshDomainGetXMLFromDom(vshControl *ctl, virshDomainGetXMLFromDom(vshControl *ctl,
virDomainPtr dom, virDomainPtr dom,
......
...@@ -660,18 +660,13 @@ static const vshCmdOptDef opts_vol_upload[] = { ...@@ -660,18 +660,13 @@ static const vshCmdOptDef opts_vol_upload[] = {
.type = VSH_OT_INT, .type = VSH_OT_INT,
.help = N_("amount of data to upload") .help = N_("amount of data to upload")
}, },
{.name = "sparse",
.type = VSH_OT_BOOL,
.help = N_("preserve sparseness of volume")
},
{.name = NULL} {.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 static bool
cmdVolUpload(vshControl *ctl, const vshCmd *cmd) cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
{ {
...@@ -683,6 +678,8 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd) ...@@ -683,6 +678,8 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
const char *name = NULL; const char *name = NULL;
unsigned long long offset = 0, length = 0; unsigned long long offset = 0, length = 0;
virshControlPtr priv = ctl->privData; virshControlPtr priv = ctl->privData;
unsigned int flags = 0;
virshStreamCallbackData cbData;
if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0) if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0)
return false; return false;
...@@ -701,19 +698,34 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd) ...@@ -701,19 +698,34 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
goto cleanup; 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))) { if (!(st = virStreamNew(priv->conn, 0))) {
vshError(ctl, _("cannot create a new stream")); vshError(ctl, _("cannot create a new stream"));
goto cleanup; 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); vshError(ctl, _("cannot upload to volume %s"), name);
goto cleanup; goto cleanup;
} }
if (virStreamSendAll(st, cmdVolUploadSource, &fd) < 0) { if (flags & VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM) {
vshError(ctl, _("cannot send data to volume %s"), name); if (virStreamSparseSendAll(st, virshStreamSource,
goto cleanup; 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) { if (VIR_CLOSE(fd) < 0) {
......
...@@ -3925,13 +3925,14 @@ the storage volume should be deleted as well. Not all storage drivers ...@@ -3925,13 +3925,14 @@ the storage volume should be deleted as well. Not all storage drivers
support this option, presently only rbd. support this option, presently only rbd.
=item B<vol-upload> [I<--pool> I<pool-or-uuid>] [I<--offset> I<bytes>] =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. 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 I<--pool> I<pool-or-uuid> is the name or UUID of the storage pool the volume
is in. is in.
I<vol-name-or-key-or-path> is the name or key or path of the volume where the I<vol-name-or-key-or-path> is the name or key or path of the volume where the
file will be uploaded. 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 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 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 of the amount of data to be uploaded. A negative value is interpreted
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册