[libvirt] [PATCH] add compress stream support

use libarchive for compressed stream support Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru> --- configure.ac | 11 ++++++-- include/libvirt/libvirt-stream.h | 6 +++++ m4/virt-archive.m4 | 26 +++++++++++++++++++ src/fdstream.c | 47 +++++++++++++++++++++++++++++++++ src/libvirt-stream.c | 56 +++++++++++++++++++++++++++++++++++++++- src/libvirt_public.syms | 7 +++++ 6 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 m4/virt-archive.m4 diff --git a/configure.ac b/configure.ac index 03463b0..4018b49 100644 --- a/configure.ac +++ b/configure.ac @@ -250,6 +250,7 @@ LIBVIRT_CHECK_SANLOCK LIBVIRT_CHECK_SASL LIBVIRT_CHECK_SELINUX LIBVIRT_CHECK_SSH2 +LIBVIRT_CHECK_LIBARCHIVE LIBVIRT_CHECK_SYSTEMD_DAEMON LIBVIRT_CHECK_UDEV LIBVIRT_CHECK_WIRESHARK @@ -1603,8 +1604,6 @@ fi AC_SUBST([LIBPCAP_CFLAGS]) AC_SUBST([LIBPCAP_LIBS]) - - dnl dnl Checks for the UML driver dnl @@ -2097,6 +2096,13 @@ AM_CONDITIONAL([WITH_STORAGE_DISK], [test "$with_storage_disk" = "yes"]) AC_SUBST([LIBPARTED_CFLAGS]) AC_SUBST([LIBPARTED_LIBS]) +if test "$with_libarchive" = "yes" || test "$with_libarchive" = "check"; then + PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.1.2], [], [LIBARCHIVE_FOUND=no]) +fi +AC_SUBST([LIBARCHIVE_CFLAGS]) +AC_SUBST([LIBARCHIVE_LIBS]) + + if test "$with_storage_mpath" = "yes" || test "$with_storage_disk" = "yes"; then DEVMAPPER_CFLAGS= @@ -2892,6 +2898,7 @@ LIBVIRT_RESULT_SANLOCK LIBVIRT_RESULT_SASL LIBVIRT_RESULT_SELINUX LIBVIRT_RESULT_SSH2 +LIBVIRT_RESULT_LIBARCHIVE LIBVIRT_RESULT_SYSTEMD_DAEMON LIBVIRT_RESULT_UDEV LIBVIRT_RESULT_WIRESHARK diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h index 831640d..ac48fba 100644 --- a/include/libvirt/libvirt-stream.h +++ b/include/libvirt/libvirt-stream.h @@ -35,6 +35,12 @@ typedef enum { virStreamPtr virStreamNew(virConnectPtr conn, unsigned int flags); +virStreamPtr virStreamNewLz4(virConnectPtr conn, + unsigned int flags); +virStreamPtr virStreamNewGzip(virConnectPtr conn, + unsigned int flags); +virStreamPtr virStreamNewXz(virConnectPtr conn, + unsigned int flags); int virStreamRef(virStreamPtr st); int virStreamSend(virStreamPtr st, diff --git a/m4/virt-archive.m4 b/m4/virt-archive.m4 new file mode 100644 index 0000000..b550c41 --- /dev/null +++ b/m4/virt-archive.m4 @@ -0,0 +1,26 @@ +dnl The libarchive.so library +dnl +dnl Copyright (C) 2012-2013 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl <http://www.gnu.org/licenses/>. +dnl + +AC_DEFUN([LIBVIRT_CHECK_LIBARCHIVE],[ + LIBVIRT_CHECK_PKG([LIBARCHIVE], [libarchive], [3.1.2]) +]) + +AC_DEFUN([LIBVIRT_RESULT_LIBARCHIVE],[ + LIBVIRT_RESULT_LIB([LIBARCHIVE]) +]) diff --git a/src/fdstream.c b/src/fdstream.c index b8ea86e..82f0e8c 100644 --- a/src/fdstream.c +++ b/src/fdstream.c @@ -33,6 +33,10 @@ #include <netinet/in.h> #include <termios.h> +#ifdef WITH_LIBARCHIVE +# include <archive.h> +#endif + #include "fdstream.h" #include "virerror.h" #include "datatypes.h" @@ -75,6 +79,9 @@ struct virFDStreamData { void *icbOpaque; virMutex lock; +#ifdef WITH_LIBARCHIVE + void *archive; +#endif }; @@ -319,6 +326,12 @@ virFDStreamCloseInt(virStreamPtr st, bool streamAbort) if (VIR_CLOSE(fdst->errfd) < 0) VIR_DEBUG("ignoring failed close on fd %d", fdst->errfd); +#ifdef WITH_LIBARCHIVE + if (fdst->archive != NULL) { + archive_write_free(fdst->archive); + archive_read_free(fdst->archive); + } +#endif st->privateData = NULL; /* call the internal stream closing callback */ @@ -385,7 +398,16 @@ static int virFDStreamWrite(virStreamPtr st, const char *bytes, size_t nbytes) } retry: +#ifdef WITH_LIBARCHIVE + if (fdst->archive != NULL) { + archive_write_open_fd(fdst->archive, fdst->fd); + ret = archive_write_data(fdst->archive, bytes, nbytes); + } else { + ret = write(fdst->fd, bytes, nbytes); + } +#else ret = write(fdst->fd, bytes, nbytes); +#endif if (ret < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { ret = -2; @@ -397,7 +419,15 @@ static int virFDStreamWrite(virStreamPtr st, const char *bytes, size_t nbytes) _("cannot write to stream")); } } else if (fdst->length) { +#ifdef WITH_LIBARCHIVE + if (fdst->archive != NULL) { + fdst->offset += nbytes; + } else { + fdst->offset += ret; + } +#else fdst->offset += ret; +#endif } virMutexUnlock(&fdst->lock); @@ -435,7 +465,16 @@ static int virFDStreamRead(virStreamPtr st, char *bytes, size_t nbytes) } retry: +#ifdef WITH_LIBARCHIVE + if (fdst->archive != NULL) { + archive_read_open_fd(fdst->archive, fdst->fd, 4096); + ret = archive_read_data(fdst->archive, bytes, nbytes); + } else { + ret = read(fdst->fd, bytes, nbytes); + } +#else ret = read(fdst->fd, bytes, nbytes); +#endif if (ret < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { ret = -2; @@ -447,7 +486,15 @@ static int virFDStreamRead(virStreamPtr st, char *bytes, size_t nbytes) _("cannot read from stream")); } } else if (fdst->length) { +#ifdef WITH_LIBARCHIVE + if (fdst->archive != NULL) { + fdst->offset += nbytes; + } else { + fdst->offset += ret; + } +#else fdst->offset += ret; +#endif } virMutexUnlock(&fdst->lock); diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c index c16f586..40702dc 100644 --- a/src/libvirt-stream.c +++ b/src/libvirt-stream.c @@ -23,12 +23,16 @@ #include "datatypes.h" #include "viralloc.h" #include "virlog.h" +#include "fdstream.h" + +#include <archive.h> + +struct virFDStreamData; VIR_LOG_INIT("libvirt.stream"); #define VIR_FROM_THIS VIR_FROM_STREAMS - /** * virStreamNew: * @conn: pointer to the connection @@ -69,6 +73,56 @@ virStreamNew(virConnectPtr conn, return st; } +virStreamPtr +virStreamNewLz4(virConnectPtr conn, + unsigned int flags) +{ + virStreamPtr st; + + st = virStreamNew(conn, flags); + if (st != NULL) { + struct virFDStreamData *fdst = st->privateData; + fdst->archive = archive_write_new(); + archive_write_add_filter(fdst->archive, ARCHIVE_FILTER_LZ4); + } + + return st; +} + +virStreamPtr +virStreamNewGzip(virConnectPtr conn, + unsigned int flags) +{ + virStreamPtr st; + + st = virStreamNew(conn, flags); + if (st != NULL) { + struct virFDStreamData *fdst = st->privateData; + fdst->archive = archive_write_new(); + archive_write_add_filter(fdst->archive, ARCHIVE_FILTER_GZIP); + } + + return st; +} + + +virStreamPtr +virStreamNewXz(virConnectPtr conn, + unsigned int flags) +{ + virStreamPtr st; + + st = virStreamNew(conn, flags); + if (st != NULL) { + struct virFDStreamData *fdst = st->privateData; + fdst->archive = archive_write_new(); + archive_write_add_filter(fdst->archive, ARCHIVE_FILTER_XZ); + } + + return st; +} + + /** * virStreamRef: diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index dd94191..46519ce 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -725,4 +725,11 @@ LIBVIRT_1.2.19 { virDomainRename; } LIBVIRT_1.2.17; +LIBVIRT_1.2.20 { + global: + virStreamNewLz4; + virStreamNewGzip; + virStreamNewXz; +} LIBVIRT_1.2.19; + # .... define new API here using predicted next version number .... -- 2.5.0

2015-09-22 17:10 GMT+03:00 Vasiliy Tolstov <v.tolstov@selfip.ru>:
use libarchive for compressed stream support
Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
this is test patch, because libvirt not build with this - struct virFDStreamData is internally used by fdstream.c, but i need to acces private data from libvirt-stream.c via virStreamNewLz4 and so. Can somebody helps me and say, how the best to integrate compressed stream support to libvirt? I plan to use this stream when upload/download volume via libvirt. -- Vasiliy Tolstov, e-mail: v.tolstov@selfip.ru

On Tue, Sep 22, 2015 at 02:10:41PM +0000, Vasiliy Tolstov wrote:
use libarchive for compressed stream support
Can you explain a bit more about how you expect this to be used ?
Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru> --- configure.ac | 11 ++++++-- include/libvirt/libvirt-stream.h | 6 +++++ m4/virt-archive.m4 | 26 +++++++++++++++++++ src/fdstream.c | 47 +++++++++++++++++++++++++++++++++ src/libvirt-stream.c | 56 +++++++++++++++++++++++++++++++++++++++- src/libvirt_public.syms | 7 +++++ 6 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 m4/virt-archive.m4
diff --git a/configure.ac b/configure.ac index 03463b0..4018b49 100644 --- a/configure.ac +++ b/configure.ac @@ -250,6 +250,7 @@ LIBVIRT_CHECK_SANLOCK LIBVIRT_CHECK_SASL LIBVIRT_CHECK_SELINUX LIBVIRT_CHECK_SSH2 +LIBVIRT_CHECK_LIBARCHIVE
This does all the pkg-config checks for libarchive...
@@ -1603,8 +1604,6 @@ fi AC_SUBST([LIBPCAP_CFLAGS]) AC_SUBST([LIBPCAP_LIBS])
- -
Avoid changing unrelated lines please
dnl dnl Checks for the UML driver dnl @@ -2097,6 +2096,13 @@ AM_CONDITIONAL([WITH_STORAGE_DISK], [test "$with_storage_disk" = "yes"]) AC_SUBST([LIBPARTED_CFLAGS]) AC_SUBST([LIBPARTED_LIBS])
+if test "$with_libarchive" = "yes" || test "$with_libarchive" = "check"; then + PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.1.2], [], [LIBARCHIVE_FOUND=no]) +fi +AC_SUBST([LIBARCHIVE_CFLAGS]) +AC_SUBST([LIBARCHIVE_LIBS])
...this is redundant given LIBVIRT_CHECK_LIBARCHIVE earlier.
if test "$with_storage_mpath" = "yes" || test "$with_storage_disk" = "yes"; then DEVMAPPER_CFLAGS= diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h index 831640d..ac48fba 100644 --- a/include/libvirt/libvirt-stream.h +++ b/include/libvirt/libvirt-stream.h @@ -35,6 +35,12 @@ typedef enum {
virStreamPtr virStreamNew(virConnectPtr conn, unsigned int flags); +virStreamPtr virStreamNewLz4(virConnectPtr conn, + unsigned int flags); +virStreamPtr virStreamNewGzip(virConnectPtr conn, + unsigned int flags); +virStreamPtr virStreamNewXz(virConnectPtr conn, + unsigned int flags);
If we want to expose this in the public API, then we'd really want an enum for each archive format, so we don't need to keep adding new APIs for each format.
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c index c16f586..40702dc 100644 --- a/src/libvirt-stream.c +++ b/src/libvirt-stream.c @@ -69,6 +73,56 @@ virStreamNew(virConnectPtr conn, return st; }
+virStreamPtr +virStreamNewLz4(virConnectPtr conn, + unsigned int flags) +{ + virStreamPtr st; + + st = virStreamNew(conn, flags); + if (st != NULL) { + struct virFDStreamData *fdst = st->privateData;
This is not valid. You can't assume anything about what st->privateData is pointing to - it can be anything that a virt driver wants to use. For example with the remote driver it can point to a virNetClientStreamPtr instead instead of virFDStreamData.
+ fdst->archive = archive_write_new(); + archive_write_add_filter(fdst->archive, ARCHIVE_FILTER_LZ4); + } + + return st; +}
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

2015-09-22 18:29 GMT+03:00 Daniel P. Berrange <berrange@redhat.com>:
On Tue, Sep 22, 2015 at 02:10:41PM +0000, Vasiliy Tolstov wrote:
use libarchive for compressed stream support
Can you explain a bit more about how you expect this to be used ?
Thanks for all suggestions. I'm send new version. -- Vasiliy Tolstov, e-mail: v.tolstov@selfip.ru
participants (2)
-
Daniel P. Berrange
-
Vasiliy Tolstov