Re: [libvirt] [PATCH 1/1] Enable Travis CI build status icon

2017-05-16 Thread Claudio André

Em 11/05/2017 10:35, Daniel P. Berrange escreveu:

On Thu, May 11, 2017 at 03:30:00PM +0200, Martin Kletzander wrote:

On Tue, Apr 18, 2017 at 02:39:28PM -0300, Claudio André wrote:

Using GitHub libvirt site, it is possible to show Travis's fancy icon of the 
current build status. It highlights the QA process.

I like seeing the icon there.  It's very quick reference that serves the
purpose.

---
README.md | 12 
1 file changed, 12 insertions(+)
create mode 100644 README.md

diff --git a/README.md b/README.md
new file mode 100644
index 000..a609286
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+## *LibVirt: the virtualization API* [![Build 
Status](https://travis-ci.org/libvirt/libvirt.svg)](https://travis-ci.org/libvirt/libvirt)
+
I don't care about the number of (sub-)s in 'sub-heading', but why
making it italic as well?  ACK without the italic.  Will push this in a
while.  Thanks.



Ok, it was too too fancy.

BTW: since more "cryptographic" build information can be added to 
readme.md in the future, I prefer to add a new .MD file (instead of 
reuse the regular README).


Thanks


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v3 08/31] Introduce virStreamSparseRecvAll

2017-05-16 Thread John Ferlan

I was wondering why this never made it to the list - seems I just sent
it to Michal...  So here's what I sent...

John

On 05/16/2017 05:34 PM, John Ferlan wrote:
> 
> 
> On 05/16/2017 10:03 AM, Michal Privoznik wrote:
>> This is just a wrapper over new functions that have been just
>> introduced: virStreamRecvFlags(), virStreamRecvHole(). It's very
>> similar to virStreamRecvAll() except it handles sparse streams
>> well.
>>
>> Signed-off-by: Michal Privoznik 
>> ---
>>  include/libvirt/libvirt-stream.h |  33 ++-
>>  src/libvirt-stream.c | 123 
>> +++
>>  src/libvirt_public.syms  |   1 +
>>  3 files changed, 154 insertions(+), 3 deletions(-)
>>
> 
> [...]
> 
>> diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
>> index bedb6159a..6bf4c4f29 100644
>> --- a/src/libvirt-stream.c
>> +++ b/src/libvirt-stream.c
>> @@ -668,6 +668,129 @@ virStreamRecvAll(virStreamPtr stream,
>>  }
>>  
>>  
>> +/**
>> + * virStreamSparseRecvAll:
>> + * @stream: pointer to the stream object
>> + * @handler: sink callback for writing data to application
>> + * @holeHandler: stream hole callback for skipping holes
>> + * @opaque: application defined data
>> + *
>> + * Receive the entire data stream, sending the data to the
>> + * requested data sink @handler and calling the skip @holeHandler
>> + * to generate holes for sparse stream targets. This is simply a
>> + * convenient alternative to virStreamRecvFlags, for apps that do
>> + * blocking-I/O.
>> + *
>> + * An example using this with a hypothetical file download
>> + * API looks like:
>> + *
>> + *   int mysink(virStreamPtr st, const char *buf, int nbytes, void *opaque) 
>> {
>> + *   int *fd = opaque;
>> + *
>> + *   return write(*fd, buf, nbytes);
>> + *   }
>> + *
>> + *   int myskip(virStreamPtr st, long long offset, void *opaque) {
>> + *   int *fd = opaque;
>> + *
> 
> I think this is where perhaps the example of lseek in "off_t" chunks of
> "long long offset" would be applicable...  Perhaps why I ended up in the
> off_t rathole before.
> 
>> + *   return lseek(*fd, offset, SEEK_CUR) == (off_t) -1 ? -1 : 0;
>> + *   }
>> + *
>> + *   virStreamPtr st = virStreamNew(conn, 0);
>> + *   int fd = open("demo.iso", O_WRONLY);
>> + *
>> + *   virConnectDownloadSparseFile(conn, st);
> 
> ^^ This API doesn't exist...  Of course neither did
> virConnectDownloadFile from whence you copied the example.  Maybe both
> should be 'adjusted'.
> 
> 
> Reviewed-by: John Ferlan 
> 
> John
> 
>> + *   if (virStreamSparseRecvAll(st, mysink, myskip, ) < 0) {
>> + *  ...report an error ...
>> + *  goto done;
>> + *   }
>> + *   if (virStreamFinish(st) < 0)
>> + *  ...report an error...
>> + *   virStreamFree(st);
>> + *   close(fd);
>> + *
>> + * Note that @opaque data is shared between both @handler and
>> + * @holeHandler callbacks.
>> + *
>> + * Returns 0 if all the data was successfully received. The caller
>> + * should invoke virStreamFinish(st) to flush the stream upon
>> + * success and then virStreamFree(st).
>> + *
>> + * Returns -1 upon any error, with virStreamAbort() already
>> + * having been called, so the caller need only call virStreamFree().
>> + */
> 
> 
> [...]
> 

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] qemu: allow to control host side link status of network device

2017-05-16 Thread Laine Stump
On 05/16/2017 06:40 PM, Laine Stump wrote:
> On 05/16/2017 04:21 AM, Vasiliy Tolstov wrote:
>> 2017-05-16 11:16 GMT+03:00 Daniel P. Berrange :
>>> Shouldn't we just tie the host & guest link state together then. This
>>> doesn't seem like enough of a reason to introduce new XML elements.
>>
>>
>> Back to half year ago i'm already have such patch, but it reverted
>> with message :
>> link state only for guest side, for host side we need different element in 
>> xml.
>>
> 
> 
> I guess I should have been working through my backlog in reverse order.
> (I just responded to the message Vasiliy sent last week about this. At
> the time of the original discussion, I intended to send a patch to
> implement  as he's done here).
> 
> Setting an interface online/offline can have further reaching
> sonsequences than just turning carrier on and off. It also removes and
> adds routes, IP addresses, and can trigger DHCP to request a new
> address, etc. Since we have other things separated for host vs guest
> side, it makes sense to do this for the link state as well. (tying two
> functions to a single knob often leads to problems, and once they're
> tied together, they can't be untied once you discover one of those
> problems. If there are two separate options, modifying both of them may
> be a bit more verbose, but it can still be done).

Oh, and I forgot to point out here (although I did in the original
thread last fall) that a toplevel  historically only
affects the state of the interface in the guest. If it began affecting
the state of the tap device in the host as well, there would be
unexpected (and undesireable) consequences.

For example, if a tap device is attached to a bridge that has STP
enabled, and you set the tap device link state down and then back up,
the port will revert to "learning" mode, and won't begin forwarding
packets again until the STP forward delay timer has expired. Likewise,
if there is an IP address configured on the host side of the tap device
and you set link state to down, any route associated with that device
will also disappear, leading to route flapping if you have any sort of
routing protocol running.

Both of these would be undesirable side effects if, for example, all you
wanted to do was trigger the guest to renegotiate an address with dhcp
(by toggling the guest NIC's link state) (I'm sure there are other
reasons someone might want to set the guest-side link state to down for
a period without encountering the side effects I listed above, that's
just what comes to mind first.)

So even if we weren't concerned about the precendent of setting  not affecting the tap device, it still makes sense to
keep the two operations separate.

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] qemu: allow to control host side link status of network device

2017-05-16 Thread Laine Stump
On 05/16/2017 04:21 AM, Vasiliy Tolstov wrote:
> 2017-05-16 11:16 GMT+03:00 Daniel P. Berrange :
>> Shouldn't we just tie the host & guest link state together then. This
>> doesn't seem like enough of a reason to introduce new XML elements.
> 
> 
> Back to half year ago i'm already have such patch, but it reverted
> with message :
> link state only for guest side, for host side we need different element in 
> xml.
> 


I guess I should have been working through my backlog in reverse order.
(I just responded to the message Vasiliy sent last week about this. At
the time of the original discussion, I intended to send a patch to
implement  as he's done here).

Setting an interface online/offline can have further reaching
sonsequences than just turning carrier on and off. It also removes and
adds routes, IP addresses, and can trigger DHCP to request a new
address, etc. Since we have other things separated for host vs guest
side, it makes sense to do this for the link state as well. (tying two
functions to a single knob often leads to problems, and once they're
tied together, they can't be untied once you discover one of those
problems. If there are two separate options, modifying both of them may
be a bit more verbose, but it can still be done).

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] set link state for ethernet network devices

2017-05-16 Thread Laine Stump
On 05/16/2017 06:27 PM, Laine Stump wrote:
> On 05/10/2017 04:58 AM, Vasiliy Tolstov wrote:
>> Hi! Sometimes ago i'm write patch for setting link state of network
>> interface for ethernet type (tap).
>> Now i'm try libvirt 3.3.0 and see, that  tap interfaces is up but in
>> xml i'm try to specify
>> 
>> also i'm try
>> 
>> Nothing changed. Laine says, that link state is only for internal
>> representation, and to modify link state on host side i need to
>> specify .
> 
> I remember we talked about implementing that, but did we actually do it?
> I may implied/suggested that I would, and then dropped the ball (it's
> happened before :-/)

Yep :-( I looked through the thread and see that I had said I was
writing a patch to do that, but apparently I never finished it and it's
sitting somewhere on one of the dozens of "mystery branches" in my sandbox.

> 
> Definitely I did push the patch that disconnects the up/down status of
> the host side of the tap from the up/down status of the emulated NIC.
> 
>>
>> For history please check email thread "qemu: remove unnecessary
>> setting of tap device online state"
>>
>> So does this bug or it my mistake?
>> Thanks!
>>
> 
> --
> libvir-list mailing list
> libvir-list@redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
> 

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] set link state for ethernet network devices

2017-05-16 Thread Laine Stump
On 05/10/2017 04:58 AM, Vasiliy Tolstov wrote:
> Hi! Sometimes ago i'm write patch for setting link state of network
> interface for ethernet type (tap).
> Now i'm try libvirt 3.3.0 and see, that  tap interfaces is up but in
> xml i'm try to specify
> 
> also i'm try
> 
> Nothing changed. Laine says, that link state is only for internal
> representation, and to modify link state on host side i need to
> specify .

I remember we talked about implementing that, but did we actually do it?
I may implied/suggested that I would, and then dropped the ball (it's
happened before :-/)

Definitely I did push the patch that disconnects the up/down status of
the host side of the tap from the up/down status of the emulated NIC.

> 
> For history please check email thread "qemu: remove unnecessary
> setting of tap device online state"
> 
> So does this bug or it my mistake?
> Thanks!
> 

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2] qemu: Adding 'downscript' feature for QEMU network interfaces.

2017-05-16 Thread Laine Stump
On 05/05/2017 10:22 AM, Julio Faracco wrote:
> This commit adds the support for 'downscript' feature:
> - For QEMU command line with the option:
>   '-net downscript=/etc/qemu-ifdown,...'.
> 
> - For Domains with a network interface description:
>   '
>  ...
>  
>  ...
>   '
> 
> The options 'script' and 'downscript' accept the argument 'no' to disable
> the script executions. The way that the code was implemented, the XML file
> accepts '<[down]script path='no'>' to solve this problem.
> 
> This commit updates the tests and documentation too.
> 
> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=825939

I have a couple issues with this implementation:

1) the script in an interface's 

Re: [libvirt] [PATCH v3 10/31] Introduce virStreamInData

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> This is just an internal API, that calls corresponding function
> in stream driver. This function will set @data=1 if the
> underlying file is in data section, or @data=0 if it is in a
> hole. At any rate, @length is set to number of bytes remaining in
> the section the file currently is.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  src/driver-stream.h  |  6 ++
>  src/libvirt-stream.c | 48 
> 
>  src/libvirt_internal.h   |  4 
>  src/libvirt_private.syms |  1 +
>  4 files changed, 59 insertions(+)
> 

[...]

> diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
> index 4cbe5eee1..30c305035 100644
> --- a/src/libvirt-stream.c
> +++ b/src/libvirt-stream.c
> @@ -481,6 +481,54 @@ virStreamRecvHole(virStreamPtr stream,
>  }
>  
>  
> +/**
> + * virStreamInData:
> + * @stream: stream
> + * @data: are we in data or hole
> + * @length: length to next section
> + *
> + * This function checks the underlying stream (typically a file)
> + * to learn whether the current stream position lies within a
> + * data section or a hole. Upon return @data is set to a nonzero
> + * value if former is the case, or to zero if @stream is in a
> + * hole. Moreover, @length is updated to tell caller how many
> + * bytes can be read from @stream until current section changes
> + * (from data to a hole or vice versa).
> + *
> + * NB: there's an implicit hole at EOF. In this situation this
> + * function should set @data = false, @length = 0 and return 0.
> + *
> + * To sum it up:
> + *
> + * data section: @data = true,  @length > 0
> + * hole: @data = false, @length > 0
> + * EOF:  @data = false, @length = 0
> + *
> + * Returns 0 on success,
> + *-1 otherwise
> + */
> +int
> +virStreamInData(virStreamPtr stream,
> +int *data,
> +long long *length)
> +{
> +VIR_DEBUG("stream=%p, data=%p, length=%p", stream, data, length);
> +
> +/* No checks of arguments or error resetting. This is an
> + * internal function that just happen to live next to some
> + * public functions of ours. */

Well... If it's publicly accessible... @data and @length should probably
be checked for non NULL.

I looked at a couple of other "libvirt_internal.h" functions and they
have some parameter checking.

I'll put the R-b on anyway, I would suggest adding parameter checks for
non null values though. It'd be stupid user death fairly quickly
otherwise...

Reviewed-by: John Ferlan 

John

[have to stop for the evening, will pick this up again tomorrow]

[...]

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 09/31] Introduce virStreamSparseSendAll

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> This is just a wrapper over new function that have been just
> introduced: virStreamSendHole() . It's very similar to
> virStreamSendAll() except it handles sparse streams well.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  include/libvirt/libvirt-stream.h |  65 +++-
>  src/libvirt-stream.c | 159 
> +++
>  src/libvirt_public.syms  |   1 +
>  3 files changed, 222 insertions(+), 3 deletions(-)
> 

[...]

> diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
> index 6bf4c4f29..4cbe5eee1 100644
> --- a/src/libvirt-stream.c
> +++ b/src/libvirt-stream.c
> @@ -574,6 +574,165 @@ virStreamSendAll(virStreamPtr stream,
>  }
>  
>  
> +/**
> + * virStreamSparseSendAll:
> + * @stream: pointer to the stream object
> + * @handler: source callback for reading data from application
> + * @holeHandler: source callback for determining holes
> + * @skipHandler: skip holes as reported by @holeHandler
> + * @opaque: application defined data
> + *
> + * Send the entire data stream, reading the data from the
> + * requested data source. This is simply a convenient alternative
> + * to virStreamSend, for apps that do blocking-I/O.
> + *
> + * An example using this with a hypothetical file upload
> + * API looks like
> + *
> + *   int mysource(virStreamPtr st, char *buf, int nbytes, void *opaque) {
> + *   int *fd = opaque;
> + *
> + *   return read(*fd, buf, nbytes);
> + *   }
> + *
> + *   int myskip(virStreamPtr st, long long offset, void *opaque) {
> + *   int *fd = opaque;
> + *
> + *   return lseek(*fd, offset, SEEK_CUR) == (off_t) -1 ? -1 : 0;
> + *   }

Similar notations here regarding "long long" values that are being used
in/for lseek() which expects "off_t"...

> + *
> + *   int myindata(virStreamPtr st, int *inData,
> + *long long *offset, void *opaque) {
> + *   int *fd = opaque;
> + *
> + *   if (@fd in hole) {
> + *   *inData = 0;
> + *   *offset = holeSize;
> + *   } else {
> + *   *inData = 1;
> + *   *offset = dataSize;
> + *   }
> + *
> + *   return 0;
> + *   }
> + *
> + *   virStreamPtr st = virStreamNew(conn, 0);
> + *   int fd = open("demo.iso", O_RDONLY);
> + *
> + *   virConnectUploadFile(conn, st);

^^ This doesn't exist either and is a straight copy from
virStreamSendAll... Should it also have the "Sparse" though?

Reviewed-by: John Ferlan 


John

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 07/31] Introduce VIR_STREAM_RECV_STOP_AT_HOLE flag

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> Add a new flag to virStreamRecvFlags in order to handle being able to
> stop reading from the stream so that the consumer can generate a "hole"
> in stream target. Generation of a hole replaces the need to receive and
> handle a sequence of zero bytes for sparse stream targets.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  include/libvirt/libvirt-stream.h |  4 
>  src/libvirt-stream.c | 34 +-
>  2 files changed, 37 insertions(+), 1 deletion(-)
> 
> diff --git a/include/libvirt/libvirt-stream.h 
> b/include/libvirt/libvirt-stream.h
> index feaa8ad64..c4baaf7a3 100644
> --- a/include/libvirt/libvirt-stream.h
> +++ b/include/libvirt/libvirt-stream.h
> @@ -45,6 +45,10 @@ int virStreamRecv(virStreamPtr st,
>char *data,
>size_t nbytes);
>  
> +typedef enum {
> +VIR_STREAM_RECV_STOP_AT_HOLE = (1 << 0),
> +} virStreamRecvFlagsValues;
> +
>  int virStreamRecvFlags(virStreamPtr st,
> char *data,
> size_t nbytes,
> diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
> index dc0dc9ea3..bedb6159a 100644
> --- a/src/libvirt-stream.c
> +++ b/src/libvirt-stream.c
> @@ -290,7 +290,7 @@ virStreamRecv(virStreamPtr stream,
>   * @stream: pointer to the stream object
>   * @data: buffer to read into from stream
>   * @nbytes: size of @data buffer
> - * @flags: extra flags; not used yet, so callers should always pass 0
> + * @flags: bitwise-OR of virStreamRecvFlagsValues
>   *
>   * Reads a series of bytes from the stream. This method may
>   * block the calling application for an arbitrary amount
> @@ -300,6 +300,33 @@ virStreamRecv(virStreamPtr stream,
>   * @flags. Calling this function with no @flags set (equal to
>   * zero) is equivalent to calling virStreamRecv(stream, data, nbytes).
>   *
> + * If flag VIR_STREAM_RECV_STOP_AT_HOLE is set, this function
> + * will stop reading from stream if it has reached a hole. In
> + * that case, -3 is returned and virStreamRecvHole() should be
> + * called to get the hole size. An example using this flag might
> + * look like this:
> + *
> + *   while (1) {
> + * char buf[4096];
> + *
> + * int ret = virStreamRecvFlags(st, buf, len, VIR_STREAM_STOP_AT_HOLE);
> + * if (ret < 0) {
> + *   if (ret == -3) {
> + * long long len;
> + * ret = virStreamRecvHole(st, , 0);
> + * if (ret < 0) {
> + *   ...error..
> + * } else {
> + *   ...seek len bytes in target...

Do/should we care to point out that @len is a "long long" and seeking is
done in chunks of "off_t"?

Reviewed-by: John Ferlan 

John

[...]

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 06/31] Introduce virStreamRecvHole

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> This function is basically a counterpart for virStreamSendHole().
> If one side of a stream called virStreamSendHole() the other
> should call virStreamRecvHole() to get the size of the hole.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  include/libvirt/libvirt-stream.h |  4 
>  src/driver-stream.h  |  6 ++
>  src/libvirt-stream.c | 44 
> 
>  src/libvirt_public.syms  |  1 +
>  4 files changed, 55 insertions(+)
> 

Reviewed-by: John Ferlan 

John

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 05/31] Introduce virStreamSendHole

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> This API is used to tell the other side of the stream to skip
> some bytes in the stream. This can be used to create a sparse
> file on the receiving side of a stream.
> 
> It takes @length argument, which says how big the hole is. This
> skipping is done from the current point of stream. Since our
> streams are not rewindable like regular files, we don't need
> @whence argument like seek(2) has.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  include/libvirt/libvirt-stream.h |  4 +++
>  src/driver-stream.h  |  6 
>  src/libvirt-stream.c | 61 
> 
>  src/libvirt_public.syms  |  1 +
>  4 files changed, 72 insertions(+)
> 

[...]

> diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
> index 7535deb3c..a09896dcd 100644
> --- a/src/libvirt-stream.c
> +++ b/src/libvirt-stream.c
> @@ -344,6 +344,67 @@ virStreamRecvFlags(virStreamPtr stream,
>  }
>  
>  
> +/**
> + * virStreamSendHole:
> + * @stream: pointer to the stream object
> + * @length: number of bytes to skip
> + * @flags: extra flags; not used yet, so callers should always pass 0
> + *
> + * Rather than transmitting empty file space, this API directs
> + * the @stream target to create @length bytes of empty space.
> + * This API would be used when uploading or downloading sparsely
> + * populated files to avoid the needless copy of empty file
> + * space.
> + *
> + * An example using this with a hypothetical file upload API
> + * looks like:
> + *
> + *   virStream st;
> + *
> + *   while (1) {
> + * char buf[4096];
> + * size_t len;
> + * if (..in hole...) {
> + *   ..get hole size...
> + *   virStreamSendHole(st, len, 0);
> + * } else {
> + *   ...read len bytes...
> + *   virStreamSend(st, buf, len);
> + * }
> + *   }
> + *
> + * Returns 0 on success,
> + *-1 error
> + */
> +int
> +virStreamSendHole(virStreamPtr stream,
> +  long long length,
> +  unsigned int flags)
> +{
> +VIR_DEBUG("stream=%p, length=%lld flags=%x",
> +  stream, length, flags);
> +
> +virResetLastError();
> +
> +virCheckStreamReturn(stream, -1);

Perhaps some preventative programming:

virCheckNonNegativeArgGoto(length, error);

Although that would mean calling virDispatchError unless there was some
sort of virCheck*ArgReturn(length, -1)

Reviewed-by: John Ferlan 


John

[...]

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 04/31] Implement virStreamRecvFlags to some drivers

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> There are three virStreamDriver's currently supported:
> 
>  * virFDStream
>  * remote driver
>  * ESX driver
> 
> For now, backend virStreamRecvFlags support for only remote driver and
> ESX driver is sufficient. Future patches will update virFDStream.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  src/esx/esx_stream.c   | 16 +++-
>  src/remote/remote_driver.c | 21 +
>  2 files changed, 32 insertions(+), 5 deletions(-)
> 

Reviewed-by: John Ferlan 

John

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 03/31] Introduce virStreamRecvFlags

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> This patch is adding the virStreamRecvFlags as a variant to the
> virStreamRecv function in order to allow for future expansion of
> functionality for processing sparse streams using a @flags
> argument.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  include/libvirt/libvirt-stream.h |  5 
>  src/driver-stream.h  |  7 +
>  src/libvirt-stream.c | 59 
> 
>  src/libvirt_public.syms  |  5 
>  4 files changed, 76 insertions(+)
> 

Reviewed-by: John Ferlan 

John

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 02/31] util: Introduce virFileInData

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> This function takes a FD and determines whether the current
> position is in data section or in a hole. In addition to that,
> it also determines how much bytes are there remaining till the
> current section ends.
> 
> Signed-off-by: Michal Privoznik 
> ---
>  src/libvirt_private.syms |   1 +
>  src/util/virfile.c   |  82 +++
>  src/util/virfile.h   |   4 +
>  tests/virfiletest.c  | 203 
> +++
>  4 files changed, 290 insertions(+)
> 
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index bbe283529..4102a002b 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1628,6 +1628,7 @@ virFileGetHugepageSize;
>  virFileGetMountReverseSubtree;
>  virFileGetMountSubtree;
>  virFileHasSuffix;
> +virFileInData;
>  virFileIsAbsPath;
>  virFileIsDir;
>  virFileIsExecutable;
> diff --git a/src/util/virfile.c b/src/util/virfile.c
> index ea44a647c..5b10f9489 100644
> --- a/src/util/virfile.c
> +++ b/src/util/virfile.c
> @@ -3793,6 +3793,88 @@ virFileComparePaths(const char *p1, const char *p2)
>   cleanup:
>  VIR_FREE(res1);
>  VIR_FREE(res2);
> +
> +return ret;
> +}
> +
> +

Still undocumented.

I know it got discussed a few times...  I guess the odd thing I find
about "long long" is that all the stream mgmt lengths/sizes, etc. are
size_t.   You also only test for smaller values only.  Just saying...

Please just add the function description *and* why a long long is being
used here.  Also a brief summary of what's being done and of course that
lseek @cleanup:

Reviewed-by: John Ferlan 


John

> +int
> +virFileInData(int fd,
> +  int *inData,
> +  long long *length)
> +{

[...]

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3] qemu: Report shutdown event details

2017-05-16 Thread Eric Blake
On 05/16/2017 03:29 PM, Martin Kletzander wrote:
> QEMU will likely report the details of it shutting down, particularly
> whether the shutdown was initiated by the guest or host.  We should
> forward that information along, at least for shutdown events.  Reset
> has that as well, however that is not a lifecycle event and would add
> extra constants that might not be used.  It can be added later on.
> 
> Since the only way we can extend information provided to the user is
> adding event details, we might as well emit multiple events (one with
> the reason for the shutdown and keep the one for the shutdown being
> finished for clarity and compatibility).

This paragraph is now dead.

> 
> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1384007
> 
> Signed-off-by: Martin Kletzander 
> ---
> v3:
>  - don't send two events, just change the detail for the existing one

ACK

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3] qemu: Report shutdown event details

2017-05-16 Thread Martin Kletzander
QEMU will likely report the details of it shutting down, particularly
whether the shutdown was initiated by the guest or host.  We should
forward that information along, at least for shutdown events.  Reset
has that as well, however that is not a lifecycle event and would add
extra constants that might not be used.  It can be added later on.

Since the only way we can extend information provided to the user is
adding event details, we might as well emit multiple events (one with
the reason for the shutdown and keep the one for the shutdown being
finished for clarity and compatibility).

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1384007

Signed-off-by: Martin Kletzander 
---
v3:
 - don't send two events, just change the detail for the existing one

v2:
 - adapt to newer patches

This is not in qemu master yet; if ACKed it will not be pushed before
the appropriate patches hit qemu master.

 examples/object-events/event-test.c |  6 ++
 include/libvirt/libvirt-domain.h| 11 ++-
 src/qemu/qemu_monitor.c |  6 +++---
 src/qemu/qemu_monitor.h |  3 ++-
 src/qemu/qemu_monitor_json.c| 10 --
 src/qemu/qemu_process.c | 21 +++--
 tools/virsh-domain.c|  4 +++-
 7 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/examples/object-events/event-test.c 
b/examples/object-events/event-test.c
index 12690cac09ce..78d200806601 100644
--- a/examples/object-events/event-test.c
+++ b/examples/object-events/event-test.c
@@ -240,6 +240,12 @@ eventDetailToString(int event,
 case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
 return "Finished";

+case VIR_DOMAIN_EVENT_SHUTDOWN_GUEST:
+return "Guest request";
+
+case VIR_DOMAIN_EVENT_SHUTDOWN_HOST:
+return "Host request";
+
 case VIR_DOMAIN_EVENT_SHUTDOWN_LAST:
 break;
 }
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index c9e96a6c90bc..720db32f7663 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -2983,7 +2983,16 @@ typedef enum {
  * Details on the cause of a 'shutdown' lifecycle event
  */
 typedef enum {
-VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0, /* Guest finished shutdown 
sequence */
+/* Guest finished shutdown sequence */
+VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0,
+
+/* Domain finished shutting down after request from the guest itself
+ * (e.g. hardware-specific action) */
+VIR_DOMAIN_EVENT_SHUTDOWN_GUEST = 1,
+
+/* Domain finished shutting down after request from the host (e.g. killed 
by
+ * a signal) */
+VIR_DOMAIN_EVENT_SHUTDOWN_HOST = 2,

 # ifdef VIR_ENUM_SENTINELS
 VIR_DOMAIN_EVENT_SHUTDOWN_LAST
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 2148d483ed6a..a2de1a6c5bad 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1326,13 +1326,13 @@ qemuMonitorEmitEvent(qemuMonitorPtr mon, const char 
*event,


 int
-qemuMonitorEmitShutdown(qemuMonitorPtr mon)
+qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest)
 {
 int ret = -1;
-VIR_DEBUG("mon=%p", mon);
+VIR_DEBUG("mon=%p guest=%u", mon, guest);
 mon->willhangup = 1;

-QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm);
+QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm, guest);
 return ret;
 }

diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 12f98beba763..8956bf929aaa 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -130,6 +130,7 @@ typedef int 
(*qemuMonitorDomainEventCallback)(qemuMonitorPtr mon,
   void *opaque);
 typedef int (*qemuMonitorDomainShutdownCallback)(qemuMonitorPtr mon,
  virDomainObjPtr vm,
+ virTristateBool guest,
  void *opaque);
 typedef int (*qemuMonitorDomainResetCallback)(qemuMonitorPtr mon,
   virDomainObjPtr vm,
@@ -344,7 +345,7 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
 int qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
  long long seconds, unsigned int micros,
  const char *details);
-int qemuMonitorEmitShutdown(qemuMonitorPtr mon);
+int qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest);
 int qemuMonitorEmitReset(qemuMonitorPtr mon);
 int qemuMonitorEmitPowerdown(qemuMonitorPtr mon);
 int qemuMonitorEmitStop(qemuMonitorPtr mon);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 083729003ba3..757595dd7472 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -523,9 +523,15 @@ qemuMonitorJSONKeywordStringToJSON(const char *str, const 
char 

Re: [libvirt] [PATCH v3 01/31] virfdstream: Use messages instead of pipe

2017-05-16 Thread John Ferlan


On 05/16/2017 10:03 AM, Michal Privoznik wrote:
> One big downside of using the pipe to transfer the data is that
> we can really transfer just bare data. No metadata can be carried
> through unless some formatted messages are introduced. That would
> be quite painful to achieve so let's use a message queue. It's
> fairly easy to exchange info between threads now that iohelper is
> no longer used.
> 
> The reason why we cannot use the FD for plain files directly is
> that despite us setting noblock flag on the FD, any
> read()/write() blocks regardless (which is a show stopper since
> those parts of the code are run from the event loop) and poll()
> reports such FD as always readable/writable - even though the
> subsequent operation might block.
> 
> The pipe is still not gone though. It is used to signal to even

s/to even/the event/

> loop that an event occurred (e.g. data are available for reading

s/are/is   (yes, an oddity of the language)

> in the queue, or vice versa).
> 
> Signed-off-by: Michal Privoznik 
> ---
>  src/util/virfdstream.c | 402 
> ++---
>  1 file changed, 350 insertions(+), 52 deletions(-)
> 

I'm still getting a compilation error on this patch...

util/virfdstream.c: In function 'virFDStreamThread':
util/virfdstream.c:551:15: error: 'got' may be used uninitialized in
this function [-Werror=maybe-uninitialized]
 total += got;
   ^~

> diff --git a/src/util/virfdstream.c b/src/util/virfdstream.c
> index 5ce78fe58..4b42939e7 100644
> --- a/src/util/virfdstream.c
> +++ b/src/util/virfdstream.c
> @@ -49,6 +49,27 @@

[...]

> +static ssize_t
> +virFDStreamThreadDoWrite(virFDStreamDataPtr fdst,
> + const int fdin,
> + const int fdout,
> + const char *fdinname,
> + const char *fdoutname)
> +{
> +ssize_t got;

got = 0;

Fixes the compilation issue since got is only set for MSG_TYPE_DATA and
even though there is only that type, the compiler seems to somehow
believe it could be set ambiguously.

> +virFDStreamMsgPtr msg = fdst->msg;
> +bool pop = false;
> +
> +switch (msg->type) {
> +case VIR_FDSTREAM_MSG_TYPE_DATA:
> +got = safewrite(fdout,
> +msg->stream.data.buf + msg->stream.data.offset,
> +msg->stream.data.len - msg->stream.data.offset);
> +if (got < 0) {
> +virReportSystemError(errno,
> + _("Unable to write %s"),
> + fdoutname);
> +return -1;
> +}
> +
> +msg->stream.data.offset += got;
> +
> +pop = msg->stream.data.offset == msg->stream.data.len;
> +break;
> +}
> +
> +if (pop) {
> +virFDStreamMsgQueuePop(fdst, fdin, fdinname);
> +virFDStreamMsgFree(msg);
> +}
> +
> +return got;
> +}
> +
> +
>  static void
>  virFDStreamThread(void *opaque)
>  {
> @@ -304,14 +496,12 @@ virFDStreamThread(void *opaque)
>  int fdout = data->fdout;
>  char *fdoutname = data->fdoutname;
>  virFDStreamDataPtr fdst = st->privateData;
> -char *buf = NULL;
> +bool doRead = fdst->threadDoRead;

Should the fdst ref come eafter the ObjectLock(fdst) below? [1]

>  size_t buflen = 256 * 1024;
>  size_t total = 0;
>  
>  virObjectRef(fdst);
> -
> -if (VIR_ALLOC_N(buf, buflen) < 0)
> -goto error;
> +virObjectLock(fdst);

^^^ [1]

Reviewed-by: John Ferlan 


John

[...]

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2] qemu: Report shutdown event details

2017-05-16 Thread Eric Blake
On 05/16/2017 12:20 PM, Daniel P. Berrange wrote:

>>> @@ -678,6 +699,7 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon 
>>> ATTRIBUTE_UNUSED,
>>>
>>>   unlock:
>>>  virObjectUnlock(vm);
>>> +qemuDomainEventQueue(driver, pre_event);
>>>  qemuDomainEventQueue(driver, event);
>>>  virObjectUnref(cfg);
>>
>> Nice - you send the same event as always so old clients don't break, but
>> new clients can now look for the new cause.
> 
> I don't think that's right actually. IMHO, we should onyl be sending the
> new event, not the original event. These are intended to indicate state
> changes, and having two VIR_DOMAIN_EVENT_SHUTDOWN events sent with
> different details is not really representing a state change.
> 
> WRT to compatibility, clients should always expect that 'detail' may
> change or new 'detail' enum values may be added - indeed we've done
> that many many times int he past. So I don't think we need to duplicate
> the existing event

That may be my fault for causing a mis-understanding of
back-compatibility handling on my review of v1. In the past, when we've
had an event that returns a too-small struct, the only way to return
more information is to create a second event with the additional info,
then fire off both events at the same time (for the clients expecting
the old event semantics, and for new clients) - which really means two
separate RPC events.  But here, we already have sufficient lifecycle
event parameters to return details without having to add a new RPC event
(proven by the fact that you didn't have to touch src/remote at all).
So now I'm agreeing with Daniel - the fact that we have new information
means we don't need to be back-compat to older clients: they will see
the same lifecycle event they have always seen, and not care that the
cause has changed, while new clients will see a plain cause where no
information was available from older qemu, or one of the two new causes
where qemu gave it to us.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2] qemu: Report shutdown event details

2017-05-16 Thread Daniel P. Berrange
On Tue, May 16, 2017 at 12:10:23PM -0500, Eric Blake wrote:
> On 05/16/2017 08:49 AM, Martin Kletzander wrote:
> > QEMU will likely report the details of it shutting down, particularly
> > whether the shutdown was initiated by the guest or host.  We should
> > forward that information along, at least for shutdown events.  Reset
> > has that as well, however that is not a lifecycle event and would add
> > extra constants that might not be used.  It can be added later on.
> > 
> > Since the only way we can extend information provided to the user is
> > adding event details, we might as well emit multiple events (one with
> > the reason for the shutdown and keep the one for the shutdown being
> > finished for clarity and compatibility).
> > 
> > Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1384007
> > 
> > Signed-off-by: Martin Kletzander 
> > ---
> > v2:
> >  - Adapt to new message format
> > 
> > Patch in QEMU:
> > https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg03624.html
> > Applied to qapi-next: 
> > https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg03742.html
> 
> Not in qemu master yet, but should land there prior to the next libvirt
> release.
> 
> 
> > +++ b/include/libvirt/libvirt-domain.h
> > @@ -2983,7 +2983,16 @@ typedef enum {
> >   * Details on the cause of a 'shutdown' lifecycle event
> >   */
> >  typedef enum {
> > -VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0, /* Guest finished shutdown 
> > sequence */
> > +/* Guest finished shutdown sequence */
> > +VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0,
> > +
> > +/* Guest is shutting down due to request from guest (e.g. 
> > hardware-specific
> > + * action) */
> > +VIR_DOMAIN_EVENT_SHUTDOWN_GUEST = 1,
> > +
> > +/* Guest is shutting down due to request from host (e.g. killed by a
> > + * signal) */
> > +VIR_DOMAIN_EVENT_SHUTDOWN_HOST = 2,
> > 
> 
> Looks reasonable.
> 
> > +++ b/src/qemu/qemu_monitor_json.c
> > @@ -523,9 +523,15 @@ qemuMonitorJSONKeywordStringToJSON(const char *str, 
> > const char *firstkeyword)
> >  }
> > 
> > 
> > -static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, 
> > virJSONValuePtr data ATTRIBUTE_UNUSED)
> > +static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, 
> > virJSONValuePtr data)
> >  {
> > -qemuMonitorEmitShutdown(mon);
> > +bool guest = false;
> > +virTristateBool guest_initiated = VIR_TRISTATE_BOOL_ABSENT;
> > +
> > +if (virJSONValueObjectGetBoolean(data, "guest", ) == 0)
> > +guest_initiated = guest ? VIR_TRISTATE_BOOL_YES : 
> > VIR_TRISTATE_BOOL_NO;
> > +
> > +qemuMonitorEmitShutdown(mon, guest_initiated);
> 
> Yes, that uses the new qemu interface correctly.
> 
> > @@ -678,6 +699,7 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon 
> > ATTRIBUTE_UNUSED,
> > 
> >   unlock:
> >  virObjectUnlock(vm);
> > +qemuDomainEventQueue(driver, pre_event);
> >  qemuDomainEventQueue(driver, event);
> >  virObjectUnref(cfg);
> 
> Nice - you send the same event as always so old clients don't break, but
> new clients can now look for the new cause.

I don't think that's right actually. IMHO, we should onyl be sending the
new event, not the original event. These are intended to indicate state
changes, and having two VIR_DOMAIN_EVENT_SHUTDOWN events sent with
different details is not really representing a state change.

WRT to compatibility, clients should always expect that 'detail' may
change or new 'detail' enum values may be added - indeed we've done
that many many times int he past. So I don't think we need to duplicate
the existing event


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH V2] libxl: add default controllers for USB devices

2017-05-16 Thread Jim Fehlig
Anyone have a few spare minutes to review this patch? TIA!

Regards,
Jim

Jim Fehlig wrote:
> Attempting to start a domain with USB hostdevs but no USB controllers
> fails with the rather cryptic error
> 
> libxl: error: libxl_qmp.c:287:qmp_handle_error_response: received an
> error message from QMP server: Bus 'xenusb-0.0' not found
> 
> This can be fixed by creating default USB controllers. When no USB
> controllers are defined, create the number of 8 port controllers
> necessary to accommodate the number of defined USB devices.
> 
> Note that USB controllers are already created as needed in the
> domainAttachDevice code path. E.g. a USB controller will be created,
> if necessary, when attaching a USB device with
> 'virsh attach-device dom usbdev.xml'.
> 
> Signed-off-by: Jim Fehlig 
> ---
> 
> V1 here
> 
> https://www.redhat.com/archives/libvir-list/2017-April/msg00965.html
> 
> While further testing of V1 found a libvirtd segfault due to
> incorrectly using virDomainControllerInsertPreAlloced instead of
> virDomainControllerInsert.
> 
>  src/libxl/libxl_conf.c | 82 
> +++---
>  1 file changed, 71 insertions(+), 11 deletions(-)
> 
> diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
> index 56bc09719..cdf6ec9f3 100644
> --- a/src/libxl/libxl_conf.c
> +++ b/src/libxl/libxl_conf.c
> @@ -1822,34 +1822,94 @@ libxlMakeUSBController(virDomainControllerDefPtr 
> controller,
>  }
>  
>  static int
> +libxlMakeDefaultUSBControllers(virDomainDefPtr def,
> +   libxl_domain_config *d_config)
> +{
> +virDomainControllerDefPtr l_controller = NULL;
> +libxl_device_usbctrl *x_controllers = NULL;
> +size_t nusbdevs = 0;
> +size_t ncontrollers;
> +size_t i;
> +
> +for (i = 0; i < def->nhostdevs; i++) {
> +if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
> +def->hostdevs[i]->source.subsys.type == 
> VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
> +nusbdevs++;
> +}
> +
> +/* No controllers needed if there are no USB devs */
> +if (nusbdevs == 0)
> +return 0;
> +
> +/* Create USB controllers with 8 ports */
> +ncontrollers = VIR_DIV_UP(nusbdevs, 8);
> +if (VIR_ALLOC_N(x_controllers, ncontrollers) < 0)
> +return -1;
> +
> +for (i = 0; i < ncontrollers; i++) {
> +if (!(l_controller = 
> virDomainControllerDefNew(VIR_DOMAIN_CONTROLLER_TYPE_USB)))
> +goto error;
> +
> +l_controller->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2;
> +l_controller->idx = i;
> +l_controller->opts.usbopts.ports = 8;
> +
> +libxl_device_usbctrl_init(_controllers[i]);
> +
> +if (libxlMakeUSBController(l_controller, _controllers[i]) < 0)
> +goto error;
> +
> +if (virDomainControllerInsert(def, l_controller) < 0)
> +goto error;
> +
> +l_controller = NULL;
> +}
> +
> +d_config->usbctrls = x_controllers;
> +d_config->num_usbctrls = ncontrollers;
> +return 0;
> +
> + error:
> + virDomainControllerDefFree(l_controller);
> + for (i = 0; i < ncontrollers; i++)
> + libxl_device_usbctrl_dispose(_controllers[i]);
> + VIR_FREE(x_controllers);
> + return -1;
> +}
> +
> +static int
>  libxlMakeUSBControllerList(virDomainDefPtr def, libxl_domain_config 
> *d_config)
>  {
>  virDomainControllerDefPtr *l_controllers = def->controllers;
>  size_t ncontrollers = def->ncontrollers;
>  size_t nusbctrls = 0;
>  libxl_device_usbctrl *x_usbctrls;
> -size_t i;
> -
> -if (ncontrollers == 0)
> -return 0;
> -
> -if (VIR_ALLOC_N(x_usbctrls, ncontrollers) < 0)
> -return -1;
> +size_t i, j;
>  
>  for (i = 0; i < ncontrollers; i++) {
> +if (l_controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB)
> +nusbctrls++;
> +}
> +
> +if (nusbctrls == 0)
> +return libxlMakeDefaultUSBControllers(def, d_config);
> +
> +if (VIR_ALLOC_N(x_usbctrls, nusbctrls) < 0)
> +return -1;
> +
> +for (i = 0, j = 0; i < ncontrollers && j < nusbctrls; i++) {
>  if (l_controllers[i]->type != VIR_DOMAIN_CONTROLLER_TYPE_USB)
>  continue;
>  
> -libxl_device_usbctrl_init(_usbctrls[nusbctrls]);
> +libxl_device_usbctrl_init(_usbctrls[j]);
>  
>  if (libxlMakeUSBController(l_controllers[i],
> -   _usbctrls[nusbctrls]) < 0)
> +   _usbctrls[j]) < 0)
>  goto error;
>  
> -nusbctrls++;
> +j++;
>  }
>  
> -VIR_SHRINK_N(x_usbctrls, ncontrollers, ncontrollers - nusbctrls);
>  d_config->usbctrls = x_usbctrls;
>  d_config->num_usbctrls = nusbctrls;
>  

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2] qemu: Report shutdown event details

2017-05-16 Thread Eric Blake
On 05/16/2017 08:49 AM, Martin Kletzander wrote:
> QEMU will likely report the details of it shutting down, particularly
> whether the shutdown was initiated by the guest or host.  We should
> forward that information along, at least for shutdown events.  Reset
> has that as well, however that is not a lifecycle event and would add
> extra constants that might not be used.  It can be added later on.
> 
> Since the only way we can extend information provided to the user is
> adding event details, we might as well emit multiple events (one with
> the reason for the shutdown and keep the one for the shutdown being
> finished for clarity and compatibility).
> 
> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1384007
> 
> Signed-off-by: Martin Kletzander 
> ---
> v2:
>  - Adapt to new message format
> 
> Patch in QEMU:
> https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg03624.html
> Applied to qapi-next: 
> https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg03742.html

Not in qemu master yet, but should land there prior to the next libvirt
release.


> +++ b/include/libvirt/libvirt-domain.h
> @@ -2983,7 +2983,16 @@ typedef enum {
>   * Details on the cause of a 'shutdown' lifecycle event
>   */
>  typedef enum {
> -VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0, /* Guest finished shutdown 
> sequence */
> +/* Guest finished shutdown sequence */
> +VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0,
> +
> +/* Guest is shutting down due to request from guest (e.g. 
> hardware-specific
> + * action) */
> +VIR_DOMAIN_EVENT_SHUTDOWN_GUEST = 1,
> +
> +/* Guest is shutting down due to request from host (e.g. killed by a
> + * signal) */
> +VIR_DOMAIN_EVENT_SHUTDOWN_HOST = 2,
> 

Looks reasonable.

> +++ b/src/qemu/qemu_monitor_json.c
> @@ -523,9 +523,15 @@ qemuMonitorJSONKeywordStringToJSON(const char *str, 
> const char *firstkeyword)
>  }
> 
> 
> -static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, 
> virJSONValuePtr data ATTRIBUTE_UNUSED)
> +static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, 
> virJSONValuePtr data)
>  {
> -qemuMonitorEmitShutdown(mon);
> +bool guest = false;
> +virTristateBool guest_initiated = VIR_TRISTATE_BOOL_ABSENT;
> +
> +if (virJSONValueObjectGetBoolean(data, "guest", ) == 0)
> +guest_initiated = guest ? VIR_TRISTATE_BOOL_YES : 
> VIR_TRISTATE_BOOL_NO;
> +
> +qemuMonitorEmitShutdown(mon, guest_initiated);

Yes, that uses the new qemu interface correctly.

> @@ -678,6 +699,7 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon 
> ATTRIBUTE_UNUSED,
> 
>   unlock:
>  virObjectUnlock(vm);
> +qemuDomainEventQueue(driver, pre_event);
>  qemuDomainEventQueue(driver, event);
>  virObjectUnref(cfg);

Nice - you send the same event as always so old clients don't break, but
new clients can now look for the new cause.

ACK
although I'd wait until it is actually in qemu.git master before pushing
to libvirt.git

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH] virsh: add --io when attaching disks to guests

2017-05-16 Thread Gordon Messmer

Please let me know if this patch requires additional revisions.

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 3/5] hyperv: add hypervInvokeMethod

2017-05-16 Thread Matthias Bolte
2017-05-05 22:24 GMT+02:00  :
> On Tue, 2017-05-02 at 00:26 +0200, Matthias Bolte wrote:
>> 2017-04-24 20:19 GMT+02:00 Sri Ramanujam :
>> > This commit adds support for invoking methods on remote objects
>> > via hypervInvokeMethod.
>> > ---
>> >  src/hyperv/hyperv_wmi.c | 569
>> > 
>> >  src/hyperv/hyperv_wmi.h |   3 +
>> >  src/hyperv/openwsman.h  |   4 +
>> >  3 files changed, 576 insertions(+)
>> >
>> > diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
>> > index 1960c4c..deea907 100644
>> > --- a/src/hyperv/hyperv_wmi.c
>> > +++ b/src/hyperv/hyperv_wmi.c
>> > @@ -24,6 +24,7 @@
>> >   */
>> >
>> >  #include 
>> > +#include 
>> >
>> >  #include "internal.h"
>> >  #include "virerror.h"
>> > @@ -34,11 +35,14 @@
>> >  #include "hyperv_private.h"
>> >  #include "hyperv_wmi.h"
>> >  #include "virstring.h"
>> > +#include "openwsman.h"
>> > +#include "virlog.h"
>> >
>> >  #define WS_SERIALIZER_FREE_MEM_WORKS 0
>> >
>> >  #define VIR_FROM_THIS VIR_FROM_HYPERV
>> >
>> > +VIR_LOG_INIT("hyperv.hyperv_wmi");
>> >
>> >  static int
>> >  hypervGetWmiClassInfo(hypervPrivate *priv,
>> > hypervWmiClassInfoListPtr list,
>> > @@ -406,6 +410,571 @@
>> > hypervAddEmbeddedParam(hypervInvokeParamsListPtr params,
>> > hypervPrivate *priv,
>> >  }
>> >
>> >
>> > +/*
>> > + * Serializing parameters to XML and invoking methods
>> > + */
>> > +
>> > +static int
>> > +hypervGetCimTypeInfo(hypervCimTypePtr typemap, const char *name,
>> > +hypervCimTypePtr *property)
>> > +{
>> > +size_t i = 0;
>> > +while (typemap[i].name[0] != '\0') {
>> > +if (STREQ(typemap[i].name, name)) {
>> > +*property = [i];
>> > +return 0;
>> > +}
>> > +i++;
>> > +}
>> > +
>> > +return -1;
>> > +}
>> > +
>> > +
>> > +static int
>> > +hypervCreateInvokeXmlDoc(hypervInvokeParamsListPtr params,
>> > WsXmlDocH *docRoot)
>> > +{
>> > +int result = -1;
>> > +char *method = NULL;
>> > +WsXmlNodeH xmlNodeMethod = NULL;
>> > +
>> > +if (virAsprintf(, "%s_INPUT", params->method) < 0)
>> > +goto error;
>> > +
>> > +*docRoot = ws_xml_create_doc(NULL, method);
>> > +if (*docRoot == NULL) {
>> > +virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> > +_("Could not instantiate XML document"));
>> > +goto error;
>> > +}
>> > +
>> > +xmlNodeMethod = xml_parser_get_root(*docRoot);
>> > +if (xmlNodeMethod == NULL) {
>> > +virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> > +_("Could not get root node of XML document"));
>> > +goto error;
>> > +}
>> > +
>> > +/* add resource URI as namespace */
>> > +ws_xml_set_ns(xmlNodeMethod, params->resourceUri, "p");
>> > +
>> > +result = 0;
>> > +goto cleanup;
>> > +
>> > + error:
>> > +if (*docRoot != NULL) {
>> > +ws_xml_destroy_doc(*docRoot);
>> > +*docRoot = NULL;
>> > +}
>> > + cleanup:
>> > +VIR_FREE(method);
>> > +return result;
>>
>> The error and cleanup label could be merged:
>>
>>
>> result = 0;
>>
>> cleanup:
>> if (result < 0 && *docRoot != NULL) {
>> ws_xml_destroy_doc(*docRoot);
>> *docRoot = NULL;
>> }
>>
>> VIR_FREE(method);
>> return result;
>> }
>>
>>
>> > +}
>> > +
>> > +static int
>> > +hypervSerializeSimpleParam(hypervParamPtr p, const char
>> > *resourceUri,
>> > +WsXmlNodeH *methodNode)
>> > +{
>> > +int result = -1;
>> > +WsXmlNodeH xmlNodeParam = NULL;
>> > +
>> > +xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
>> > +p->simple.name, p->simple.value);
>> > +if (xmlNodeParam == NULL) {
>> > +virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> > +_("Could not create simple param"));
>> > +goto cleanup;
>>
>> There is no actual cleanup, just return -1 here.
>>
>> > +}
>> > +
>> > +result = 0;
>> > +
>> > + cleanup:
>> > +return result;
>>
>> And just return 0 here.
>>
>> > +}
>> > +
>> > +static int
>> > +hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
>> > +const char *resourceUri, WsXmlDocH doc, WsXmlNodeH
>> > *methodNode)
>> > +{
>> > +int result = -1;
>> > +WsXmlNodeH xmlNodeParam = NULL,
>> > +   xmlNodeTemp = NULL,
>> > +   xmlNodeAddr = NULL,
>> > +   xmlNodeRef = NULL;
>> > +xmlNodePtr xmlNodeAddrPtr = NULL,
>> > +   xmlNodeRefPtr = NULL;
>> > +WsXmlDocH xmlDocResponse = NULL;
>> > +xmlDocPtr docPtr = (xmlDocPtr) doc->parserDoc;
>> > +WsXmlNsH ns = NULL;
>> > +client_opt_t *options = NULL;
>> > +filter_t *filter = NULL;
>> > +char *enumContext = NULL;
>> > +char *query_string = NULL;
>> > +
>> > +/* init and set up options */
>> > +options = wsmc_options_init();
>> > +if (!options) {
>> > +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", 

Re: [libvirt] [PATCH v2 3/5] qemu: Use GICv2 for aarch64/virt TCG guests

2017-05-16 Thread Peter Krempa
On Mon, May 15, 2017 at 17:06:50 +0200, Andrea Bolognani wrote:
> There are currently some limitations in the emulated GICv3
> that make it unsuitable as a default. Use GICv2 instead.
> 
> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1450433
> 
> Signed-off-by: Andrea Bolognani 
> ---
>  src/qemu/qemu_domain.c | 23 
> +-
>  .../qemuxml2argv-aarch64-gic-none-tcg.args |  2 +-
>  .../qemuxml2xmlout-aarch64-gic-none-tcg.xml|  2 +-
>  3 files changed, 24 insertions(+), 3 deletions(-)

ACK


signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 31/31] virsh: Implement sparse stream to vol-upload

2017-05-16 Thread Michal Privoznik
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 
---
 tools/virsh-util.c   | 47 +++
 tools/virsh-util.h   | 24 
 tools/virsh-volume.c | 38 +-
 tools/virsh.pod  |  3 ++-
 4 files changed, 98 insertions(+), 14 deletions(-)

diff --git a/tools/virsh-util.c b/tools/virsh-util.c
index 198625bdb..44be3ad64 100644
--- a/tools/virsh-util.c
+++ b/tools/virsh-util.c
@@ -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)
 {
diff --git a/tools/virsh-util.h b/tools/virsh-util.h
index 0aba247f6..9a0af3513 100644
--- a/tools/virsh-util.h
+++ b/tools/virsh-util.h
@@ -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,
diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c
index 3d19b745e..0736bdcdb 100644
--- a/tools/virsh-volume.c
+++ b/tools/virsh-volume.c
@@ -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", ) < 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, ) < 0) {
-vshError(ctl, _("cannot send data to volume %s"), name);
-goto cleanup;
+if (flags & 

[libvirt] [PATCH v3 28/31] gendispatch: Introduce @sparseflag for our calls

2017-05-16 Thread Michal Privoznik
Now, not all APIs are going to support sparse streams. To some it
makes no sense at all, e.g. virDomainOpenConsole() or
virDomainOpenChannel(). To others, we will need a special flag to
indicate that client wants to enable sparse streams. Instead of
having to write RPC dispatchers by hand we can just annotate in
our .x files that a certain flag to certain RPC call enables this
feature. For instance:

 /**
  * @generate: both
  * @readstream: 1
  * @sparseflag: VIR_SPARSE_STREAM
  * @acl: storage_vol:data_read
  */
 REMOTE_PROC_DOMAIN_SOME_API = XXX,

Therefore, whenever client calls virDomainSomeAPI(..,
VIR_SPARSE_STREAM); daemon will mark that down and send stream
skips when possible.

Signed-off-by: Michal Privoznik 
---
 src/rpc/gendispatch.pl | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index 98625983a..def88d4f9 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -281,6 +281,13 @@ while () {
 $calls{$name}->{streamflag} = "none";
 }
 
+if (exists $opts{sparseflag}) {
+die "\@sparseflag requires stream" unless 
$calls{$name}->{streamflag} ne "none";
+$calls{$name}->{sparseflag} = $opts{sparseflag};
+} else {
+$calls{$name}->{sparseflag} = "none";
+}
+
 $calls{$name}->{acl} = $opts{acl};
 $calls{$name}->{aclfilter} = $opts{aclfilter};
 
@@ -982,6 +989,11 @@ elsif ($mode eq "server") {
 if ($call->{streamflag} ne "none") {
 print "virStreamPtr st = NULL;\n";
 print "daemonClientStreamPtr stream = NULL;\n";
+if ($call->{sparseflag} ne "none") {
+print "const bool sparse = args->flags & 
$call->{sparseflag};\n"
+} else {
+print "const bool sparse = false;\n";
+}
 }
 
 print "\n";
@@ -1024,7 +1036,7 @@ elsif ($mode eq "server") {
 print "if (!(st = virStreamNew(priv->conn, 
VIR_STREAM_NONBLOCK)))\n";
 print "goto cleanup;\n";
 print "\n";
-print "if (!(stream = daemonCreateClientStream(client, st, 
remoteProgram, >header, false)))\n";
+print "if (!(stream = daemonCreateClientStream(client, st, 
remoteProgram, >header, sparse)))\n";
 print "goto cleanup;\n";
 print "\n";
 }
@@ -1727,6 +1739,11 @@ elsif ($mode eq "client") {
 
 if ($call->{streamflag} ne "none") {
 print "virNetClientStreamPtr netst = NULL;\n";
+if ($call->{sparseflag} ne "none") {
+print "const bool sparse = flags & $call->{sparseflag};\n"
+} else {
+print "const bool sparse = false;\n";
+}
 }
 
 print "\n";
@@ -1738,7 +1755,7 @@ elsif ($mode eq "client") {
 
 if ($call->{streamflag} ne "none") {
 print "\n";
-print "if (!(netst = virNetClientStreamNew(st, 
priv->remoteProgram, $call->{constname}, priv->counter, false)))\n";
+print "if (!(netst = virNetClientStreamNew(st, 
priv->remoteProgram, $call->{constname}, priv->counter, sparse)))\n";
 print "goto done;\n";
 print "\n";
 print "if (virNetClientAddStream(priv->client, netst) < 0) 
{\n";
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 25/31] remote_driver: Implement VIR_STREAM_RECV_STOP_AT_HOLE

2017-05-16 Thread Michal Privoznik
Signed-off-by: Michal Privoznik 
---
 src/remote/remote_driver.c   | 2 +-
 src/rpc/virnetclientstream.c | 9 -
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index dc59034c3..d27e96ffc 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -5652,7 +5652,7 @@ remoteStreamRecvFlags(virStreamPtr st,
 virNetClientStreamPtr privst = st->privateData;
 int rv;
 
-virCheckFlags(0, -1);
+virCheckFlags(VIR_STREAM_RECV_STOP_AT_HOLE, -1);
 
 if (virNetClientStreamRaiseError(privst))
 return -1;
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index 75ec3f57f..e68d8f946 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -467,7 +467,7 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
 VIR_DEBUG("st=%p client=%p data=%p nbytes=%zu nonblock=%d flags=%x",
   st, client, data, nbytes, nonblock, flags);
 
-virCheckFlags(0, -1);
+virCheckFlags(VIR_STREAM_RECV_STOP_AT_HOLE, -1);
 
 virObjectLock(st);
 
@@ -531,6 +531,13 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
 /* Pretend holeLength zeroes was read from stream. */
 size_t len = want;
 
+/* Yes, pretend unless we are asked not to. */
+if (flags & VIR_STREAM_RECV_STOP_AT_HOLE) {
+/* No error reporting here. Caller knows what they are doing. */
+rv = -3;
+goto cleanup;
+}
+
 if (len > st->holeLength)
 len = st->holeLength;
 
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 26/31] daemonStreamHandleRead: Wire up seekable stream

2017-05-16 Thread Michal Privoznik
Whenever client is able to receive some data from stream
daemonStreamHandleRead is called. But now the behaviour of this
function needs to be changed a bit. Previously it just read data
from underlying file (of chardev or whatever) and sent those
through the stream to client. This model will not work any longer
because it does not differentiate whether underlying file is in
data or hole section. Therefore, at the beginning of this
function add code that checks this situation and acts
accordingly.
So after the this, when wanting to send some data we always check
whether we are not in a hole and if so, skip it an inform client
about its size.

Signed-off-by: Michal Privoznik 
---
 daemon/stream.c | 59 +
 1 file changed, 59 insertions(+)

diff --git a/daemon/stream.c b/daemon/stream.c
index 57ddfe830..284499912 100644
--- a/daemon/stream.c
+++ b/daemon/stream.c
@@ -29,6 +29,7 @@
 #include "virlog.h"
 #include "virnetserverclient.h"
 #include "virerror.h"
+#include "libvirt_internal.h"
 
 #define VIR_FROM_THIS VIR_FROM_STREAMS
 
@@ -53,6 +54,7 @@ struct daemonClientStream {
 bool tx;
 
 bool allowSkip;
+size_t dataLen; /* How much data is there remaining until we see a hole */
 
 daemonClientStreamPtr next;
 };
@@ -796,6 +798,8 @@ daemonStreamHandleRead(virNetServerClientPtr client,
 size_t bufferLen = VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX;
 int ret = -1;
 int rv;
+int inData = 0;
+long long length = 0;
 
 VIR_DEBUG("client=%p, stream=%p tx=%d closed=%d",
   client, stream, stream->tx, stream->closed);
@@ -820,6 +824,58 @@ daemonStreamHandleRead(virNetServerClientPtr client,
 if (!(msg = virNetMessageNew(false)))
 goto cleanup;
 
+if (stream->allowSkip && !stream->dataLen) {
+/* Handle skip. We want to send some data to the client. But we might
+ * be in a hole. Seek to next data. But if we are in data already, just
+ * carry on. */
+
+rv = virStreamInData(stream->st, , );
+VIR_DEBUG("rv=%d inData=%d length=%lld", rv, inData, length);
+
+if (rv < 0) {
+if (virNetServerProgramSendStreamError(remoteProgram,
+   client,
+   msg,
+   ,
+   stream->procedure,
+   stream->serial) < 0)
+goto cleanup;
+msg = NULL;
+
+/* We're done with this call */
+goto done;
+} else {
+if (!inData && length) {
+stream->tx = false;
+msg->cb = daemonStreamMessageFinished;
+msg->opaque = stream;
+stream->refs++;
+if (virNetServerProgramSendStreamHole(remoteProgram,
+  client,
+  msg,
+  stream->procedure,
+  stream->serial,
+  length,
+  0) < 0)
+goto cleanup;
+
+msg = NULL;
+
+/* We have successfully sent stream skip to the  other side.
+ * To keep streams in sync seek locally too. */
+virStreamSendHole(stream->st, length, 0);
+/* We're done with this call */
+goto done;
+}
+}
+
+stream->dataLen = length;
+}
+
+if (stream->allowSkip &&
+bufferLen > stream->dataLen)
+bufferLen = stream->dataLen;
+
 rv = virStreamRecv(stream->st, buffer, bufferLen);
 if (rv == -2) {
 /* Should never get this, since we're only called when we know
@@ -834,6 +890,8 @@ daemonStreamHandleRead(virNetServerClientPtr client,
 goto cleanup;
 msg = NULL;
 } else {
+stream->dataLen -= rv;
+
 stream->tx = false;
 if (rv == 0)
 stream->recvEOF = true;
@@ -851,6 +909,7 @@ daemonStreamHandleRead(virNetServerClientPtr client,
 msg = NULL;
 }
 
+ done:
 ret = 0;
  cleanup:
 VIR_FREE(buffer);
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 20/31] remote_driver: Implement virStreamSendHole

2017-05-16 Thread Michal Privoznik
Now that we have RPC wrappers over VIR_NET_STREAM_HOLE we can
start wiring them up. This commit wires up situation when a
client wants to send a hole to daemon.

To keep stream offsets synchronous, upon successful call on the
daemon skip the same hole in local part of the stream.

Signed-off-by: Michal Privoznik 
---
 src/remote/remote_driver.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index aebdd47c9..ff5be6ebb 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -5683,6 +5683,37 @@ remoteStreamRecv(virStreamPtr st,
 return remoteStreamRecvFlags(st, data, nbytes, 0);
 }
 
+
+static int
+remoteStreamSendHole(virStreamPtr st,
+ long long length,
+ unsigned int flags)
+{
+VIR_DEBUG("st=%p length=%lld flags=%x",
+  st, length, flags);
+struct private_data *priv = st->conn->privateData;
+virNetClientStreamPtr privst = st->privateData;
+int rv;
+
+if (virNetClientStreamRaiseError(privst))
+return -1;
+
+remoteDriverLock(priv);
+priv->localUses++;
+remoteDriverUnlock(priv);
+
+rv = virNetClientStreamSendHole(privst,
+priv->client,
+length,
+flags);
+
+remoteDriverLock(priv);
+priv->localUses--;
+remoteDriverUnlock(priv);
+return rv;
+}
+
+
 struct remoteStreamCallbackData {
 virStreamPtr st;
 virStreamEventCallback cb;
@@ -5857,6 +5888,7 @@ static virStreamDriver remoteStreamDrv = {
 .streamRecv = remoteStreamRecv,
 .streamRecvFlags = remoteStreamRecvFlags,
 .streamSend = remoteStreamSend,
+.streamSendHole = remoteStreamSendHole,
 .streamFinish = remoteStreamFinish,
 .streamAbort = remoteStreamAbort,
 .streamEventAddCallback = remoteStreamEventAddCallback,
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 24/31] virNetClientStream: Wire up VIR_NET_STREAM_HOLE

2017-05-16 Thread Michal Privoznik
Whenever server sends a client stream packet (either regular with
actual data or stream skip one) it is queued on @st->rx. So the
list is a mixture of both types of stream packets. So now that we
have all the helpers needed we can wire their processing up. But
since virNetClientStreamRecvPacket doesn't support
VIR_STREAM_RECV_STOP_AT_HOLE flag yet, let's turn all received
skips into zeroes repeating requested times.

Signed-off-by: Michal Privoznik 
---
 src/rpc/virnetclientstream.c | 45 ++--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index bf3922cb5..75ec3f57f 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -295,6 +295,8 @@ int virNetClientStreamQueuePacket(virNetClientStreamPtr st,
 
 virObjectLock(st);
 
+/* Don't distinguish VIR_NET_STREAM and VIR_NET_STREAM_SKIP
+ * here just yet. We want in order processing! */
 virNetMessageQueuePush(>rx, tmp_msg);
 
 virNetClientStreamEventTimerUpdate(st);
@@ -390,7 +392,7 @@ virNetClientStreamSetHole(virNetClientStreamPtr st,
  * Returns: 0 on success,
  *  -1 otherwise.
  */
-static int ATTRIBUTE_UNUSED
+static int
 virNetClientStreamHandleHole(virNetClientPtr client,
  virNetClientStreamPtr st)
 {
@@ -468,6 +470,8 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
 virCheckFlags(0, -1);
 
 virObjectLock(st);
+
+ reread:
 if (!st->rx && !st->incomingEOF) {
 virNetMessagePtr msg;
 int ret;
@@ -499,8 +503,45 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
 }
 
 VIR_DEBUG("After IO rx=%p", st->rx);
+
+if (st->rx &&
+st->rx->header.type == VIR_NET_STREAM_HOLE &&
+st->holeLength == 0) {
+/* Handle skip sent to us by server. */
+
+if (virNetClientStreamHandleHole(client, st) < 0)
+goto cleanup;
+}
+
+if (!st->rx && !st->incomingEOF && !st->holeLength) {
+if (nonblock) {
+VIR_DEBUG("Non-blocking mode and no data available");
+rv = -2;
+goto cleanup;
+}
+
+/* We have consumed all packets from incoming queue but those
+ * were only skip packets, no data. Read the stream again. */
+goto reread;
+}
+
 want = nbytes;
-while (want && st->rx) {
+
+if (st->holeLength) {
+/* Pretend holeLength zeroes was read from stream. */
+size_t len = want;
+
+if (len > st->holeLength)
+len = st->holeLength;
+
+memset(data, 0, len);
+st->holeLength -= len;
+want -= len;
+}
+
+while (want &&
+   st->rx &&
+   st->rx->header.type == VIR_NET_STREAM) {
 virNetMessagePtr msg = st->rx;
 size_t len = want;
 
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 21/31] virNetClientStreamRecvPacket: Introduce @flags argument

2017-05-16 Thread Michal Privoznik
Signed-off-by: Michal Privoznik 
---
 src/remote/remote_driver.c   |  3 ++-
 src/rpc/virnetclientstream.c | 10 +++---
 src/rpc/virnetclientstream.h |  3 ++-
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index ff5be6ebb..63daec587 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -5665,7 +5665,8 @@ remoteStreamRecvFlags(virStreamPtr st,
   priv->client,
   data,
   nbytes,
-  (st->flags & VIR_STREAM_NONBLOCK));
+  (st->flags & VIR_STREAM_NONBLOCK),
+  flags);
 
 VIR_DEBUG("Done %d", rv);
 
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index 2f4f92a96..4a3d843b1 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -456,13 +456,17 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
  virNetClientPtr client,
  char *data,
  size_t nbytes,
- bool nonblock)
+ bool nonblock,
+ unsigned int flags)
 {
 int rv = -1;
 size_t want;
 
-VIR_DEBUG("st=%p client=%p data=%p nbytes=%zu nonblock=%d",
-  st, client, data, nbytes, nonblock);
+VIR_DEBUG("st=%p client=%p data=%p nbytes=%zu nonblock=%d flags=%x",
+  st, client, data, nbytes, nonblock, flags);
+
+virCheckFlags(0, -1);
+
 virObjectLock(st);
 if (!st->rx && !st->incomingEOF) {
 virNetMessagePtr msg;
diff --git a/src/rpc/virnetclientstream.h b/src/rpc/virnetclientstream.h
index c25c69bb1..1774e5ac3 100644
--- a/src/rpc/virnetclientstream.h
+++ b/src/rpc/virnetclientstream.h
@@ -59,7 +59,8 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
  virNetClientPtr client,
  char *data,
  size_t nbytes,
- bool nonblock);
+ bool nonblock,
+ unsigned int flags);
 
 int virNetClientStreamSendHole(virNetClientStreamPtr st,
virNetClientPtr client,
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 30/31] virsh: Implement sparse stream to vol-download

2017-05-16 Thread Michal Privoznik
The command grew new --sparse switch that does nothing more than
enables the sparse streams feature for this command. Among with
the switch new helper function is introduced: virshStreamSkip().
This is the callback that is called whenever daemon sends us a
hole. In the callback we reflect the hole in underlying file by
seeking as many bytes as told.

Signed-off-by: Michal Privoznik 
---
 tools/virsh-util.c   | 18 ++
 tools/virsh-util.h   |  5 +
 tools/virsh-volume.c | 12 ++--
 tools/virsh.pod  |  3 ++-
 4 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/tools/virsh-util.c b/tools/virsh-util.c
index 4b86e29cb..198625bdb 100644
--- a/tools/virsh-util.c
+++ b/tools/virsh-util.c
@@ -153,6 +153,24 @@ virshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
 }
 
 
+int
+virshStreamSkip(virStreamPtr st ATTRIBUTE_UNUSED,
+long long offset,
+void *opaque)
+{
+int *fd = opaque;
+off_t cur;
+
+if ((cur = lseek(*fd, offset, SEEK_CUR)) == (off_t) -1)
+return -1;
+
+if (ftruncate(*fd, cur) < 0)
+return -1;
+
+return 0;
+}
+
+
 void
 virshDomainFree(virDomainPtr dom)
 {
diff --git a/tools/virsh-util.h b/tools/virsh-util.h
index 64cef23c0..0aba247f6 100644
--- a/tools/virsh-util.h
+++ b/tools/virsh-util.h
@@ -57,6 +57,11 @@ virshStreamSink(virStreamPtr st,
 size_t nbytes,
 void *opaque);
 
+int
+virshStreamSkip(virStreamPtr st,
+long long offset,
+void *opaque);
+
 int
 virshDomainGetXMLFromDom(vshControl *ctl,
  virDomainPtr dom,
diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c
index 66fe70ea7..3d19b745e 100644
--- a/tools/virsh-volume.c
+++ b/tools/virsh-volume.c
@@ -763,6 +763,10 @@ static const vshCmdOptDef opts_vol_download[] = {
  .type = VSH_OT_INT,
  .help = N_("amount of data to download")
 },
+{.name = "sparse",
+ .type = VSH_OT_BOOL,
+ .help = N_("preserve sparseness of volume")
+},
 {.name = NULL}
 };
 
@@ -778,6 +782,7 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
 unsigned long long offset = 0, length = 0;
 bool created = false;
 virshControlPtr priv = ctl->privData;
+unsigned int flags = 0;
 
 if (vshCommandOptULongLong(ctl, cmd, "offset", ) < 0)
 return false;
@@ -791,6 +796,9 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
 if (vshCommandOptStringReq(ctl, cmd, "file", ) < 0)
 goto cleanup;
 
+if (vshCommandOptBool(cmd, "sparse"))
+flags |= VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM;
+
 if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) {
 if (errno != EEXIST ||
 (fd = open(file, O_WRONLY|O_TRUNC, 0666)) < 0) {
@@ -806,12 +814,12 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
 goto cleanup;
 }
 
-if (virStorageVolDownload(vol, st, offset, length, 0) < 0) {
+if (virStorageVolDownload(vol, st, offset, length, flags) < 0) {
 vshError(ctl, _("cannot download from volume %s"), name);
 goto cleanup;
 }
 
-if (virStreamRecvAll(st, virshStreamSink, ) < 0) {
+if (virStreamSparseRecvAll(st, virshStreamSink, virshStreamSkip, ) < 0) 
{
 vshError(ctl, _("cannot receive data from volume %s"), name);
 goto cleanup;
 }
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 727acf6e6..dcaa0c170 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -3942,12 +3942,13 @@ regarding possible target volume and pool changes as a 
result of the
 pool refresh when the upload is attempted.
 
 =item B [I<--pool> I] [I<--offset> I]
-[I<--length> I] I I
+[I<--length> I] [I<--sparse>] I I
 
 Download the contents of a storage volume to I.
 I<--pool> I is the name or UUID of the storage pool the volume
 is in.
 I is the name or key or path of the volume to 
download.
+If I<--sparse> is specified, this command will preserve volume sparseness.
 I<--offset> is the position in the storage volume at which to start reading
 the data. The value must be 0 or larger. I<--length> is an upper bound of
 the amount of data to be downloaded. A negative value is interpreted as
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 27/31] fdstream: Implement sparse stream

2017-05-16 Thread Michal Privoznik
Basically, what is needed here is to introduce new message type
for the messages passed between the event loop callbacks and the
worker thread that does all the I/O. The idea is that instead of
a queue of read buffers we will have a queue where "hole of size
X" messages appear. That way the even loop callbacks can just
check the head of the queue and see if the worker thread is in
data or a hole section and how long the section is.

Signed-off-by: Michal Privoznik 
---
 src/storage/storage_util.c |   4 +-
 src/util/virfdstream.c | 239 -
 src/util/virfdstream.h |   1 +
 3 files changed, 220 insertions(+), 24 deletions(-)

diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
index 43f3561f8..908cad874 100644
--- a/src/storage/storage_util.c
+++ b/src/storage/storage_util.c
@@ -2427,7 +2427,7 @@ virStorageBackendVolUploadLocal(virConnectPtr conn 
ATTRIBUTE_UNUSED,
 /* Not using O_CREAT because the file is required to already exist at
  * this point */
 ret = virFDStreamOpenBlockDevice(stream, target_path,
- offset, len, O_WRONLY);
+ offset, len, false, O_WRONLY);
 
  cleanup:
 VIR_FREE(path);
@@ -2465,7 +2465,7 @@ virStorageBackendVolDownloadLocal(virConnectPtr conn 
ATTRIBUTE_UNUSED,
 }
 
 ret = virFDStreamOpenBlockDevice(stream, target_path,
- offset, len, O_RDONLY);
+ offset, len, false, O_RDONLY);
 
  cleanup:
 VIR_FREE(path);
diff --git a/src/util/virfdstream.c b/src/util/virfdstream.c
index 4b42939e7..ba209025a 100644
--- a/src/util/virfdstream.c
+++ b/src/util/virfdstream.c
@@ -51,6 +51,7 @@ VIR_LOG_INIT("fdstream");
 
 typedef enum {
 VIR_FDSTREAM_MSG_TYPE_DATA,
+VIR_FDSTREAM_MSG_TYPE_HOLE,
 } virFDStreamMsgType;
 
 typedef struct _virFDStreamMsg virFDStreamMsg;
@@ -66,6 +67,9 @@ struct _virFDStreamMsg {
 size_t len;
 size_t offset;
 } data;
+struct {
+long long len;
+} hole;
 } stream;
 };
 
@@ -198,6 +202,9 @@ virFDStreamMsgFree(virFDStreamMsgPtr msg)
 case VIR_FDSTREAM_MSG_TYPE_DATA:
 VIR_FREE(msg->stream.data.buf);
 break;
+case VIR_FDSTREAM_MSG_TYPE_HOLE:
+/* nada */
+break;
 }
 
 VIR_FREE(msg);
@@ -385,6 +392,7 @@ struct _virFDStreamThreadData {
 virStreamPtr st;
 size_t length;
 bool doRead;
+bool sparse;
 int fdin;
 char *fdinname;
 int fdout;
@@ -407,34 +415,68 @@ virFDStreamThreadDataFree(virFDStreamThreadDataPtr data)
 
 static ssize_t
 virFDStreamThreadDoRead(virFDStreamDataPtr fdst,
+bool sparse,
 const int fdin,
 const int fdout,
 const char *fdinname,
 const char *fdoutname,
+size_t *dataLen,
 size_t buflen)
 {
 virFDStreamMsgPtr msg = NULL;
+int inData = 0;
+long long sectionLen = 0;
 char *buf = NULL;
 ssize_t got;
 
+if (sparse && *dataLen == 0) {
+if (virFileInData(fdin, , ) < 0)
+goto error;
+
+if (inData)
+*dataLen = sectionLen;
+}
+
 if (VIR_ALLOC(msg) < 0)
 goto error;
 
-if (VIR_ALLOC_N(buf, buflen) < 0)
-goto error;
-
-if ((got = saferead(fdin, buf, buflen)) < 0) {
-virReportSystemError(errno,
- _("Unable to read %s"),
- fdinname);
-goto error;
+if (sparse && *dataLen == 0) {
+msg->type = VIR_FDSTREAM_MSG_TYPE_HOLE;
+msg->stream.hole.len = sectionLen;
+got = sectionLen;
+
+/* HACK. The message queue is one directional. So caller
+ * cannot make us skip the hole. Do that for them instead. */
+if (sectionLen &&
+lseek(fdin, sectionLen, SEEK_CUR) == (off_t) -1) {
+virReportSystemError(errno,
+ _("unable to seek in %s"),
+ fdinname);
+goto error;
+}
+} else {
+if (sparse &&
+buflen > *dataLen)
+buflen = *dataLen;
+
+if (VIR_ALLOC_N(buf, buflen) < 0)
+goto error;
+
+if ((got = saferead(fdin, buf, buflen)) < 0) {
+virReportSystemError(errno,
+ _("Unable to read %s"),
+ fdinname);
+goto error;
+}
+
+msg->type = VIR_FDSTREAM_MSG_TYPE_DATA;
+msg->stream.data.buf = buf;
+msg->stream.data.len = got;
+buf = NULL;
+if (sparse)
+*dataLen -= got;
 }
 
-msg->type = VIR_FDSTREAM_MSG_TYPE_DATA;
-msg->stream.data.buf = buf;
-msg->stream.data.len = got;
-buf = NULL;
-
 

[libvirt] [PATCH v3 16/31] daemon: Introduce virNetServerProgramSendStreamHole

2017-05-16 Thread Michal Privoznik
This is just a helper function that takes in a length value,
encodes it into XDR and sends to client.

Signed-off-by: Michal Privoznik 
---
 src/libvirt_remote.syms   |  1 +
 src/rpc/virnetserverprogram.c | 35 +++
 src/rpc/virnetserverprogram.h |  8 
 3 files changed, 44 insertions(+)

diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index ca1f3ac86..bb6a8d465 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -178,6 +178,7 @@ virNetServerProgramNew;
 virNetServerProgramSendReplyError;
 virNetServerProgramSendStreamData;
 virNetServerProgramSendStreamError;
+virNetServerProgramSendStreamHole;
 virNetServerProgramUnknownError;
 
 
diff --git a/src/rpc/virnetserverprogram.c b/src/rpc/virnetserverprogram.c
index d1597f438..556c91605 100644
--- a/src/rpc/virnetserverprogram.c
+++ b/src/rpc/virnetserverprogram.c
@@ -548,6 +548,41 @@ int 
virNetServerProgramSendStreamData(virNetServerProgramPtr prog,
 }
 
 
+int virNetServerProgramSendStreamHole(virNetServerProgramPtr prog,
+  virNetServerClientPtr client,
+  virNetMessagePtr msg,
+  int procedure,
+  unsigned int serial,
+  long long length,
+  unsigned int flags)
+{
+virNetStreamHole data;
+
+VIR_DEBUG("client=%p msg=%p length=%lld", client, msg, length);
+
+memset(, 0, sizeof(data));
+data.length = length;
+data.flags = flags;
+
+msg->header.prog = prog->program;
+msg->header.vers = prog->version;
+msg->header.proc = procedure;
+msg->header.type = VIR_NET_STREAM_HOLE;
+msg->header.serial = serial;
+msg->header.status = VIR_NET_CONTINUE;
+
+if (virNetMessageEncodeHeader(msg) < 0)
+return -1;
+
+if (virNetMessageEncodePayload(msg,
+   (xdrproc_t) xdr_virNetStreamHole,
+   ) < 0)
+return -1;
+
+return virNetServerClientSendMessage(client, msg);
+}
+
+
 void virNetServerProgramDispose(void *obj ATTRIBUTE_UNUSED)
 {
 }
diff --git a/src/rpc/virnetserverprogram.h b/src/rpc/virnetserverprogram.h
index 531fca024..1731c9e1d 100644
--- a/src/rpc/virnetserverprogram.h
+++ b/src/rpc/virnetserverprogram.h
@@ -104,4 +104,12 @@ int 
virNetServerProgramSendStreamData(virNetServerProgramPtr prog,
   const char *data,
   size_t len);
 
+int virNetServerProgramSendStreamHole(virNetServerProgramPtr prog,
+  virNetServerClientPtr client,
+  virNetMessagePtr msg,
+  int procedure,
+  unsigned int serial,
+  long long length,
+  unsigned int flags);
+
 #endif /* __VIR_NET_SERVER_PROGRAM_H__ */
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 23/31] remote: Implement virStreamRecvHole

2017-05-16 Thread Michal Privoznik
Signed-off-by: Michal Privoznik 
---
 src/remote/remote_driver.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 63daec587..dc59034c3 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -5715,6 +5715,36 @@ remoteStreamSendHole(virStreamPtr st,
 }
 
 
+static int
+remoteStreamRecvHole(virStreamPtr st,
+ long long *length,
+ unsigned int flags)
+{
+struct private_data *priv = st->conn->privateData;
+virNetClientStreamPtr privst = st->privateData;
+int rv;
+
+VIR_DEBUG("st=%p length=%p flags=%x",
+  st, length, flags);
+
+virCheckFlags(0, -1);
+
+if (virNetClientStreamRaiseError(privst))
+return -1;
+
+remoteDriverLock(priv);
+priv->localUses++;
+remoteDriverUnlock(priv);
+
+rv = virNetClientStreamRecvHole(priv->client, privst, length);
+
+remoteDriverLock(priv);
+priv->localUses--;
+remoteDriverUnlock(priv);
+return rv;
+}
+
+
 struct remoteStreamCallbackData {
 virStreamPtr st;
 virStreamEventCallback cb;
@@ -5890,6 +5920,7 @@ static virStreamDriver remoteStreamDrv = {
 .streamRecvFlags = remoteStreamRecvFlags,
 .streamSend = remoteStreamSend,
 .streamSendHole = remoteStreamSendHole,
+.streamRecvHole = remoteStreamRecvHole,
 .streamFinish = remoteStreamFinish,
 .streamAbort = remoteStreamAbort,
 .streamEventAddCallback = remoteStreamEventAddCallback,
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 09/31] Introduce virStreamSparseSendAll

2017-05-16 Thread Michal Privoznik
This is just a wrapper over new function that have been just
introduced: virStreamSendHole() . It's very similar to
virStreamSendAll() except it handles sparse streams well.

Signed-off-by: Michal Privoznik 
---
 include/libvirt/libvirt-stream.h |  65 +++-
 src/libvirt-stream.c | 159 +++
 src/libvirt_public.syms  |   1 +
 3 files changed, 222 insertions(+), 3 deletions(-)

diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index a5e69a1c1..d18d43140 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -71,9 +71,9 @@ int virStreamRecvHole(virStreamPtr,
  * @nbytes: size of the data array
  * @opaque: optional application provided data
  *
- * The virStreamSourceFunc callback is used together
- * with the virStreamSendAll function for libvirt to
- * obtain the data that is to be sent.
+ * The virStreamSourceFunc callback is used together with
+ * the virStreamSendAll and virStreamSparseSendAll functions
+ * for libvirt to obtain the data that is to be sent.
  *
  * The callback will be invoked multiple times,
  * fetching data in small chunks. The application
@@ -96,6 +96,65 @@ int virStreamSendAll(virStreamPtr st,
  virStreamSourceFunc handler,
  void *opaque);
 
+/**
+ * virStreamSourceHoleFunc:
+ * @st: the stream object
+ * @inData: are we in data section
+ * @length: how long is the section we are currently in
+ * @opaque: optional application provided data
+ *
+ * The virStreamSourceHoleFunc callback is used together with the
+ * virStreamSparseSendAll function for libvirt to obtain the
+ * length of section stream is currently in.
+ *
+ * Moreover, upon successful return, @length should be updated
+ * with how many bytes are left until the current section ends
+ * (either data section or hole section). Also the stream is
+ * currently in data section, @inData should be set to a non-zero
+ * value and vice versa.
+ *
+ * NB: there's an implicit hole at the end of each file. If
+ * that's the case, @inData and @length should be both set to 0.
+ *
+ * This function should not adjust the current position within
+ * the file.
+ *
+ * Returns 0 on success,
+ *-1 upon error
+ */
+typedef int (*virStreamSourceHoleFunc)(virStreamPtr st,
+   int *inData,
+   long long *length,
+   void *opaque);
+
+/**
+ * virStreamSourceSkipFunc:
+ * @st: the stream object
+ * @length: stream hole size
+ * @opaque: optional application provided data
+ *
+ * This callback is used together with the virStreamSparseSendAll
+ * to skip holes in the underlying file as reported by
+ * virStreamSourceHoleFunc.
+ *
+ * The callback may be invoked multiple times as holes are found
+ * during processing a stream. The application should skip
+ * processing the hole in the stream source and then return.
+ * A return value of -1 at any time will abort the send operation.
+ *
+ * Returns 0 on success,
+ *-1 upon error.
+ */
+typedef int (*virStreamSourceSkipFunc)(virStreamPtr st,
+   long long length,
+   void *opaque);
+
+int virStreamSparseSendAll(virStreamPtr st,
+   virStreamSourceFunc handler,
+   virStreamSourceHoleFunc holeHandler,
+   virStreamSourceSkipFunc skipHandler,
+   void *opaque);
+
 /**
  * virStreamSinkFunc:
  *
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index 6bf4c4f29..4cbe5eee1 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -574,6 +574,165 @@ virStreamSendAll(virStreamPtr stream,
 }
 
 
+/**
+ * virStreamSparseSendAll:
+ * @stream: pointer to the stream object
+ * @handler: source callback for reading data from application
+ * @holeHandler: source callback for determining holes
+ * @skipHandler: skip holes as reported by @holeHandler
+ * @opaque: application defined data
+ *
+ * Send the entire data stream, reading the data from the
+ * requested data source. This is simply a convenient alternative
+ * to virStreamSend, for apps that do blocking-I/O.
+ *
+ * An example using this with a hypothetical file upload
+ * API looks like
+ *
+ *   int mysource(virStreamPtr st, char *buf, int nbytes, void *opaque) {
+ *   int *fd = opaque;
+ *
+ *   return read(*fd, buf, nbytes);
+ *   }
+ *
+ *   int myskip(virStreamPtr st, long long offset, void *opaque) {
+ *   int *fd = opaque;
+ *
+ *   return lseek(*fd, offset, SEEK_CUR) == (off_t) -1 ? -1 : 0;
+ *   }
+ *
+ *   int myindata(virStreamPtr st, int *inData,
+ *long long *offset, void *opaque) {
+ *   int *fd = opaque;
+ *
+ *   if (@fd in hole) {
+ *   *inData = 0;
+ *   *offset = holeSize;
+ *   } else {
+ * 

[libvirt] [PATCH v3 15/31] Teach wireshark plugin about VIR_NET_STREAM_HOLE

2017-05-16 Thread Michal Privoznik
Ideally, this would be generated, but to achieve that
corresponding XDR definitions needed to go into a different .x
file. But they belong just to the one that they are right now.

Signed-off-by: Michal Privoznik 
---
 tools/wireshark/src/packet-libvirt.c | 52 
 tools/wireshark/src/packet-libvirt.h |  2 ++
 2 files changed, 54 insertions(+)

diff --git a/tools/wireshark/src/packet-libvirt.c 
b/tools/wireshark/src/packet-libvirt.c
index 260161e98..a1f5a34f4 100644
--- a/tools/wireshark/src/packet-libvirt.c
+++ b/tools/wireshark/src/packet-libvirt.c
@@ -50,8 +50,12 @@ static int hf_libvirt_serial = -1;
 static int hf_libvirt_status = -1;
 static int hf_libvirt_stream = -1;
 static int hf_libvirt_num_of_fds = -1;
+static int hf_libvirt_stream_hole_length = -1;
+static int hf_libvirt_stream_hole_flags = -1;
+static int hf_libvirt_stream_hole = -1;
 int hf_libvirt_unknown = -1;
 static gint ett_libvirt = -1;
+static gint ett_libvirt_stream_hole = -1;
 
 #define XDR_PRIMITIVE_DISSECTOR(xtype, ctype, ftype)\
 static gboolean \
@@ -326,6 +330,33 @@ dissect_libvirt_payload_xdr_data(tvbuff_t *tvb, proto_tree 
*tree, gint payload_l
 dissect_libvirt_fds(tvb, start + payload_length, nfds);
 }
 
+static gboolean
+dissect_xdr_stream_hole(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf)
+{
+goffset start;
+proto_item *ti;
+
+start = xdr_getpos(xdrs);
+if (hf == -1) {
+ti = proto_tree_add_item(tree, hf_libvirt_stream_hole, tvb, start, -1, 
ENC_NA);
+} else {
+header_field_info *hfinfo;
+hfinfo = proto_registrar_get_nth(hf_libvirt_stream_hole);
+ti = proto_tree_add_item(tree, hf, tvb, start, -1, ENC_NA);
+proto_item_append_text(ti, " :: %s", hfinfo->name);
+}
+tree = proto_item_add_subtree(ti, ett_libvirt_stream_hole);
+
+hf = hf_libvirt_stream_hole_length;
+if (!dissect_xdr_hyper(tvb, tree, xdrs, hf)) return FALSE;
+
+hf = hf_libvirt_stream_hole_flags;
+if (!dissect_xdr_u_int(tvb, tree, xdrs, hf)) return FALSE;
+
+proto_item_set_len(ti, xdr_getpos(xdrs) - start);
+return TRUE;
+}
+
 static void
 dissect_libvirt_payload(tvbuff_t *tvb, proto_tree *tree,
 guint32 prog, guint32 proc, guint32 type, guint32 
status)
@@ -346,6 +377,8 @@ dissect_libvirt_payload(tvbuff_t *tvb, proto_tree *tree,
 dissect_libvirt_payload_xdr_data(tvb, tree, payload_length, status, 
VIR_ERROR_MESSAGE_DISSECTOR);
 } else if (type == VIR_NET_STREAM) { /* implicitly, status == 
VIR_NET_CONTINUE */
 dissect_libvirt_stream(tvb, tree, payload_length);
+} else if (type == VIR_NET_STREAM_HOLE) {
+dissect_libvirt_payload_xdr_data(tvb, tree, payload_length, status, 
dissect_xdr_stream_hole);
 } else {
 goto unknown;
 }
@@ -525,6 +558,24 @@ proto_register_libvirt(void)
 NULL, 0x0,
 NULL, HFILL}
 },
+{ _libvirt_stream_hole,
+  { "stream_hole", "libvirt.stream_hole",
+FT_NONE, BASE_NONE,
+NULL, 0x0,
+NULL, HFILL}
+},
+{ _libvirt_stream_hole_length,
+  { "length", "libvirt.stream_hole.length",
+FT_INT64, BASE_DEC,
+NULL, 0x0,
+NULL, HFILL}
+},
+{ _libvirt_stream_hole_flags,
+  { "flags", "libvirt.stream_hole.flags",
+FT_UINT32, BASE_DEC,
+NULL, 0x0,
+NULL, HFILL}
+},
 { _libvirt_unknown,
   { "unknown", "libvirt.unknown",
 FT_BYTES, BASE_NONE,
@@ -535,6 +586,7 @@ proto_register_libvirt(void)
 
 static gint *ett[] = {
 VIR_DYNAMIC_ETTSET
+_libvirt_stream_hole,
 _libvirt
 };
 
diff --git a/tools/wireshark/src/packet-libvirt.h 
b/tools/wireshark/src/packet-libvirt.h
index 5f99fdfae..9874a8cbf 100644
--- a/tools/wireshark/src/packet-libvirt.h
+++ b/tools/wireshark/src/packet-libvirt.h
@@ -53,6 +53,7 @@ enum vir_net_message_type {
 VIR_NET_STREAM = 3,
 VIR_NET_CALL_WITH_FDS  = 4,
 VIR_NET_REPLY_WITH_FDS = 5,
+VIR_NET_STREAM_HOLE= 6,
 };
 
 enum vir_net_message_status {
@@ -76,6 +77,7 @@ static const value_string type_strings[] = {
 { VIR_NET_STREAM, "STREAM" },
 { VIR_NET_CALL_WITH_FDS,  "CALL_WITH_FDS"  },
 { VIR_NET_REPLY_WITH_FDS, "REPLY_WITH_FDS" },
+{ VIR_NET_STREAM_HOLE,"STREAM_HOLE"},
 { -1, NULL }
 };
 
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 22/31] Introduce virNetClientStreamRecvHole

2017-05-16 Thread Michal Privoznik
This function will fetch previously processed stream holes and
return their sum.

Signed-off-by: Michal Privoznik 
---
 src/libvirt_remote.syms  |  1 +
 src/rpc/virnetclientstream.c | 16 
 src/rpc/virnetclientstream.h |  4 
 3 files changed, 21 insertions(+)

diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index 186d2c622..61c20d530 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -52,6 +52,7 @@ virNetClientStreamMatches;
 virNetClientStreamNew;
 virNetClientStreamQueuePacket;
 virNetClientStreamRaiseError;
+virNetClientStreamRecvHole;
 virNetClientStreamRecvPacket;
 virNetClientStreamSendHole;
 virNetClientStreamSendPacket;
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index 4a3d843b1..bf3922cb5 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -583,6 +583,22 @@ virNetClientStreamSendHole(virNetClientStreamPtr st,
 }
 
 
+int virNetClientStreamRecvHole(virNetClientPtr client ATTRIBUTE_UNUSED,
+   virNetClientStreamPtr st,
+   long long *length)
+{
+if (!st->allowSkip) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("Holes are not supported with this stream"));
+return -1;
+}
+
+*length = st->holeLength;
+st->holeLength = 0;
+return 0;
+}
+
+
 int virNetClientStreamEventAddCallback(virNetClientStreamPtr st,
int events,
virNetClientStreamEventCallback cb,
diff --git a/src/rpc/virnetclientstream.h b/src/rpc/virnetclientstream.h
index 1774e5ac3..c4e01bf1c 100644
--- a/src/rpc/virnetclientstream.h
+++ b/src/rpc/virnetclientstream.h
@@ -67,6 +67,10 @@ int virNetClientStreamSendHole(virNetClientStreamPtr st,
long long length,
unsigned int flags);
 
+int virNetClientStreamRecvHole(virNetClientPtr client,
+   virNetClientStreamPtr st,
+   long long *length);
+
 int virNetClientStreamEventAddCallback(virNetClientStreamPtr st,
int events,
virNetClientStreamEventCallback cb,
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 08/31] Introduce virStreamSparseRecvAll

2017-05-16 Thread Michal Privoznik
This is just a wrapper over new functions that have been just
introduced: virStreamRecvFlags(), virStreamRecvHole(). It's very
similar to virStreamRecvAll() except it handles sparse streams
well.

Signed-off-by: Michal Privoznik 
---
 include/libvirt/libvirt-stream.h |  33 ++-
 src/libvirt-stream.c | 123 +++
 src/libvirt_public.syms  |   1 +
 3 files changed, 154 insertions(+), 3 deletions(-)

diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index c4baaf7a3..a5e69a1c1 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -104,9 +104,9 @@ int virStreamSendAll(virStreamPtr st,
  * @nbytes: size of the data array
  * @opaque: optional application provided data
  *
- * The virStreamSinkFunc callback is used together
- * with the virStreamRecvAll function for libvirt to
- * provide the data that has been received.
+ * The virStreamSinkFunc callback is used together with the
+ * virStreamRecvAll or virStreamSparseRecvAll functions for
+ * libvirt to provide the data that has been received.
  *
  * The callback will be invoked multiple times,
  * providing data in small chunks. The application
@@ -129,6 +129,33 @@ int virStreamRecvAll(virStreamPtr st,
  virStreamSinkFunc handler,
  void *opaque);
 
+/**
+ * virStreamSinkHoleFunc:
+ * @st: the stream object
+ * @length: stream hole size
+ * @opaque: optional application provided data
+ *
+ * This callback is used together with the virStreamSparseRecvAll
+ * function for libvirt to provide the size of a hole that
+ * occurred in the stream.
+ *
+ * The callback may be invoked multiple times as holes are found
+ * during processing a stream. The application should create the
+ * hole in the stream target and then return. A return value of
+ * -1 at any time will abort the receive operation.
+ *
+ * Returns 0 on success,
+ *-1 upon error
+ */
+typedef int (*virStreamSinkHoleFunc)(virStreamPtr st,
+ long long length,
+ void *opaque);
+
+int virStreamSparseRecvAll(virStreamPtr stream,
+   virStreamSinkFunc handler,
+   virStreamSinkHoleFunc holeHandler,
+   void *opaque);
+
 typedef enum {
 VIR_STREAM_EVENT_READABLE  = (1 << 0),
 VIR_STREAM_EVENT_WRITABLE  = (1 << 1),
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index bedb6159a..6bf4c4f29 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -668,6 +668,129 @@ virStreamRecvAll(virStreamPtr stream,
 }
 
 
+/**
+ * virStreamSparseRecvAll:
+ * @stream: pointer to the stream object
+ * @handler: sink callback for writing data to application
+ * @holeHandler: stream hole callback for skipping holes
+ * @opaque: application defined data
+ *
+ * Receive the entire data stream, sending the data to the
+ * requested data sink @handler and calling the skip @holeHandler
+ * to generate holes for sparse stream targets. This is simply a
+ * convenient alternative to virStreamRecvFlags, for apps that do
+ * blocking-I/O.
+ *
+ * An example using this with a hypothetical file download
+ * API looks like:
+ *
+ *   int mysink(virStreamPtr st, const char *buf, int nbytes, void *opaque) {
+ *   int *fd = opaque;
+ *
+ *   return write(*fd, buf, nbytes);
+ *   }
+ *
+ *   int myskip(virStreamPtr st, long long offset, void *opaque) {
+ *   int *fd = opaque;
+ *
+ *   return lseek(*fd, offset, SEEK_CUR) == (off_t) -1 ? -1 : 0;
+ *   }
+ *
+ *   virStreamPtr st = virStreamNew(conn, 0);
+ *   int fd = open("demo.iso", O_WRONLY);
+ *
+ *   virConnectDownloadSparseFile(conn, st);
+ *   if (virStreamSparseRecvAll(st, mysink, myskip, ) < 0) {
+ *  ...report an error ...
+ *  goto done;
+ *   }
+ *   if (virStreamFinish(st) < 0)
+ *  ...report an error...
+ *   virStreamFree(st);
+ *   close(fd);
+ *
+ * Note that @opaque data is shared between both @handler and
+ * @holeHandler callbacks.
+ *
+ * Returns 0 if all the data was successfully received. The caller
+ * should invoke virStreamFinish(st) to flush the stream upon
+ * success and then virStreamFree(st).
+ *
+ * Returns -1 upon any error, with virStreamAbort() already
+ * having been called, so the caller need only call virStreamFree().
+ */
+int
+virStreamSparseRecvAll(virStreamPtr stream,
+   virStreamSinkFunc handler,
+   virStreamSinkHoleFunc holeHandler,
+   void *opaque)
+{
+char *bytes = NULL;
+size_t want = VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX;
+const unsigned int flags = VIR_STREAM_RECV_STOP_AT_HOLE;
+int ret = -1;
+
+VIR_DEBUG("stream=%p handler=%p holeHandler=%p opaque=%p",
+  stream, handler, holeHandler, opaque);
+
+virResetLastError();
+
+virCheckStreamReturn(stream, -1);
+

[libvirt] [PATCH v3 14/31] Introduce VIR_NET_STREAM_HOLE message type

2017-05-16 Thread Michal Privoznik
This is a special type of stream packet, that is bidirectional
and will contain information on how much bytes are both sides
skipping in the stream.

Signed-off-by: Michal Privoznik 
---
 daemon/stream.c|  3 ++-
 src/rpc/virnetclient.c |  1 +
 src/rpc/virnetprotocol.x   | 12 +++-
 src/virnetprotocol-structs |  1 +
 4 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/daemon/stream.c b/daemon/stream.c
index 6465463ff..f44c21278 100644
--- a/daemon/stream.c
+++ b/daemon/stream.c
@@ -287,7 +287,8 @@ daemonStreamFilter(virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
 
 virMutexLock(>priv->lock);
 
-if (msg->header.type != VIR_NET_STREAM)
+if (msg->header.type != VIR_NET_STREAM &&
+msg->header.type != VIR_NET_STREAM_HOLE)
 goto cleanup;
 
 if (!virNetServerProgramMatches(stream->prog, msg))
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
index 837a8a707..95cd9a6c7 100644
--- a/src/rpc/virnetclient.c
+++ b/src/rpc/virnetclient.c
@@ -1284,6 +1284,7 @@ virNetClientCallDispatch(virNetClientPtr client)
 return virNetClientCallDispatchMessage(client);
 
 case VIR_NET_STREAM: /* Stream protocol */
+case VIR_NET_STREAM_HOLE: /* Sparse stream protocol*/
 return virNetClientCallDispatchStream(client);
 
 default:
diff --git a/src/rpc/virnetprotocol.x b/src/rpc/virnetprotocol.x
index cab047cb0..ee9899059 100644
--- a/src/rpc/virnetprotocol.x
+++ b/src/rpc/virnetprotocol.x
@@ -143,6 +143,14 @@ const VIR_NET_MESSAGE_NUM_FDS_MAX = 32;
  * * status == VIR_NET_ERROR
  *  remote_errorError information
  *
+ *  - type == VIR_NET_STREAM_HOLE
+ * * status == VIR_NET_CONTINUE
+ *  byte[]  hole data
+ * * status == VIR_NET_ERROR
+ *  remote_error error information
+ * * status == VIR_NET_OK
+ *  
+ *
  */
 enum virNetMessageType {
 /* client -> server. args from a method call */
@@ -156,7 +164,9 @@ enum virNetMessageType {
 /* client -> server. args from a method call, with passed FDs */
 VIR_NET_CALL_WITH_FDS = 4,
 /* server -> client. reply/error from a method call, with passed FDs */
-VIR_NET_REPLY_WITH_FDS = 5
+VIR_NET_REPLY_WITH_FDS = 5,
+/* either direction, stream hole data packet */
+VIR_NET_STREAM_HOLE = 6
 };
 
 enum virNetMessageStatus {
diff --git a/src/virnetprotocol-structs b/src/virnetprotocol-structs
index aa6e0602a..b36581f86 100644
--- a/src/virnetprotocol-structs
+++ b/src/virnetprotocol-structs
@@ -6,6 +6,7 @@ enum virNetMessageType {
 VIR_NET_STREAM = 3,
 VIR_NET_CALL_WITH_FDS = 4,
 VIR_NET_REPLY_WITH_FDS = 5,
+VIR_NET_STREAM_HOLE = 6,
 };
 enum virNetMessageStatus {
 VIR_NET_OK = 0,
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 19/31] virnetclientstream: Introduce virNetClientStreamHandleHole

2017-05-16 Thread Michal Privoznik
This is a function that handles an incoming STREAM_HOLE packet.
Even though it is not wired up yet, it will be soon. At the
beginning do couple of checks whether server plays nicely and
sent us a STREAM_HOLE packed only after we've enabled sparse
streams. Then decodes the message payload to see how big the hole
is and stores it in passed @length argument.

Signed-off-by: Michal Privoznik 
---
 src/rpc/virnetclientstream.c | 96 
 1 file changed, 96 insertions(+)

diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index 9005e6be9..2f4f92a96 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -55,6 +55,7 @@ struct _virNetClientStream {
 bool incomingEOF;
 
 bool allowSkip;
+long long holeLength;  /* Size of incoming hole in stream. */
 
 virNetClientStreamEventCallback cb;
 void *cbOpaque;
@@ -356,6 +357,101 @@ int virNetClientStreamSendPacket(virNetClientStreamPtr st,
 return -1;
 }
 
+
+static int
+virNetClientStreamSetHole(virNetClientStreamPtr st,
+  long long length,
+  unsigned int flags)
+{
+virCheckFlags(0, -1);
+
+/* Shouldn't happen, But it's better to safe than sorry. */
+if (st->holeLength) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("unprocessed hole of size %lld already in the queue"),
+   st->holeLength);
+return -1;
+}
+
+st->holeLength += length;
+return 0;
+}
+
+
+/**
+ * virNetClientStreamHandleHole:
+ * @client: client
+ * @st: stream
+ *
+ * Called whenever current message processed in the stream is
+ * VIR_NET_STREAM_HOLE. The stream @st is expected to be locked
+ * already.
+ *
+ * Returns: 0 on success,
+ *  -1 otherwise.
+ */
+static int ATTRIBUTE_UNUSED
+virNetClientStreamHandleHole(virNetClientPtr client,
+ virNetClientStreamPtr st)
+{
+virNetMessagePtr msg;
+virNetStreamHole data;
+int ret = -1;
+
+VIR_DEBUG("client=%p st=%p", client, st);
+
+msg = st->rx;
+memset(, 0, sizeof(data));
+
+/* We should not be called unless there's VIR_NET_STREAM_HOLE
+ * message at the head of the list. But doesn't hurt to check */
+if (!msg) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("No message in the queue"));
+goto cleanup;
+}
+
+if (msg->header.type != VIR_NET_STREAM_HOLE) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Invalid message prog=%d type=%d serial=%u proc=%d"),
+   msg->header.prog,
+   msg->header.type,
+   msg->header.serial,
+   msg->header.proc);
+goto cleanup;
+}
+
+/* Server should not send us VIR_NET_STREAM_HOLE unless we
+ * have requested so. But does not hurt to check ... */
+if (!st->allowSkip) {
+virReportError(VIR_ERR_RPC, "%s",
+   _("Unexpected stream hole"));
+goto cleanup;
+}
+
+if (virNetMessageDecodePayload(msg,
+   (xdrproc_t) xdr_virNetStreamHole,
+   ) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Malformed stream hole packet"));
+goto cleanup;
+}
+
+virNetMessageQueueServe(>rx);
+virNetMessageFree(msg);
+
+if (virNetClientStreamSetHole(st, data.length, data.flags) < 0)
+goto cleanup;
+
+ret = 0;
+ cleanup:
+if (ret < 0) {
+/* Abort stream? */
+}
+return ret;
+}
+
+
 int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
  virNetClientPtr client,
  char *data,
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 12/31] Add new flag to daemonCreateClientStream and virNetClientStreamNew

2017-05-16 Thread Michal Privoznik
Add a new argument to daemonCreateClientStream in order to allow for
future expansion to mark that a specific stream can be used to skip
data, such as the case with sparsely populated files. The new flag will
be the eventual decision point between client/server to decide whether
both ends can support and want to use sparse streams.

A new bool 'allowSkip' is added to both _virNetClientStream and
daemonClientStream in order to perform the tracking.

Signed-off-by: Michal Privoznik 
---
 daemon/remote.c  | 2 +-
 daemon/stream.c  | 6 +-
 daemon/stream.h  | 3 ++-
 src/remote/remote_driver.c   | 6 --
 src/rpc/gendispatch.pl   | 4 ++--
 src/rpc/virnetclientstream.c | 6 +-
 src/rpc/virnetclientstream.h | 3 ++-
 7 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 0dbb250ff..fd8542120 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5323,7 +5323,7 @@ 
remoteDispatchDomainMigratePrepareTunnel3Params(virNetServerPtr server ATTRIBUTE
 
 if (!(st = virStreamNew(priv->conn, VIR_STREAM_NONBLOCK)) ||
 !(stream = daemonCreateClientStream(client, st, remoteProgram,
->header)))
+>header, false)))
 goto cleanup;
 
 if (virDomainMigratePrepareTunnel3Params(priv->conn, st, params, nparams,
diff --git a/daemon/stream.c b/daemon/stream.c
index 11c0a469d..6465463ff 100644
--- a/daemon/stream.c
+++ b/daemon/stream.c
@@ -52,6 +52,8 @@ struct daemonClientStream {
 virNetMessagePtr rx;
 bool tx;
 
+bool allowSkip;
+
 daemonClientStreamPtr next;
 };
 
@@ -321,7 +323,8 @@ daemonClientStream *
 daemonCreateClientStream(virNetServerClientPtr client,
  virStreamPtr st,
  virNetServerProgramPtr prog,
- virNetMessageHeaderPtr header)
+ virNetMessageHeaderPtr header,
+ bool allowSkip)
 {
 daemonClientStream *stream;
 daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client);
@@ -339,6 +342,7 @@ daemonCreateClientStream(virNetServerClientPtr client,
 stream->serial = header->serial;
 stream->filterID = -1;
 stream->st = st;
+stream->allowSkip = allowSkip;
 
 return stream;
 }
diff --git a/daemon/stream.h b/daemon/stream.h
index cf76e717a..e1f106759 100644
--- a/daemon/stream.h
+++ b/daemon/stream.h
@@ -30,7 +30,8 @@ daemonClientStream *
 daemonCreateClientStream(virNetServerClientPtr client,
  virStreamPtr st,
  virNetServerProgramPtr prog,
- virNetMessageHeaderPtr hdr);
+ virNetMessageHeaderPtr hdr,
+ bool allowSkip);
 
 int daemonFreeClientStream(virNetServerClientPtr client,
daemonClientStream *stream);
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index b152be523..aebdd47c9 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6173,7 +6173,8 @@ remoteDomainMigratePrepareTunnel3(virConnectPtr dconn,
 if (!(netst = virNetClientStreamNew(st,
 priv->remoteProgram,
 
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3,
-priv->counter)))
+priv->counter,
+false)))
 goto done;
 
 if (virNetClientAddStream(priv->client, netst) < 0) {
@@ -7098,7 +7099,8 @@ remoteDomainMigratePrepareTunnel3Params(virConnectPtr 
dconn,
 if (!(netst = virNetClientStreamNew(st,
 priv->remoteProgram,
 
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3_PARAMS,
-priv->counter)))
+priv->counter,
+false)))
 goto cleanup;
 
 if (virNetClientAddStream(priv->client, netst) < 0) {
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index e608812ce..98625983a 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -1024,7 +1024,7 @@ elsif ($mode eq "server") {
 print "if (!(st = virStreamNew(priv->conn, 
VIR_STREAM_NONBLOCK)))\n";
 print "goto cleanup;\n";
 print "\n";
-print "if (!(stream = daemonCreateClientStream(client, st, 
remoteProgram, >header)))\n";
+print "if (!(stream = daemonCreateClientStream(client, st, 
remoteProgram, >header, false)))\n";
 print "goto cleanup;\n";
 print "\n";
 }
@@ -1738,7 +1738,7 @@ elsif ($mode eq "client") {
 
 if ($call->{streamflag} ne "none") {
 print "\n";
-

[libvirt] [PATCH v3 06/31] Introduce virStreamRecvHole

2017-05-16 Thread Michal Privoznik
This function is basically a counterpart for virStreamSendHole().
If one side of a stream called virStreamSendHole() the other
should call virStreamRecvHole() to get the size of the hole.

Signed-off-by: Michal Privoznik 
---
 include/libvirt/libvirt-stream.h |  4 
 src/driver-stream.h  |  6 ++
 src/libvirt-stream.c | 44 
 src/libvirt_public.syms  |  1 +
 4 files changed, 55 insertions(+)

diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index 14c9af142..feaa8ad64 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -54,6 +54,10 @@ int virStreamSendHole(virStreamPtr st,
   long long length,
   unsigned int flags);
 
+int virStreamRecvHole(virStreamPtr,
+  long long *length,
+  unsigned int flags);
+
 
 /**
  * virStreamSourceFunc:
diff --git a/src/driver-stream.h b/src/driver-stream.h
index 0a5201431..0fb56ebd2 100644
--- a/src/driver-stream.h
+++ b/src/driver-stream.h
@@ -46,6 +46,11 @@ typedef int
 long long length,
 unsigned int flags);
 
+typedef int
+(*virDrvStreamRecvHole)(virStreamPtr st,
+long long *length,
+unsigned int flags);
+
 typedef int
 (*virDrvStreamEventAddCallback)(virStreamPtr stream,
 int events,
@@ -74,6 +79,7 @@ struct _virStreamDriver {
 virDrvStreamRecv streamRecv;
 virDrvStreamRecvFlags streamRecvFlags;
 virDrvStreamSendHole streamSendHole;
+virDrvStreamRecvHole streamRecvHole;
 virDrvStreamEventAddCallback streamEventAddCallback;
 virDrvStreamEventUpdateCallback streamEventUpdateCallback;
 virDrvStreamEventRemoveCallback streamEventRemoveCallback;
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index a09896dcd..dc0dc9ea3 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -405,6 +405,50 @@ virStreamSendHole(virStreamPtr stream,
 }
 
 
+/**
+ * virStreamRecvHole:
+ * @stream: pointer to the stream object
+ * @length: number of bytes to skip
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * This API is used to determine the @length in bytes of the
+ * empty space to be created in a @stream's target file when
+ * uploading or downloading sparsely populated files. This is the
+ * counterpart to virStreamSendHole().
+ *
+ * Returns 0 on success,
+ *-1 on error or when there's currently no hole in the stream
+ */
+int
+virStreamRecvHole(virStreamPtr stream,
+  long long *length,
+  unsigned int flags)
+{
+VIR_DEBUG("stream=%p, length=%p flags=%x",
+  stream, length, flags);
+
+virResetLastError();
+
+virCheckStreamReturn(stream, -1);
+virCheckNonNullArgReturn(length, -1);
+
+if (stream->driver &&
+stream->driver->streamRecvHole) {
+int ret;
+ret = (stream->driver->streamRecvHole)(stream, length, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+
+virReportUnsupportedError();
+
+ error:
+virDispatchError(stream->conn);
+return -1;
+}
+
+
 /**
  * virStreamSendAll:
  * @stream: pointer to the stream object
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 3be7cc6a0..b73cc8af1 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -762,6 +762,7 @@ LIBVIRT_3.1.0 {
 LIBVIRT_3.4.0 {
 global:
 virStreamRecvFlags;
+virStreamRecvHole;
 virStreamSendHole;
 } LIBVIRT_3.1.0;
 
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 18/31] daemon: Implement VIR_NET_STREAM_HOLE handling

2017-05-16 Thread Michal Privoznik
Basically, whenever the new type of stream packet arrives to the
daemon call this function that decodes it and calls
virStreamSendHole(). Otherwise a regular data stream packet has
arrived and therefore continue its processing.

Signed-off-by: Michal Privoznik 
---
 daemon/stream.c | 80 +
 1 file changed, 69 insertions(+), 11 deletions(-)

diff --git a/daemon/stream.c b/daemon/stream.c
index f44c21278..57ddfe830 100644
--- a/daemon/stream.c
+++ b/daemon/stream.c
@@ -653,6 +653,52 @@ daemonStreamHandleAbort(virNetServerClientPtr client,
 }
 
 
+static int
+daemonStreamHandleHole(virNetServerClientPtr client,
+   daemonClientStream *stream,
+   virNetMessagePtr msg)
+{
+int ret;
+virNetStreamHole data;
+
+VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%u",
+  client, stream, msg->header.proc, msg->header.serial);
+
+/* Let's check if client plays nicely and advertised usage of
+ * sparse stream upfront. */
+if (!stream->allowSkip) {
+virReportError(VIR_ERR_RPC, "%s",
+   _("Unexpected stream hole"));
+return -1;
+}
+
+if (virNetMessageDecodePayload(msg,
+   (xdrproc_t) xdr_virNetStreamHole,
+   ) < 0)
+return -1;
+
+ret = virStreamSendHole(stream->st, data.length, data.flags);
+
+if (ret < 0) {
+virNetMessageError rerr;
+
+memset(, 0, sizeof(rerr));
+
+VIR_INFO("Stream send hole failed");
+stream->closed = true;
+virStreamEventRemoveCallback(stream->st);
+virStreamAbort(stream->st);
+
+return virNetServerProgramSendReplyError(stream->prog,
+ client,
+ msg,
+ ,
+ >header);
+}
+
+return 0;
+}
+
 
 /*
  * Called when the stream is signalled has being able to accept
@@ -671,19 +717,31 @@ daemonStreamHandleWrite(virNetServerClientPtr client,
 virNetMessagePtr msg = stream->rx;
 int ret;
 
-switch (msg->header.status) {
-case VIR_NET_OK:
-ret = daemonStreamHandleFinish(client, stream, msg);
-break;
+if (msg->header.type == VIR_NET_STREAM_HOLE) {
+/* Handle special case when the client sent us a hole.
+ * Otherwise just carry on with processing stream
+ * data. */
+ret = daemonStreamHandleHole(client, stream, msg);
+} else if (msg->header.type == VIR_NET_STREAM) {
+switch (msg->header.status) {
+case VIR_NET_OK:
+ret = daemonStreamHandleFinish(client, stream, msg);
+break;
 
-case VIR_NET_CONTINUE:
-ret = daemonStreamHandleWriteData(client, stream, msg);
-break;
+case VIR_NET_CONTINUE:
+ret = daemonStreamHandleWriteData(client, stream, msg);
+break;
 
-case VIR_NET_ERROR:
-default:
-ret = daemonStreamHandleAbort(client, stream, msg);
-break;
+case VIR_NET_ERROR:
+default:
+ret = daemonStreamHandleAbort(client, stream, msg);
+break;
+}
+} else {
+virReportError(VIR_ERR_RPC,
+   _("Unexpected message type: %d"),
+   msg->header.type);
+ret = -1;
 }
 
 if (ret > 0)
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 11/31] virNetClientStreamNew: Track origin stream

2017-05-16 Thread Michal Privoznik
Add a virStreamPtr pointer to the _virNetClientStream
in order to reverse track the parent stream.

Signed-off-by: Michal Privoznik 
---
 src/remote/remote_driver.c   | 6 --
 src/rpc/gendispatch.pl   | 2 +-
 src/rpc/virnetclientstream.c | 6 +-
 src/rpc/virnetclientstream.h | 3 ++-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index e79e796f2..b152be523 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6170,7 +6170,8 @@ remoteDomainMigratePrepareTunnel3(virConnectPtr dconn,
 memset(, 0, sizeof(args));
 memset(, 0, sizeof(ret));
 
-if (!(netst = virNetClientStreamNew(priv->remoteProgram,
+if (!(netst = virNetClientStreamNew(st,
+priv->remoteProgram,
 
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3,
 priv->counter)))
 goto done;
@@ -7094,7 +7095,8 @@ remoteDomainMigratePrepareTunnel3Params(virConnectPtr 
dconn,
 goto cleanup;
 }
 
-if (!(netst = virNetClientStreamNew(priv->remoteProgram,
+if (!(netst = virNetClientStreamNew(st,
+priv->remoteProgram,
 
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3_PARAMS,
 priv->counter)))
 goto cleanup;
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index 173189c81..e608812ce 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -1738,7 +1738,7 @@ elsif ($mode eq "client") {
 
 if ($call->{streamflag} ne "none") {
 print "\n";
-print "if (!(netst = 
virNetClientStreamNew(priv->remoteProgram, $call->{constname}, 
priv->counter)))\n";
+print "if (!(netst = virNetClientStreamNew(st, 
priv->remoteProgram, $call->{constname}, priv->counter)))\n";
 print "goto done;\n";
 print "\n";
 print "if (virNetClientAddStream(priv->client, netst) < 0) 
{\n";
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index 2105bd0a9..01761cf8d 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -36,6 +36,8 @@ VIR_LOG_INIT("rpc.netclientstream");
 struct _virNetClientStream {
 virObjectLockable parent;
 
+virStreamPtr stream; /* Reverse pointer to parent stream */
+
 virNetClientProgramPtr prog;
 int proc;
 unsigned serial;
@@ -133,7 +135,8 @@ virNetClientStreamEventTimer(int timer ATTRIBUTE_UNUSED, 
void *opaque)
 }
 
 
-virNetClientStreamPtr virNetClientStreamNew(virNetClientProgramPtr prog,
+virNetClientStreamPtr virNetClientStreamNew(virStreamPtr stream,
+virNetClientProgramPtr prog,
 int proc,
 unsigned serial)
 {
@@ -145,6 +148,7 @@ virNetClientStreamPtr 
virNetClientStreamNew(virNetClientProgramPtr prog,
 if (!(st = virObjectLockableNew(virNetClientStreamClass)))
 return NULL;
 
+st->stream = stream;
 st->prog = virObjectRef(prog);
 st->proc = proc;
 st->serial = serial;
diff --git a/src/rpc/virnetclientstream.h b/src/rpc/virnetclientstream.h
index a0d2be9ed..e278dab85 100644
--- a/src/rpc/virnetclientstream.h
+++ b/src/rpc/virnetclientstream.h
@@ -32,7 +32,8 @@ typedef virNetClientStream *virNetClientStreamPtr;
 typedef void (*virNetClientStreamEventCallback)(virNetClientStreamPtr stream,
 int events, void *opaque);
 
-virNetClientStreamPtr virNetClientStreamNew(virNetClientProgramPtr prog,
+virNetClientStreamPtr virNetClientStreamNew(virStreamPtr stream,
+virNetClientProgramPtr prog,
 int proc,
 unsigned serial);
 
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 04/31] Implement virStreamRecvFlags to some drivers

2017-05-16 Thread Michal Privoznik
There are three virStreamDriver's currently supported:

 * virFDStream
 * remote driver
 * ESX driver

For now, backend virStreamRecvFlags support for only remote driver and
ESX driver is sufficient. Future patches will update virFDStream.

Signed-off-by: Michal Privoznik 
---
 src/esx/esx_stream.c   | 16 +++-
 src/remote/remote_driver.c | 21 +
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/esx/esx_stream.c b/src/esx/esx_stream.c
index fb9abbca6..b820b38ee 100644
--- a/src/esx/esx_stream.c
+++ b/src/esx/esx_stream.c
@@ -252,12 +252,17 @@ esxStreamSend(virStreamPtr stream, const char *data, 
size_t nbytes)
 }
 
 static int
-esxStreamRecv(virStreamPtr stream, char *data, size_t nbytes)
+esxStreamRecvFlags(virStreamPtr stream,
+   char *data,
+   size_t nbytes,
+   unsigned int flags)
 {
 int result = -1;
 esxStreamPrivate *priv = stream->privateData;
 int status;
 
+virCheckFlags(0, -1);
+
 if (nbytes == 0)
 return 0;
 
@@ -317,6 +322,14 @@ esxStreamRecv(virStreamPtr stream, char *data, size_t 
nbytes)
 return result;
 }
 
+static int
+esxStreamRecv(virStreamPtr stream,
+  char *data,
+  size_t nbytes)
+{
+return esxStreamRecvFlags(stream, data, nbytes, 0);
+}
+
 static void
 esxFreeStreamPrivate(esxStreamPrivate **priv)
 {
@@ -369,6 +382,7 @@ esxStreamAbort(virStreamPtr stream)
 virStreamDriver esxStreamDriver = {
 .streamSend = esxStreamSend,
 .streamRecv = esxStreamRecv,
+.streamRecvFlags = esxStreamRecvFlags,
 /* FIXME: streamAddCallback missing */
 /* FIXME: streamUpdateCallback missing */
 /* FIXME: streamRemoveCallback missing */
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 77250ea56..e79e796f2 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -5641,15 +5641,19 @@ remoteStreamSend(virStreamPtr st,
 
 
 static int
-remoteStreamRecv(virStreamPtr st,
- char *data,
- size_t nbytes)
+remoteStreamRecvFlags(virStreamPtr st,
+  char *data,
+  size_t nbytes,
+  unsigned int flags)
 {
-VIR_DEBUG("st=%p data=%p nbytes=%zu", st, data, nbytes);
+VIR_DEBUG("st=%p data=%p nbytes=%zu flags=%x",
+  st, data, nbytes, flags);
 struct private_data *priv = st->conn->privateData;
 virNetClientStreamPtr privst = st->privateData;
 int rv;
 
+virCheckFlags(0, -1);
+
 if (virNetClientStreamRaiseError(privst))
 return -1;
 
@@ -5671,6 +5675,14 @@ remoteStreamRecv(virStreamPtr st,
 return rv;
 }
 
+static int
+remoteStreamRecv(virStreamPtr st,
+ char *data,
+ size_t nbytes)
+{
+return remoteStreamRecvFlags(st, data, nbytes, 0);
+}
+
 struct remoteStreamCallbackData {
 virStreamPtr st;
 virStreamEventCallback cb;
@@ -5843,6 +5855,7 @@ remoteStreamAbort(virStreamPtr st)
 
 static virStreamDriver remoteStreamDrv = {
 .streamRecv = remoteStreamRecv,
+.streamRecvFlags = remoteStreamRecvFlags,
 .streamSend = remoteStreamSend,
 .streamFinish = remoteStreamFinish,
 .streamAbort = remoteStreamAbort,
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 17/31] virnetclientstream: Introduce virNetClientStreamSendHole

2017-05-16 Thread Michal Privoznik
While the previous commit implemented a helper for sending a
STREAM_HOLE packet for daemon, this is a client's counterpart.

Signed-off-by: Michal Privoznik 
---
 src/libvirt_remote.syms  |  1 +
 src/rpc/virnetclientstream.c | 54 
 src/rpc/virnetclientstream.h |  5 
 3 files changed, 60 insertions(+)

diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index bb6a8d465..186d2c622 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -53,6 +53,7 @@ virNetClientStreamNew;
 virNetClientStreamQueuePacket;
 virNetClientStreamRaiseError;
 virNetClientStreamRecvPacket;
+virNetClientStreamSendHole;
 virNetClientStreamSendPacket;
 virNetClientStreamSetError;
 
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index 4c27f308e..9005e6be9 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -429,6 +429,60 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
 }
 
 
+int
+virNetClientStreamSendHole(virNetClientStreamPtr st,
+   virNetClientPtr client,
+   long long length,
+   unsigned int flags)
+{
+virNetMessagePtr msg = NULL;
+virNetStreamHole data;
+int ret = -1;
+
+VIR_DEBUG("st=%p length=%llu", st, length);
+
+if (!st->allowSkip) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("Skipping is not supported with this stream"));
+return -1;
+}
+
+memset(, 0, sizeof(data));
+data.length = length;
+data.flags = flags;
+
+if (!(msg = virNetMessageNew(false)))
+return -1;
+
+virObjectLock(st);
+
+msg->header.prog = virNetClientProgramGetProgram(st->prog);
+msg->header.vers = virNetClientProgramGetVersion(st->prog);
+msg->header.status = VIR_NET_CONTINUE;
+msg->header.type = VIR_NET_STREAM_HOLE;
+msg->header.serial = st->serial;
+msg->header.proc = st->proc;
+
+virObjectUnlock(st);
+
+if (virNetMessageEncodeHeader(msg) < 0)
+goto cleanup;
+
+if (virNetMessageEncodePayload(msg,
+   (xdrproc_t) xdr_virNetStreamHole,
+   ) < 0)
+goto cleanup;
+
+if (virNetClientSendNoReply(client, msg) < 0)
+goto cleanup;
+
+ret = 0;
+ cleanup:
+virNetMessageFree(msg);
+return ret;
+}
+
+
 int virNetClientStreamEventAddCallback(virNetClientStreamPtr st,
int events,
virNetClientStreamEventCallback cb,
diff --git a/src/rpc/virnetclientstream.h b/src/rpc/virnetclientstream.h
index f3bc0672b..c25c69bb1 100644
--- a/src/rpc/virnetclientstream.h
+++ b/src/rpc/virnetclientstream.h
@@ -61,6 +61,11 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
  size_t nbytes,
  bool nonblock);
 
+int virNetClientStreamSendHole(virNetClientStreamPtr st,
+   virNetClientPtr client,
+   long long length,
+   unsigned int flags);
+
 int virNetClientStreamEventAddCallback(virNetClientStreamPtr st,
int events,
virNetClientStreamEventCallback cb,
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 10/31] Introduce virStreamInData

2017-05-16 Thread Michal Privoznik
This is just an internal API, that calls corresponding function
in stream driver. This function will set @data=1 if the
underlying file is in data section, or @data=0 if it is in a
hole. At any rate, @length is set to number of bytes remaining in
the section the file currently is.

Signed-off-by: Michal Privoznik 
---
 src/driver-stream.h  |  6 ++
 src/libvirt-stream.c | 48 
 src/libvirt_internal.h   |  4 
 src/libvirt_private.syms |  1 +
 4 files changed, 59 insertions(+)

diff --git a/src/driver-stream.h b/src/driver-stream.h
index 0fb56ebd2..f207bf0eb 100644
--- a/src/driver-stream.h
+++ b/src/driver-stream.h
@@ -51,6 +51,11 @@ typedef int
 long long *length,
 unsigned int flags);
 
+typedef int
+(*virDrvStreamInData)(virStreamPtr st,
+  int *data,
+  long long *length);
+
 typedef int
 (*virDrvStreamEventAddCallback)(virStreamPtr stream,
 int events,
@@ -80,6 +85,7 @@ struct _virStreamDriver {
 virDrvStreamRecvFlags streamRecvFlags;
 virDrvStreamSendHole streamSendHole;
 virDrvStreamRecvHole streamRecvHole;
+virDrvStreamInData streamInData;
 virDrvStreamEventAddCallback streamEventAddCallback;
 virDrvStreamEventUpdateCallback streamEventUpdateCallback;
 virDrvStreamEventRemoveCallback streamEventRemoveCallback;
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index 4cbe5eee1..30c305035 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -481,6 +481,54 @@ virStreamRecvHole(virStreamPtr stream,
 }
 
 
+/**
+ * virStreamInData:
+ * @stream: stream
+ * @data: are we in data or hole
+ * @length: length to next section
+ *
+ * This function checks the underlying stream (typically a file)
+ * to learn whether the current stream position lies within a
+ * data section or a hole. Upon return @data is set to a nonzero
+ * value if former is the case, or to zero if @stream is in a
+ * hole. Moreover, @length is updated to tell caller how many
+ * bytes can be read from @stream until current section changes
+ * (from data to a hole or vice versa).
+ *
+ * NB: there's an implicit hole at EOF. In this situation this
+ * function should set @data = false, @length = 0 and return 0.
+ *
+ * To sum it up:
+ *
+ * data section: @data = true,  @length > 0
+ * hole: @data = false, @length > 0
+ * EOF:  @data = false, @length = 0
+ *
+ * Returns 0 on success,
+ *-1 otherwise
+ */
+int
+virStreamInData(virStreamPtr stream,
+int *data,
+long long *length)
+{
+VIR_DEBUG("stream=%p, data=%p, length=%p", stream, data, length);
+
+/* No checks of arguments or error resetting. This is an
+ * internal function that just happen to live next to some
+ * public functions of ours. */
+
+if (stream->driver->streamInData) {
+int ret;
+ret = (stream->driver->streamInData)(stream, data, length);
+return ret;
+}
+
+virReportUnsupportedError();
+return -1;
+}
+
+
 /**
  * virStreamSendAll:
  * @stream: pointer to the stream object
diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h
index 96439d840..62f490a7d 100644
--- a/src/libvirt_internal.h
+++ b/src/libvirt_internal.h
@@ -294,4 +294,8 @@ virTypedParameterValidateSet(virConnectPtr conn,
  virTypedParameterPtr params,
  int nparams);
 
+int virStreamInData(virStreamPtr stream,
+int *data,
+long long *length);
+
 #endif
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4102a002b..a1447eb44 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1124,6 +1124,7 @@ virStateCleanup;
 virStateInitialize;
 virStateReload;
 virStateStop;
+virStreamInData;
 
 
 # locking/domain_lock.h
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 05/31] Introduce virStreamSendHole

2017-05-16 Thread Michal Privoznik
This API is used to tell the other side of the stream to skip
some bytes in the stream. This can be used to create a sparse
file on the receiving side of a stream.

It takes @length argument, which says how big the hole is. This
skipping is done from the current point of stream. Since our
streams are not rewindable like regular files, we don't need
@whence argument like seek(2) has.

Signed-off-by: Michal Privoznik 
---
 include/libvirt/libvirt-stream.h |  4 +++
 src/driver-stream.h  |  6 
 src/libvirt-stream.c | 61 
 src/libvirt_public.syms  |  1 +
 4 files changed, 72 insertions(+)

diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index bee25168b..14c9af142 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -50,6 +50,10 @@ int virStreamRecvFlags(virStreamPtr st,
size_t nbytes,
unsigned int flags);
 
+int virStreamSendHole(virStreamPtr st,
+  long long length,
+  unsigned int flags);
+
 
 /**
  * virStreamSourceFunc:
diff --git a/src/driver-stream.h b/src/driver-stream.h
index d4b048018..0a5201431 100644
--- a/src/driver-stream.h
+++ b/src/driver-stream.h
@@ -41,6 +41,11 @@ typedef int
  size_t nbytes,
  unsigned int flags);
 
+typedef int
+(*virDrvStreamSendHole)(virStreamPtr st,
+long long length,
+unsigned int flags);
+
 typedef int
 (*virDrvStreamEventAddCallback)(virStreamPtr stream,
 int events,
@@ -68,6 +73,7 @@ struct _virStreamDriver {
 virDrvStreamSend streamSend;
 virDrvStreamRecv streamRecv;
 virDrvStreamRecvFlags streamRecvFlags;
+virDrvStreamSendHole streamSendHole;
 virDrvStreamEventAddCallback streamEventAddCallback;
 virDrvStreamEventUpdateCallback streamEventUpdateCallback;
 virDrvStreamEventRemoveCallback streamEventRemoveCallback;
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index 7535deb3c..a09896dcd 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -344,6 +344,67 @@ virStreamRecvFlags(virStreamPtr stream,
 }
 
 
+/**
+ * virStreamSendHole:
+ * @stream: pointer to the stream object
+ * @length: number of bytes to skip
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Rather than transmitting empty file space, this API directs
+ * the @stream target to create @length bytes of empty space.
+ * This API would be used when uploading or downloading sparsely
+ * populated files to avoid the needless copy of empty file
+ * space.
+ *
+ * An example using this with a hypothetical file upload API
+ * looks like:
+ *
+ *   virStream st;
+ *
+ *   while (1) {
+ * char buf[4096];
+ * size_t len;
+ * if (..in hole...) {
+ *   ..get hole size...
+ *   virStreamSendHole(st, len, 0);
+ * } else {
+ *   ...read len bytes...
+ *   virStreamSend(st, buf, len);
+ * }
+ *   }
+ *
+ * Returns 0 on success,
+ *-1 error
+ */
+int
+virStreamSendHole(virStreamPtr stream,
+  long long length,
+  unsigned int flags)
+{
+VIR_DEBUG("stream=%p, length=%lld flags=%x",
+  stream, length, flags);
+
+virResetLastError();
+
+virCheckStreamReturn(stream, -1);
+
+if (stream->driver &&
+stream->driver->streamSendHole) {
+int ret;
+ret = (stream->driver->streamSendHole)(stream, length, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+
+virReportUnsupportedError();
+
+ error:
+virDispatchError(stream->conn);
+return -1;
+}
+
+
 /**
  * virStreamSendAll:
  * @stream: pointer to the stream object
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index d50b36a24..3be7cc6a0 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -762,6 +762,7 @@ LIBVIRT_3.1.0 {
 LIBVIRT_3.4.0 {
 global:
 virStreamRecvFlags;
+virStreamSendHole;
 } LIBVIRT_3.1.0;
 
 #  define new API here using predicted next version number 
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 13/31] RPC: Introduce virNetStreamHole

2017-05-16 Thread Michal Privoznik
This is going to be RPC representation for virStreamSendHole.

Signed-off-by: Michal Privoznik 
---
 src/rpc/virnetprotocol.x   | 5 +
 src/virnetprotocol-structs | 4 
 2 files changed, 9 insertions(+)

diff --git a/src/rpc/virnetprotocol.x b/src/rpc/virnetprotocol.x
index 9ce33b073..cab047cb0 100644
--- a/src/rpc/virnetprotocol.x
+++ b/src/rpc/virnetprotocol.x
@@ -236,3 +236,8 @@ struct virNetMessageError {
 int int2;
 virNetMessageNetwork net; /* unused */
 };
+
+struct virNetStreamHole {
+hyper length;
+unsigned int flags;
+};
diff --git a/src/virnetprotocol-structs b/src/virnetprotocol-structs
index af4526c90..aa6e0602a 100644
--- a/src/virnetprotocol-structs
+++ b/src/virnetprotocol-structs
@@ -42,3 +42,7 @@ struct virNetMessageError {
 intint2;
 virNetMessageNetwork   net;
 };
+struct virNetStreamHole {
+int64_tlength;
+u_int  flags;
+};
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 07/31] Introduce VIR_STREAM_RECV_STOP_AT_HOLE flag

2017-05-16 Thread Michal Privoznik
Add a new flag to virStreamRecvFlags in order to handle being able to
stop reading from the stream so that the consumer can generate a "hole"
in stream target. Generation of a hole replaces the need to receive and
handle a sequence of zero bytes for sparse stream targets.

Signed-off-by: Michal Privoznik 
---
 include/libvirt/libvirt-stream.h |  4 
 src/libvirt-stream.c | 34 +-
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index feaa8ad64..c4baaf7a3 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -45,6 +45,10 @@ int virStreamRecv(virStreamPtr st,
   char *data,
   size_t nbytes);
 
+typedef enum {
+VIR_STREAM_RECV_STOP_AT_HOLE = (1 << 0),
+} virStreamRecvFlagsValues;
+
 int virStreamRecvFlags(virStreamPtr st,
char *data,
size_t nbytes,
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index dc0dc9ea3..bedb6159a 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -290,7 +290,7 @@ virStreamRecv(virStreamPtr stream,
  * @stream: pointer to the stream object
  * @data: buffer to read into from stream
  * @nbytes: size of @data buffer
- * @flags: extra flags; not used yet, so callers should always pass 0
+ * @flags: bitwise-OR of virStreamRecvFlagsValues
  *
  * Reads a series of bytes from the stream. This method may
  * block the calling application for an arbitrary amount
@@ -300,6 +300,33 @@ virStreamRecv(virStreamPtr stream,
  * @flags. Calling this function with no @flags set (equal to
  * zero) is equivalent to calling virStreamRecv(stream, data, nbytes).
  *
+ * If flag VIR_STREAM_RECV_STOP_AT_HOLE is set, this function
+ * will stop reading from stream if it has reached a hole. In
+ * that case, -3 is returned and virStreamRecvHole() should be
+ * called to get the hole size. An example using this flag might
+ * look like this:
+ *
+ *   while (1) {
+ * char buf[4096];
+ *
+ * int ret = virStreamRecvFlags(st, buf, len, VIR_STREAM_STOP_AT_HOLE);
+ * if (ret < 0) {
+ *   if (ret == -3) {
+ * long long len;
+ * ret = virStreamRecvHole(st, , 0);
+ * if (ret < 0) {
+ *   ...error..
+ * } else {
+ *   ...seek len bytes in target...
+ * }
+ *   } else {
+ * return -1;
+ *   }
+ * } else {
+ * ...write buf to target...
+ * }
+ *   }
+ *
  * Returns 0 when the end of the stream is reached, at
  * which time the caller should invoke virStreamFinish()
  * to get confirmation of stream completion.
@@ -310,6 +337,9 @@ virStreamRecv(virStreamPtr stream,
  *
  * Returns -2 if there is no data pending to be read & the
  * stream is marked as non-blocking.
+ *
+ * Returns -3 if there is a hole in stream and caller requested
+ * to stop at a hole.
  */
 int
 virStreamRecvFlags(virStreamPtr stream,
@@ -331,6 +361,8 @@ virStreamRecvFlags(virStreamPtr stream,
 ret = (stream->driver->streamRecvFlags)(stream, data, nbytes, flags);
 if (ret == -2)
 return -2;
+if (ret == -3)
+return -3;
 if (ret < 0)
 goto error;
 return ret;
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 02/31] util: Introduce virFileInData

2017-05-16 Thread Michal Privoznik
This function takes a FD and determines whether the current
position is in data section or in a hole. In addition to that,
it also determines how much bytes are there remaining till the
current section ends.

Signed-off-by: Michal Privoznik 
---
 src/libvirt_private.syms |   1 +
 src/util/virfile.c   |  82 +++
 src/util/virfile.h   |   4 +
 tests/virfiletest.c  | 203 +++
 4 files changed, 290 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index bbe283529..4102a002b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1628,6 +1628,7 @@ virFileGetHugepageSize;
 virFileGetMountReverseSubtree;
 virFileGetMountSubtree;
 virFileHasSuffix;
+virFileInData;
 virFileIsAbsPath;
 virFileIsDir;
 virFileIsExecutable;
diff --git a/src/util/virfile.c b/src/util/virfile.c
index ea44a647c..5b10f9489 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -3793,6 +3793,88 @@ virFileComparePaths(const char *p1, const char *p2)
  cleanup:
 VIR_FREE(res1);
 VIR_FREE(res2);
+
+return ret;
+}
+
+
+int
+virFileInData(int fd,
+  int *inData,
+  long long *length)
+{
+int ret = -1;
+off_t cur, data, hole, end;
+
+/* Get current position */
+cur = lseek(fd, 0, SEEK_CUR);
+if (cur == (off_t) -1) {
+virReportSystemError(errno, "%s",
+ _("Unable to get current position in file"));
+goto cleanup;
+}
+
+/* Now try to get data and hole offsets */
+data = lseek(fd, cur, SEEK_DATA);
+
+/* There are four options:
+ * 1) data == cur;  @cur is in data
+ * 2) data > cur; @cur is in a hole, next data at @data
+ * 3) data < 0, errno = ENXIO; either @cur is in trailing hole, or @cur is 
beyond EOF.
+ * 4) data < 0, errno != ENXIO; we learned nothing
+ */
+
+if (data == (off_t) -1) {
+/* cases 3 and 4 */
+if (errno != ENXIO) {
+virReportSystemError(errno, "%s",
+ _("Unable to seek to data"));
+goto cleanup;
+}
+
+*inData = 0;
+/* There are two situations now. There is always an
+ * implicit hole at EOF. However, there might be a
+ * trailing hole just before EOF too. If that's the case
+ * report it. */
+if ((end = lseek(fd, 0, SEEK_END)) == (off_t) -1) {
+virReportSystemError(errno, "%s",
+ _("Unable to seek to EOF"));
+goto cleanup;
+}
+*length = end - cur;
+} else if (data > cur) {
+/* case 2 */
+*inData = 0;
+*length = data - cur;
+} else {
+/* case 1 */
+*inData = 1;
+
+/* We don't know where does the next hole start. Let's
+ * find out. Here we get the same 4 possibilities as
+ * described above.*/
+hole = lseek(fd, data, SEEK_HOLE);
+if (hole == (off_t) -1 || hole == data) {
+/* cases 1, 3 and 4 */
+/* Wait a second. The reason why we are here is
+ * because we are in data. But at the same time we
+ * are in a trailing hole? Wut!? Do the best what we
+ * can do here. */
+virReportSystemError(errno, "%s",
+ _("unable to seek to hole"));
+goto cleanup;
+} else {
+/* case 2 */
+*length = (hole - data);
+}
+}
+
+ret = 0;
+ cleanup:
+/* At any rate, reposition back to where we started. */
+if (cur != (off_t) -1)
+ignore_value(lseek(fd, cur, SEEK_SET));
 return ret;
 }
 
diff --git a/src/util/virfile.h b/src/util/virfile.h
index 38e938f87..57ceb8072 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -348,4 +348,8 @@ int virFileReadValueString(char **value, const char 
*format, ...)
  ATTRIBUTE_FMT_PRINTF(2, 3);
 
 
+int virFileInData(int fd,
+  int *inData,
+  long long *length);
+
 #endif /* __VIR_FILE_H */
diff --git a/tests/virfiletest.c b/tests/virfiletest.c
index 702a76a50..a93bee01a 100644
--- a/tests/virfiletest.c
+++ b/tests/virfiletest.c
@@ -21,6 +21,7 @@
 #include 
 
 #include 
+#include 
 
 #include "testutils.h"
 #include "virfile.h"
@@ -118,6 +119,190 @@ testFileSanitizePath(const void *opaque)
 }
 
 
+static int
+makeSparseFile(const off_t offsets[],
+   const bool startData);
+
+#ifdef __linux__
+/* Create a sparse file. @offsets in KiB. */
+static int
+makeSparseFile(const off_t offsets[],
+   const bool startData)
+{
+int fd = -1;
+char path[] = abs_builddir "fileInData.XX";
+off_t len = 0;
+size_t i;
+
+if ((fd = mkostemp(path,  O_CLOEXEC|O_RDWR)) < 0)
+goto error;
+
+if (unlink(path) < 0)
+goto error;
+
+for (i = 0; offsets[i] != (off_t) -1; i++)
+len += 

[libvirt] [PATCH v3 03/31] Introduce virStreamRecvFlags

2017-05-16 Thread Michal Privoznik
This patch is adding the virStreamRecvFlags as a variant to the
virStreamRecv function in order to allow for future expansion of
functionality for processing sparse streams using a @flags
argument.

Signed-off-by: Michal Privoznik 
---
 include/libvirt/libvirt-stream.h |  5 
 src/driver-stream.h  |  7 +
 src/libvirt-stream.c | 59 
 src/libvirt_public.syms  |  5 
 4 files changed, 76 insertions(+)

diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index 831640d56..bee25168b 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -45,6 +45,11 @@ int virStreamRecv(virStreamPtr st,
   char *data,
   size_t nbytes);
 
+int virStreamRecvFlags(virStreamPtr st,
+   char *data,
+   size_t nbytes,
+   unsigned int flags);
+
 
 /**
  * virStreamSourceFunc:
diff --git a/src/driver-stream.h b/src/driver-stream.h
index 85b4e3bc7..d4b048018 100644
--- a/src/driver-stream.h
+++ b/src/driver-stream.h
@@ -35,6 +35,12 @@ typedef int
 char *data,
 size_t nbytes);
 
+typedef int
+(*virDrvStreamRecvFlags)(virStreamPtr st,
+ char *data,
+ size_t nbytes,
+ unsigned int flags);
+
 typedef int
 (*virDrvStreamEventAddCallback)(virStreamPtr stream,
 int events,
@@ -61,6 +67,7 @@ typedef virStreamDriver *virStreamDriverPtr;
 struct _virStreamDriver {
 virDrvStreamSend streamSend;
 virDrvStreamRecv streamRecv;
+virDrvStreamRecvFlags streamRecvFlags;
 virDrvStreamEventAddCallback streamEventAddCallback;
 virDrvStreamEventUpdateCallback streamEventUpdateCallback;
 virDrvStreamEventRemoveCallback streamEventRemoveCallback;
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index 8384b3720..7535deb3c 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -285,6 +285,65 @@ virStreamRecv(virStreamPtr stream,
 }
 
 
+/**
+ * virStreamRecvFlags:
+ * @stream: pointer to the stream object
+ * @data: buffer to read into from stream
+ * @nbytes: size of @data buffer
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Reads a series of bytes from the stream. This method may
+ * block the calling application for an arbitrary amount
+ * of time.
+ *
+ * This is just like virStreamRecv except this one has extra
+ * @flags. Calling this function with no @flags set (equal to
+ * zero) is equivalent to calling virStreamRecv(stream, data, nbytes).
+ *
+ * Returns 0 when the end of the stream is reached, at
+ * which time the caller should invoke virStreamFinish()
+ * to get confirmation of stream completion.
+ *
+ * Returns -1 upon error, at which time the stream will
+ * be marked as aborted, and the caller should now release
+ * the stream with virStreamFree.
+ *
+ * Returns -2 if there is no data pending to be read & the
+ * stream is marked as non-blocking.
+ */
+int
+virStreamRecvFlags(virStreamPtr stream,
+   char *data,
+   size_t nbytes,
+   unsigned int flags)
+{
+VIR_DEBUG("stream=%p, data=%p, nbytes=%zu flags=%x",
+  stream, data, nbytes, flags);
+
+virResetLastError();
+
+virCheckStreamReturn(stream, -1);
+virCheckNonNullArgGoto(data, error);
+
+if (stream->driver &&
+stream->driver->streamRecvFlags) {
+int ret;
+ret = (stream->driver->streamRecvFlags)(stream, data, nbytes, flags);
+if (ret == -2)
+return -2;
+if (ret < 0)
+goto error;
+return ret;
+}
+
+virReportUnsupportedError();
+
+ error:
+virDispatchError(stream->conn);
+return -1;
+}
+
+
 /**
  * virStreamSendAll:
  * @stream: pointer to the stream object
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 428cf2e19..d50b36a24 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -759,4 +759,9 @@ LIBVIRT_3.1.0 {
 virDomainSetVcpu;
 } LIBVIRT_3.0.0;
 
+LIBVIRT_3.4.0 {
+global:
+virStreamRecvFlags;
+} LIBVIRT_3.1.0;
+
 #  define new API here using predicted next version number 
-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 01/31] virfdstream: Use messages instead of pipe

2017-05-16 Thread Michal Privoznik
One big downside of using the pipe to transfer the data is that
we can really transfer just bare data. No metadata can be carried
through unless some formatted messages are introduced. That would
be quite painful to achieve so let's use a message queue. It's
fairly easy to exchange info between threads now that iohelper is
no longer used.

The reason why we cannot use the FD for plain files directly is
that despite us setting noblock flag on the FD, any
read()/write() blocks regardless (which is a show stopper since
those parts of the code are run from the event loop) and poll()
reports such FD as always readable/writable - even though the
subsequent operation might block.

The pipe is still not gone though. It is used to signal to even
loop that an event occurred (e.g. data are available for reading
in the queue, or vice versa).

Signed-off-by: Michal Privoznik 
---
 src/util/virfdstream.c | 402 ++---
 1 file changed, 350 insertions(+), 52 deletions(-)

diff --git a/src/util/virfdstream.c b/src/util/virfdstream.c
index 5ce78fe58..4b42939e7 100644
--- a/src/util/virfdstream.c
+++ b/src/util/virfdstream.c
@@ -49,6 +49,27 @@
 
 VIR_LOG_INIT("fdstream");
 
+typedef enum {
+VIR_FDSTREAM_MSG_TYPE_DATA,
+} virFDStreamMsgType;
+
+typedef struct _virFDStreamMsg virFDStreamMsg;
+typedef virFDStreamMsg *virFDStreamMsgPtr;
+struct _virFDStreamMsg {
+virFDStreamMsgPtr next;
+
+virFDStreamMsgType type;
+
+union {
+struct {
+char *buf;
+size_t len;
+size_t offset;
+} data;
+} stream;
+};
+
+
 /* Tunnelled migration stream support */
 typedef struct virFDStreamData virFDStreamData;
 typedef virFDStreamData *virFDStreamDataPtr;
@@ -80,18 +101,25 @@ struct virFDStreamData {
 
 /* Thread data */
 virThreadPtr thread;
+virCond threadCond;
 int threadErr;
 bool threadQuit;
+bool threadAbort;
+bool threadDoRead;
+virFDStreamMsgPtr msg;
 };
 
 static virClassPtr virFDStreamDataClass;
 
+static void virFDStreamMsgQueueFree(virFDStreamMsgPtr *queue);
+
 static void
 virFDStreamDataDispose(void *obj)
 {
 virFDStreamDataPtr fdst = obj;
 
 VIR_DEBUG("obj=%p", fdst);
+virFDStreamMsgQueueFree(>msg);
 }
 
 static int virFDStreamDataOnceInit(void)
@@ -108,6 +136,89 @@ static int virFDStreamDataOnceInit(void)
 VIR_ONCE_GLOBAL_INIT(virFDStreamData)
 
 
+static int
+virFDStreamMsgQueuePush(virFDStreamDataPtr fdst,
+virFDStreamMsgPtr msg,
+int fd,
+const char *fdname)
+{
+virFDStreamMsgPtr *tmp = >msg;
+char c = '1';
+
+while (*tmp)
+tmp = &(*tmp)->next;
+
+*tmp = msg;
+virCondSignal(>threadCond);
+
+if (safewrite(fd, , sizeof(c)) != sizeof(c)) {
+virReportSystemError(errno,
+ _("Unable to write to %s"),
+ fdname);
+return -1;
+}
+
+return 0;
+}
+
+
+static virFDStreamMsgPtr
+virFDStreamMsgQueuePop(virFDStreamDataPtr fdst,
+   int fd,
+   const char *fdname)
+{
+virFDStreamMsgPtr tmp = fdst->msg;
+char c;
+
+if (tmp) {
+fdst->msg = tmp->next;
+tmp->next = NULL;
+}
+
+virCondSignal(>threadCond);
+
+if (saferead(fd, , sizeof(c)) != sizeof(c)) {
+virReportSystemError(errno,
+ _("Unable to read from %s"),
+ fdname);
+return NULL;
+}
+
+return tmp;
+}
+
+
+static void
+virFDStreamMsgFree(virFDStreamMsgPtr msg)
+{
+if (!msg)
+return;
+
+switch (msg->type) {
+case VIR_FDSTREAM_MSG_TYPE_DATA:
+VIR_FREE(msg->stream.data.buf);
+break;
+}
+
+VIR_FREE(msg);
+}
+
+
+static void
+virFDStreamMsgQueueFree(virFDStreamMsgPtr *queue)
+{
+virFDStreamMsgPtr tmp = *queue;
+
+while (tmp) {
+virFDStreamMsgPtr next = tmp->next;
+virFDStreamMsgFree(tmp);
+tmp = next;
+}
+
+*queue = NULL;
+}
+
+
 static int virFDStreamRemoveCallback(virStreamPtr stream)
 {
 virFDStreamDataPtr fdst = stream->privateData;
@@ -273,6 +384,7 @@ typedef virFDStreamThreadData *virFDStreamThreadDataPtr;
 struct _virFDStreamThreadData {
 virStreamPtr st;
 size_t length;
+bool doRead;
 int fdin;
 char *fdinname;
 int fdout;
@@ -293,6 +405,86 @@ virFDStreamThreadDataFree(virFDStreamThreadDataPtr data)
 }
 
 
+static ssize_t
+virFDStreamThreadDoRead(virFDStreamDataPtr fdst,
+const int fdin,
+const int fdout,
+const char *fdinname,
+const char *fdoutname,
+size_t buflen)
+{
+virFDStreamMsgPtr msg = NULL;
+char *buf = NULL;
+ssize_t got;
+
+if (VIR_ALLOC(msg) < 0)
+goto error;
+
+if (VIR_ALLOC_N(buf, buflen) < 0)
+goto 

[libvirt] [PATCH v3 00/31] Implement sparse streams for libvirt

2017-05-16 Thread Michal Privoznik
v3 of:

https://www.redhat.com/archives/libvir-list/2017-April/msg00671.html

All the patches can be found on my github:

  https://github.com/zippy2/libvirt/tree/sparse_streams2

diff to v2:
 - renamed APIs from Skip & GetHoleSize to SendHole & RecvHole
 - switched from 'unsigned long long len' to 'long long len' (where len is size 
of a hole)
 - introduced @flags to public APIs for future extensibility
 - couple of coding style fixes
 - couple of fixes suggested by John in review of v2

As expressed earlier, a lot of these patches should have Reviewed-by tag as
John reviewed majority of them. But we don't have a clear agreement when to use
the tag, so I'm not putting it in just yet. However, will do before pushing.

Some patches were ACKed. However, changes described above changed them, so I'm
not sure ACK still stands.

Michal Privoznik (31):
  virfdstream: Use messages instead of pipe
  util: Introduce virFileInData
  Introduce virStreamRecvFlags
  Implement virStreamRecvFlags to some drivers
  Introduce virStreamSendHole
  Introduce virStreamRecvHole
  Introduce VIR_STREAM_RECV_STOP_AT_HOLE flag
  Introduce virStreamSparseRecvAll
  Introduce virStreamSparseSendAll
  Introduce virStreamInData
  virNetClientStreamNew: Track origin stream
  Add new flag to daemonCreateClientStream and virNetClientStreamNew
  RPC: Introduce virNetStreamHole
  Introduce VIR_NET_STREAM_HOLE message type
  Teach wireshark plugin about VIR_NET_STREAM_HOLE
  daemon: Introduce virNetServerProgramSendStreamHole
  virnetclientstream: Introduce virNetClientStreamSendHole
  daemon: Implement VIR_NET_STREAM_HOLE handling
  virnetclientstream: Introduce virNetClientStreamHandleHole
  remote_driver: Implement virStreamSendHole
  virNetClientStreamRecvPacket: Introduce @flags argument
  Introduce virNetClientStreamRecvHole
  remote: Implement virStreamRecvHole
  virNetClientStream: Wire up VIR_NET_STREAM_HOLE
  remote_driver: Implement VIR_STREAM_RECV_STOP_AT_HOLE
  daemonStreamHandleRead: Wire up seekable stream
  fdstream: Implement sparse stream
  gendispatch: Introduce @sparseflag for our calls
  Introduce virStorageVol{Download,Upload}Flags
  virsh: Implement sparse stream to vol-download
  virsh: Implement sparse stream to vol-upload

 daemon/remote.c  |   2 +-
 daemon/stream.c  | 148 -
 daemon/stream.h  |   3 +-
 include/libvirt/libvirt-storage.h|   9 +
 include/libvirt/libvirt-stream.h | 115 ++-
 src/driver-stream.h  |  25 ++
 src/esx/esx_stream.c |  16 +-
 src/libvirt-storage.c|   4 +-
 src/libvirt-stream.c | 526 ++
 src/libvirt_internal.h   |   4 +
 src/libvirt_private.syms |   2 +
 src/libvirt_public.syms  |   9 +
 src/libvirt_remote.syms  |   3 +
 src/remote/remote_driver.c   |  99 +-
 src/remote/remote_protocol.x |   2 +
 src/rpc/gendispatch.pl   |  21 +-
 src/rpc/virnetclient.c   |   1 +
 src/rpc/virnetclientstream.c | 238 +-
 src/rpc/virnetclientstream.h |  18 +-
 src/rpc/virnetprotocol.x |  17 +-
 src/rpc/virnetserverprogram.c|  35 ++
 src/rpc/virnetserverprogram.h|   8 +
 src/storage/storage_driver.c |   4 +-
 src/storage/storage_util.c   |  10 +-
 src/util/virfdstream.c   | 609 +++
 src/util/virfdstream.h   |   1 +
 src/util/virfile.c   |  82 +
 src/util/virfile.h   |   4 +
 src/virnetprotocol-structs   |   5 +
 tests/virfiletest.c  | 203 
 tools/virsh-util.c   |  65 
 tools/virsh-util.h   |  29 ++
 tools/virsh-volume.c |  50 ++-
 tools/virsh.pod  |   6 +-
 tools/wireshark/src/packet-libvirt.c |  52 +++
 tools/wireshark/src/packet-libvirt.h |   2 +
 36 files changed, 2301 insertions(+), 126 deletions(-)

-- 
2.13.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2] qemu: Report shutdown event details

2017-05-16 Thread Martin Kletzander
QEMU will likely report the details of it shutting down, particularly
whether the shutdown was initiated by the guest or host.  We should
forward that information along, at least for shutdown events.  Reset
has that as well, however that is not a lifecycle event and would add
extra constants that might not be used.  It can be added later on.

Since the only way we can extend information provided to the user is
adding event details, we might as well emit multiple events (one with
the reason for the shutdown and keep the one for the shutdown being
finished for clarity and compatibility).

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1384007

Signed-off-by: Martin Kletzander 
---
v2:
 - Adapt to new message format

Patch in QEMU:
https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg03624.html
Applied to qapi-next: 
https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg03742.html

 examples/object-events/event-test.c |  6 ++
 include/libvirt/libvirt-domain.h| 11 ++-
 src/qemu/qemu_monitor.c |  6 +++---
 src/qemu/qemu_monitor.h |  3 ++-
 src/qemu/qemu_monitor_json.c| 10 --
 src/qemu/qemu_process.c | 22 ++
 tools/virsh-domain.c|  5 -
 7 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/examples/object-events/event-test.c 
b/examples/object-events/event-test.c
index 12690cac09ce..d3a81eb4a559 100644
--- a/examples/object-events/event-test.c
+++ b/examples/object-events/event-test.c
@@ -240,6 +240,12 @@ eventDetailToString(int event,
 case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
 return "Finished";

+case VIR_DOMAIN_EVENT_SHUTDOWN_GUEST:
+return "Killed on a guest request";
+
+case VIR_DOMAIN_EVENT_SHUTDOWN_HOST:
+return "Killed on a host request";
+
 case VIR_DOMAIN_EVENT_SHUTDOWN_LAST:
 break;
 }
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index c9e96a6c90bc..de391a9214d1 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -2983,7 +2983,16 @@ typedef enum {
  * Details on the cause of a 'shutdown' lifecycle event
  */
 typedef enum {
-VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0, /* Guest finished shutdown 
sequence */
+/* Guest finished shutdown sequence */
+VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0,
+
+/* Guest is shutting down due to request from guest (e.g. hardware-specific
+ * action) */
+VIR_DOMAIN_EVENT_SHUTDOWN_GUEST = 1,
+
+/* Guest is shutting down due to request from host (e.g. killed by a
+ * signal) */
+VIR_DOMAIN_EVENT_SHUTDOWN_HOST = 2,

 # ifdef VIR_ENUM_SENTINELS
 VIR_DOMAIN_EVENT_SHUTDOWN_LAST
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 2148d483ed6a..a2de1a6c5bad 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1326,13 +1326,13 @@ qemuMonitorEmitEvent(qemuMonitorPtr mon, const char 
*event,


 int
-qemuMonitorEmitShutdown(qemuMonitorPtr mon)
+qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest)
 {
 int ret = -1;
-VIR_DEBUG("mon=%p", mon);
+VIR_DEBUG("mon=%p guest=%u", mon, guest);
 mon->willhangup = 1;

-QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm);
+QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm, guest);
 return ret;
 }

diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 12f98beba763..8956bf929aaa 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -130,6 +130,7 @@ typedef int 
(*qemuMonitorDomainEventCallback)(qemuMonitorPtr mon,
   void *opaque);
 typedef int (*qemuMonitorDomainShutdownCallback)(qemuMonitorPtr mon,
  virDomainObjPtr vm,
+ virTristateBool guest,
  void *opaque);
 typedef int (*qemuMonitorDomainResetCallback)(qemuMonitorPtr mon,
   virDomainObjPtr vm,
@@ -344,7 +345,7 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
 int qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
  long long seconds, unsigned int micros,
  const char *details);
-int qemuMonitorEmitShutdown(qemuMonitorPtr mon);
+int qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest);
 int qemuMonitorEmitReset(qemuMonitorPtr mon);
 int qemuMonitorEmitPowerdown(qemuMonitorPtr mon);
 int qemuMonitorEmitStop(qemuMonitorPtr mon);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 083729003ba3..757595dd7472 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -523,9 +523,15 @@ qemuMonitorJSONKeywordStringToJSON(const char *str, const 
char 

[libvirt] [PATCH] pci: fix link maximum speed detection

2017-05-16 Thread Marek Marczykowski-Górecki
Commit 8e09663 "pci: recognize/report GEN4 (PCIe 4.0) card 16GT/s Link
speed" introduced another speed into enum, but mistakenly also altered
field width, so one bit of link width was included there.

Signed-off-by: Marek Marczykowski-Górecki 
---
 src/util/virpci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/util/virpci.c b/src/util/virpci.c
index 83c7e74..2c1b758 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -147,7 +147,7 @@ struct _virPCIDeviceList {
 #define PCI_EXP_DEVCAP  0x4 /* Device capabilities */
 #define PCI_EXP_DEVCAP_FLR (1<<28)  /* Function Level Reset */
 #define PCI_EXP_LNKCAP  0xc /* Link Capabilities */
-#define PCI_EXP_LNKCAP_SPEED0x0001f /* Maximum Link Speed */
+#define PCI_EXP_LNKCAP_SPEED0xf /* Maximum Link Speed */
 #define PCI_EXP_LNKCAP_WIDTH0x003f0 /* Maximum Link Width */
 #define PCI_EXP_LNKSTA  0x12/* Link Status */
 #define PCI_EXP_LNKSTA_SPEED0x000f  /* Negotiated Link Speed */
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] limit pps via bandwidth

2017-05-16 Thread Michal Privoznik
On 05/15/2017 09:31 PM, Vasiliy Tolstov wrote:
> Hi. I have a problem that some vps generate very big pps (50). I
> want to limit it for some reasonable value. iptables does not support
> by default limit by pps more that 1, i can use nft... but
> Why not use tc for this ?
> http://www.lartc.org/manpages/tc-pbfifo.html
> http://man7.org/linux/man-pages/man8/tc-sfb.8.html
> 
> As i understand firstly we can limit by pps and secondly via bandwidth...
> What do you think?
> 

That's exactly what  is for. Although, we don't support pps
based limiting rather than bps based rate limiting, but I believe the
latter has wider usage range.

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2] Provide a useful README file

2017-05-16 Thread Daniel P. Berrange
The current README file contents has almost no useful info, and that
which does exist is very outdated.

Signed-off-by: Daniel P. Berrange 
---

In v2:

 - Use markdown syntax
 - Use README.md file
 - Symlink README to README.md
 - Include travis build status

 README| 14 +--
 README.md | 79 +++
 2 files changed, 80 insertions(+), 13 deletions(-)
 mode change 100644 => 12 README
 create mode 100644 README.md

diff --git a/README b/README
deleted file mode 100644
index 3d5167d..000
--- a/README
+++ /dev/null
@@ -1,13 +0,0 @@
-
- LibVirt : simple API for virtualization
-
-  Libvirt is a C toolkit to interact with the virtualization capabilities
-of recent versions of Linux (and other OSes). It is free software
-available under the GNU Lesser General Public License. Virtualization of
-the Linux Operating System means the ability to run multiple instances of
-Operating Systems concurrently on a single hardware system where the basic
-resources are driven by a Linux instance. The library aim at providing
-long term stable C API initially for the Xen paravirtualization but
-should be able to integrate other virtualization mechanisms if needed.
-
-Daniel Veillard 
diff --git a/README b/README
new file mode 12
index 000..42061c0
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 000..c2bd2f8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,79 @@
+[![Build 
Status](https://travis-ci.org/libvirt/libvirt.svg)](https://travis-ci.org/libvirt/libvirt)
+
+Libvirt API for virtualization
+==
+
+Libvirt provides a portable, long term stable C API for managing the
+virtualization technologies provided by many operating systems. It
+includes support for QEMU, KVM, Xen, LXC, BHyve, Virtuozzo, VMWare
+vCenter and ESX, VMWare Desktop, Hyper-V, VirtualBox and PowerHyp.
+
+For some of these hypervisors, it provides a stateful management
+daemon runs on the virtualization host allowing access to the API
+both by non-privileged local users and remote users.
+
+Layered packages provide bindings of the Libvirt C API into other
+languages including Python, Perl, Php, Go, Java, OCaml, as well as
+mappings into object systems such as GObject, CIM and SNMP.
+
+Further information about the libvirt project can be found on the
+website:
+
+*  
+
+License
+---
+
+The libvirt C API is distributed under the terms of GNU Lesser General
+Public License, version 2.1 (or later). Some parts of the code that are
+not part of the C library, may have the more restricted GNU General
+Public License, version 2.1 (or later). See the files COPYING.LESSER
+and COPYING for full license terms & conditions.
+
+Installation
+
+
+Libvirt uses the GNU Autotools build system, so in general can be built
+and installed with the normal commands. For example, to build in a manner
+that is suitable for installing as root, use:
+
+```
+# ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
+# make
+# sudo make install
+```
+
+While to build & install as an unprivileged user
+
+```
+# ./configure --prefix=$HOME/usr
+#  make
+#  make install
+```
+
+
+The libvirt code relies on a large number of 3rd party libraries. These will
+be detected during execution of the configure script and a summary printed
+which lists any missing (optional) dependancies.
+
+Contributing
+
+
+The libvirt project welcomes contributors from all. For most components
+the best way to contributor is to send patches to the primary development
+mailing list, using the 'git send-email' command. Further guidance on this
+can be found in the HACKING file, or the project website
+
+* 
+
+Contact
+---
+
+The libvirt project has two primary mailing lists:
+
+ * libvir-list@redhat.com (**for development**)
+ * libvirt-us...@redhat.com (**for users**)
+
+Further details on contacting the project are available on the website
+
+* 
-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] Provide a useful README file

2017-05-16 Thread Daniel P. Berrange
On Tue, May 16, 2017 at 01:54:30PM +0200, Martin Kletzander wrote:
> On Tue, May 16, 2017 at 11:50:27AM +0100, Daniel P. Berrange wrote:
> > The current README file contents has almost no useful info, and that
> > which does exist is very outdated.
> > 
> > Signed-off-by: Daniel P. Berrange 
> > ---
> > README | 81 
> > +-
> > 1 file changed, 71 insertions(+), 10 deletions(-)
> > 
> 
> This is great and all, but if we are making this better, why not take
> the opportunity to use some plaintext format that has few features?  I,
> personally, don't care whether that's org, markdown or rst.  Just
> something that is still usable and readable as a plaintext file while it
> can be nicely formatted (with headers, links and images) on pages that
> support it (e.g. github).  I know this seems like stupid wannabe modern
> tiny thing, but there are many nuances that can potentially influence
> future contributors.  And I think this is one of the positive ones.

Sure, I can do that.


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] Provide a useful README file

2017-05-16 Thread Martin Kletzander

On Tue, May 16, 2017 at 11:50:27AM +0100, Daniel P. Berrange wrote:

The current README file contents has almost no useful info, and that
which does exist is very outdated.

Signed-off-by: Daniel P. Berrange 
---
README | 81 +-
1 file changed, 71 insertions(+), 10 deletions(-)



This is great and all, but if we are making this better, why not take
the opportunity to use some plaintext format that has few features?  I,
personally, don't care whether that's org, markdown or rst.  Just
something that is still usable and readable as a plaintext file while it
can be nicely formatted (with headers, links and images) on pages that
support it (e.g. github).  I know this seems like stupid wannabe modern
tiny thing, but there are many nuances that can potentially influence
future contributors.  And I think this is one of the positive ones.

Martin


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH] Provide a useful README file

2017-05-16 Thread Daniel P. Berrange
The current README file contents has almost no useful info, and that
which does exist is very outdated.

Signed-off-by: Daniel P. Berrange 
---
 README | 81 +-
 1 file changed, 71 insertions(+), 10 deletions(-)

diff --git a/README b/README
index 3d5167d..7103ae9 100644
--- a/README
+++ b/README
@@ -1,13 +1,74 @@
+ Libvirt API for virtualization
+==
 
- LibVirt : simple API for virtualization
+Libvirt provides a portable, long term stable C API for managing the
+virtualization technologies provided by many operating systems. It
+includes support for QEMU, KVM, Xen, LXC, BHyve, Virtuozzo, VMWare
+vCenter and ESX, VMWare Desktop, Hyper-V, VirtualBox and PowerHyp.
 
-  Libvirt is a C toolkit to interact with the virtualization capabilities
-of recent versions of Linux (and other OSes). It is free software
-available under the GNU Lesser General Public License. Virtualization of
-the Linux Operating System means the ability to run multiple instances of
-Operating Systems concurrently on a single hardware system where the basic
-resources are driven by a Linux instance. The library aim at providing
-long term stable C API initially for the Xen paravirtualization but
-should be able to integrate other virtualization mechanisms if needed.
+For some of these hypervisors, it provides a stateful management
+daemon runs on the virtualization host allowing access to the API
+both by non-privileged local users and remote users.
 
-Daniel Veillard 
+Layered packages provide bindings of the Libvirt C API into other
+languages including Python, Perl, Php, Go, Java, OCaml, as well as
+mappings into object systems such as GObject, CIM and SNMP.
+
+Further information about the libvirt project can be found on the
+website:
+
+  https://libvirt.org
+
+License
+===
+
+The libvirt C API is distributed under the terms of GNU Lesser General
+Public License, version 2.1 (or later). Some parts of the code that are
+not part of the C library, may have the more restricted GNU General
+Public License, version 2.1 (or later). See the files COPYING.LESSER
+and COPYING for full license terms & conditions.
+
+Installation
+
+
+Libvirt uses the GNU Autotools build system, so in general can be built
+and installed with the normal commands. For example, to build in a manner
+that is suitable for installing as root, use:
+
+  ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
+  make
+  sudo make install
+
+While to build & install as an unprivileged user
+
+  ./configure --prefix=$HOME/usr
+  make
+  make install
+
+The libvirt code relies on a large number of 3rd party libraries. These will
+be detected during execution of the configure script and a summary printed
+which lists any missing (optional) dependancies.
+
+Contributing
+
+
+The libvirt project welcomes contributors from all. For most components
+the best way to contributor is to send patches to the primary development
+mailing list, using the 'git send-email' command. Further guidance on this
+can be found in the HACKING file, or the project website
+
+  https://libvirt.org/contribute.html
+
+Contact
+===
+
+The libvirt project has two primary mailing lists:
+
+  * libvir-list@redhat.com (for development)
+  * libvirt-us...@redhat.com (for users)
+
+Further details on contacting the project are available on the website
+
+  https://libvirt.org/contact.html
+
+-- End
-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] virsh: add --domain option for domain-to-native

2017-05-16 Thread Martin Kletzander

On Mon, May 15, 2017 at 04:29:48AM -0400, Daniel Liu wrote:

Fix bug 835476[1].


It's enough to mention it below (as you did).


virsh: add [--domain DOMAIN] option to  domxml-to-native DOMAIN COMMAND


This first line is already in the subject.


Add support for the following syntax:
domxml-to-native  { [--domain DOMAIN] | [XML] }, i.e., it supports
either designating domain (domain id, uuid, or name), or path to XML domain
configuration file.



I would reword this a little bit.  How would you feel about something
along the lines of:

 The option allows someone to run domain-to-native on already existing
 domain without the need of supplying their XML.  It is basically
 wrapper around `virsh dumpxml $dom | virsh domxml-to-native /dev/stdin`.

 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=835476


E.g.:
virsh domxml-to-native qemu-argv --domain RHEL7.3   # domain name
virsh domxml-to-native qemu-argv --domain 10# domain id
virsh domxml-to-native qemu-argv dumped_dom.xml # dumped xml

[1] https://bugzilla.redhat.com/show_bug.cgi?id=835476
---
tools/virsh-domain.c | 54 ++--
1 file changed, 44 insertions(+), 10 deletions(-)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 0d19d0e01..a79fd3ab2 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -9840,9 +9840,13 @@ static const vshCmdOptDef opts_domxmltonative[] = {
 .flags = VSH_OFLAG_REQ,
 .help = N_("target config data type format")
},
+{.name = "domain",
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ_OPT,
+ .help = N_("domain name, id or uuid")
+},
{.name = "xml",
 .type = VSH_OT_DATA,
- .flags = VSH_OFLAG_REQ,
 .help = N_("xml data file to export from")
},
{.name = NULL}
@@ -9851,30 +9855,60 @@ static const vshCmdOptDef opts_domxmltonative[] = {
static bool
cmdDomXMLToNative(vshControl *ctl, const vshCmd *cmd)
{
-bool ret = true;
+bool ret = false;
const char *format = NULL;
-const char *xmlFile = NULL;
-char *configData;
-char *xmlData;
+const char *domain = NULL;
+const char *xml = NULL;
+char *xmlData = NULL;
+char *configData = NULL;
unsigned int flags = 0;
virshControlPtr priv = ctl->privData;
+virDomainPtr dom = NULL;

-if (vshCommandOptStringReq(ctl, cmd, "format", ) < 0 ||
-vshCommandOptStringReq(ctl, cmd, "xml", ) < 0)


If this was already there, you could keep using it.  But that's not a
big deal for me, just some others might not like it.


+if (vshCommandOptStringReq(ctl, cmd, "format", ) < 0)
+return false;
+
+if (vshCommandOptStringReq(ctl, cmd, "domain", ) < 0)
+return false;
+


[1] So here you get the domain name/id/uuid ...


+if (vshCommandOptStringReq(ctl, cmd, "xml", ) < 0)
return false;

-if (virFileReadAll(xmlFile, VSH_MAX_XML_FILE, ) < 0)
+VSH_EXCLUSIVE_OPTIONS_VAR(domain, xml);
+
+if (domain)
+dom = virshCommandOptDomain(ctl, cmd, );
+


... and here you get the object.  What do you supply as the third
parameter?  Check what the function does.  There's a leak that you will
fix by getting rid of the lines above [1].  And just supply NULL here.

Also make sure  is not NULL here, in case someone supplies
non-existing domain name.


+if (!dom && !xml) {
+vshError(ctl, _("need either domain (ID, UUID, or name) or domain XML 
configuration file path"));
return false;
+}
+
+if (dom) {
+xmlData = virDomainGetXMLDesc(dom, flags);
+if (xmlData == NULL)
+goto cleanup;
+}
+
+if (xml) {
+if (virFileReadAll(xml, VSH_MAX_XML_FILE, ) < 0)
+goto cleanup;
+}



This ^^ would be more readable as:

if (dom) {
  xmlData = blah;
} else if (xml) {
  readFile(asdf, );
}

if (!xmlData) {
 vshError(ctl, "%s",
  _("Either  or --domain must be suppied"));


Or something in that regard.


configData = virConnectDomainXMLToNative(priv->conn, format, xmlData, 
flags);
if (configData != NULL) {
vshPrint(ctl, "%s", configData);
-VIR_FREE(configData);
+ret = true;
+goto cleanup;
} else {
-ret = false;
+vshError(ctl, _("convert from domain XML to native command failed"));
+goto cleanup;
}


Since you are changing this...  This does not look like all the other
places in libvirt.  What we do _almost_ exclusively is:

 something = func();
 if (!func) {
 handle error;
 goto somewhere;
 }

 what = should + continue(in.case->of.no();

 ret = success code;
cleanup:
 stuff to clean up;


I would not normally mention it, but since you are changing that part
anyway, it could be cleaned up so that it does what other parts of the
code do.  Or just keep it as it is.  It's small and right before the
cleanup, so it's _kinda_ OK (i.e. we don't have a rule written down in
the coding style for this).

Otherwise it's fine ;)

Martin



Re: [libvirt] [PATCH v3] qemu: improve detection of UNIX path generated by libvirt

2017-05-16 Thread Martin Kletzander

On Fri, May 12, 2017 at 05:17:33PM +0200, Pavel Hrdina wrote:

Currently we consider all UNIX paths with specific prefix as generated
by libvirt, but that's a wrong assumption.  Let's make the detection
better by actually checking whether the whole path matches one of the
paths that we generate or generated in the past.

The UNIX path isn't stored in config XML since libvirt-1.3.1.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1446980

Signed-off-by: Pavel Hrdina 
---
src/qemu/qemu_domain.c | 66 +-
.../qemuxml2argv-channel-unix-source-path.xml  | 29 ++
.../qemuxml2xmlout-channel-unix-source-path.xml| 45 +++
tests/qemuxml2xmltest.c|  2 +
4 files changed, 128 insertions(+), 14 deletions(-)
create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-channel-unix-source-path.xml
create mode 100644 
tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-unix-source-path.xml



ACK


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [RFC] qemu: monitor: do not report error on shutdown

2017-05-16 Thread Martin Kletzander

On Thu, Mar 09, 2017 at 10:59:45AM +0100, Christian Ehrhardt wrote:

On Thu, Mar 9, 2017 at 10:54 AM, Christian Ehrhardt <
christian.ehrha...@canonical.com> wrote:


In those cases do not report an
internal error like:
  "internal error: End of file from qemu monitor"



There is some extra background on the issue that shall be fixed at [1].
According to my experiments this seems to happen in general (various
distros, upstream), but since my gut feeling isn't sure if I might have
followed a red-herring I explicitly marked the patch as RFC for now.

Note: I also have seen similar EOF messages of virtlogd on guest start that
I have not looked at yet

[1]: https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1582990



Either I forgot to reply or the reply got lost (it wouldn't be the first
time).  I found the patch usable as-is, not only as an RFC.  Even though
I have yet to encounter such error message, I think the handling you
suggested makes perfect sense.  ACK && Pushed now.



--
Christian Ehrhardt
Software Engineer, Ubuntu Server
Canonical Ltd



--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH] qemu: allow to control host side link status of network device

2017-05-16 Thread Vasiliy Tolstov
2017-05-16 11:16 GMT+03:00 Daniel P. Berrange :
> Shouldn't we just tie the host & guest link state together then. This
> doesn't seem like enough of a reason to introduce new XML elements.


Back to half year ago i'm already have such patch, but it reverted
with message :
link state only for guest side, for host side we need different element in xml.

-- 
Vasiliy Tolstov,
e-mail: v.tols...@selfip.ru

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] qemu: allow to control host side link status of network device

2017-05-16 Thread Daniel P. Berrange
On Tue, May 16, 2017 at 10:28:27AM +0300, Vasiliy Tolstov wrote:
> 2017-05-16 9:32 GMT+03:00 Peter Krempa :
> > 3.3.2? We dropped micro versions some time ago.
> >
> 
> This is copy/paste from link element, sorry.
> 
> >> +
> >> +
> >>  MTU configuration
> >>  
> >
> >
> > There already is an element called  with attribute "state" which
> > modifies the link state in qemu. So that maps to guest link state. So
> > this patch has a naming collision going on.
> 
> Yes, but some times ago Laine Stump says that for host side link
> status we can use source element with link state.
> 
> >
> > I also don't really see how modifying the host side link state would be
> > useful. Could you elaborate why you think it would be useful?
> 
> OSPF - tap device have addresses assigned to it and bird/quagga create
> routing based on interface link status and addresses on device.
> So if i have host side device in up state no matter that have guest -
> host system forward traffic to it. So i need to modify host side link
> status too.

Shouldn't we just tie the host & guest link state together then. This
doesn't seem like enough of a reason to introduce new XML elements.


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] qemu: Remove unused variables in qemuDomainUpdateDeviceConfig

2017-05-16 Thread Kothapally Madhu Pavan
priv and qemuCaps variables are not used anymore.

Signed-off-by: Kothapally Madhu Pavan 
---
 src/qemu/qemu_driver.c |   11 ---
 1 file changed, 11 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1c4873e..4721356 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8172,8 +8172,6 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
 virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
 bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
 int ret = -1;
-virQEMUCapsPtr qemuCaps = NULL;
-qemuDomainObjPrivatePtr priv;
 virQEMUDriverConfigPtr cfg = NULL;
 virCapsPtr caps = NULL;
 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
@@ -8192,8 +8190,6 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
 if (!(vm = qemuDomObjFromDomain(dom)))
 goto cleanup;
 
-priv = vm->privateData;
-
 if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
 goto cleanup;
 
@@ -8220,12 +8216,6 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
 goto endjob;
 }
 
-if (priv->qemuCaps)
-qemuCaps = virObjectRef(priv->qemuCaps);
-else if (!(qemuCaps = virQEMUCapsCacheLookup(caps, driver->qemuCapsCache,
- vm->def->emulator)))
-goto endjob;
-
 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
 /* Make a copy for updated domain. */
 vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
@@ -8273,7 +8263,6 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
 qemuDomainObjEndJob(driver, vm);
 
  cleanup:
-virObjectUnref(qemuCaps);
 virDomainDefFree(vmdef);
 if (dev != dev_copy)
 virDomainDeviceDefFree(dev_copy);

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] qemu: allow to control host side link status of network device

2017-05-16 Thread Vasiliy Tolstov
2017-05-16 9:32 GMT+03:00 Peter Krempa :
> 3.3.2? We dropped micro versions some time ago.
>

This is copy/paste from link element, sorry.

>> +
>> +
>>  MTU configuration
>>  
>
>
> There already is an element called  with attribute "state" which
> modifies the link state in qemu. So that maps to guest link state. So
> this patch has a naming collision going on.

Yes, but some times ago Laine Stump says that for host side link
status we can use source element with link state.

>
> I also don't really see how modifying the host side link state would be
> useful. Could you elaborate why you think it would be useful?

OSPF - tap device have addresses assigned to it and bird/quagga create
routing based on interface link status and addresses on device.
So if i have host side device in up state no matter that have guest -
host system forward traffic to it. So i need to modify host side link
status too.

>
> At any rate, if you provide a justification, you also need to modify the
> XML portion to have a separate element and provide a test case as it's
> required with XML changes.
>
>

Can you gave me example test for xml changes?

Thanks!


-- 
Vasiliy Tolstov,
e-mail: v.tols...@selfip.ru

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] qemu: allow to control host side link status of network device

2017-05-16 Thread Peter Krempa
On Tue, May 16, 2017 at 01:15:59 +0300, Vasiliy Tolstov wrote:
> Signed-off-by: Vasiliy Tolstov 
> ---
>  docs/formatdomain.html.in | 21 +
>  docs/schemas/domaincommon.rng | 11 +++
>  src/conf/domain_conf.c| 28 
>  src/conf/domain_conf.h|  1 +
>  src/qemu/qemu_hotplug.c   | 17 +
>  src/qemu/qemu_interface.c |  8 
>  6 files changed, 82 insertions(+), 4 deletions(-)
> 
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index 8c884f4af9cb..dd8e6a4afa99 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -5421,6 +5421,27 @@ qemu-kvm -net nic,model=? /dev/null
>Since 0.9.5
>  
>  
> +Modifying phisical link state
> +
> +...
> +devices
> +  interface type='ethernet'
> +source
> +link state='down'/
> +target dev='vnet0'/
> +  /interface
> +/devices
> +...
> +
> +
> +  This element provides means of setting state of the phisical network 
> interface.
> +  Possible values for attribute state are up 
> and
> +  down. If down is specified as the value, the 
> interface
> +  put in down state. Default behavior if this element is unspecified is 
> to have the
> +  link state up.
> +  Since 3.3.2

3.3.2? We dropped micro versions some time ago.

> +
> +
>  MTU configuration
>  


There already is an element called  with attribute "state" which
modifies the link state in qemu. So that maps to guest link state. So
this patch has a naming collision going on.

I also don't really see how modifying the host side link state would be
useful. Could you elaborate why you think it would be useful?

At any rate, if you provide a justification, you also need to modify the
XML portion to have a separate element and provide a test case as it's
required with XML changes.



signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list