Bug 770683

Summary: blockIoTune did not work right with parameters
Product: Red Hat Enterprise Linux 6 Reporter: Wayne Sun <gsun>
Component: libvirtAssignee: Eric Blake <eblake>
Status: CLOSED ERRATA QA Contact: Virtualization Bugs <virt-bugs>
Severity: medium Docs Contact:
Priority: high    
Version: 6.3CC: acathrow, ajia, dallan, dyuan, eblake, jyang, mzhan, rwu, veillard, weizhan
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: libvirt-0.9.10-5.el6 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 819014 (view as bug list) Environment:
Last Closed: 2012-06-20 06:40:26 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 796526, 813972, 819014    

Description Wayne Sun 2011-12-28 10:32:28 UTC
Description of problem:
blockIoTune() not working right:
# python
Python 2.6.6 (r266:84292, Sep 12 2011, 14:03:14) 
[GCC 4.4.5 20110214 (Red Hat 4.4.5-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libvirt
>>> conn = libvirt.open(None)
>>> dom = conn.lookupByName("dom_test")
>>> dom.blockIoTune('hda', None, 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/site-packages/libvirt.py", line 1465, in blockIoTune
    ret = libvirtmod.virDomainGetBlockIoTune(self._o, disk, params, flags)
TypeError: virDomainGetBlockIoTune() takes exactly 2 arguments (4 given)

^^
virDomainGetBlockIoTune() actually take 4 more parameters besides dom:

int	virDomainGetBlockIoTune		(virDomainPtr dom, 
					 const char * disk, 
					 virTypedParameterPtr params, 
					 int * nparams, 
					 unsigned int flags)

user only should need provide 3 parameters: dom, disk, flags

when only input with 2 arguements:

>>> dom.blockIoTune(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: blockIoTune() takes exactly 4 arguments (2 given)


Version-Release number of selected component (if applicable):
libvirt-0.9.8-1.el6.x86_64


How reproducible:
always

Steps to Reproduce:
1. as in description

2.
3.
  
Actual results:
Fail to work

Expected results:
should work


Additional info:
Also tried this with virsh commands and it's working even though get the error of unable to get the parameters:

# virsh blkdeviotune dom_test hda
error: Unable to get block I/O throttle parameters
error: internal error cannot read total_bytes_sec

This parameter problem also happened to setBlockIoTune, maybe another bug should be filed to track that.

Comment 2 Alex Jia 2011-12-29 03:01:15 UTC
Patch on upstream:
https://www.redhat.com/archives/libvir-list/2011-December/msg01074.html

Comment 3 Osier Yang 2011-12-29 06:08:54 UTC
commit ae3315aa4a296a26845d2920cb581d6be63a4602
Author: Alex Jia <ajia>
Date:   Thu Dec 29 13:22:52 2011 +0800

    python: Fix problems of virDomain{Set, Get}BlockIoTune bindings
    
    The parameter 'params' is useless for virDomainGetBlockIoTune API,
    and the return value type should be a virTypedParameterPtr but not
    integer. And "PyArg_ParseTuple" in functions
    libvirt_virDomain{Set,Get}BlockIoTune misses format unit for "format"
    argument.
    
    * libvirt-override-api.xml: Remove useless the parameter 'params'
    from virDomainGetBlockIoTune API, and change return value type from
    integer to virTypedParameterPtr.
    
    * python/libvirt-override.c: Add the missed format units.
    
    RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=770683
    
    Signed-off-by: Alex Jia <ajia>

Comment 5 Wayne Sun 2012-01-10 09:08:23 UTC
# rpm -q libvirt libvirt-python
libvirt-0.9.9-1.el6.x86_64
libvirt-python-0.9.9-1.el6.x86_64

# python
Python 2.6.6 (r266:84292, Sep 12 2011, 14:03:14) 
[GCC 4.4.5 20110214 (Red Hat 4.4.5-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libvirt
>>> conn = libvirt.open(None)
>>> dom = conn.lookupByName("rhel6u2")
>>> dom.blockIoTune('hda', None, 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: blockIoTune() takes exactly 3 arguments (4 given)
>>> dom.blockIoTune('hda', 0)
libvir: QEMU error : internal error cannot read total_bytes_sec
>>> dom.blockIoTune('hda', 1)
libvir: QEMU error : internal error cannot read total_bytes_sec
>>> dom.blockIoTune('hda', 2)
{'write_bytes_sec': 0L, 'total_iops_sec': 0L, 'read_iops_sec': 0L, 'read_bytes_sec': 0L, 'write_iops_sec': 0L, 'total_bytes_sec': 0L}

Comment 6 Eric Blake 2012-03-08 22:13:04 UTC
Reopening; we want one additional patch (otherwise, setting tuning values on a live domain followed by a libvirtd restart will lose the tuning values on the next guest boot):

commit 172d34298f202d7af3fd7ef3bd0f061020dcb1c8
Author: Eric Blake <eblake>
Date:   Fri Feb 10 14:53:49 2012 -0700

    qemu: make block io tuning smarter
    
    When blkdeviotune was first committed in 0.9.8, we had the limitation
    that setting one value reset all others.  But bytes and iops should
    be relatively independent.  Furthermore, setting tuning values on
    a live domain followed by dumpxml did not output the new settings.
    
    * src/qemu/qemu_driver.c (qemuDiskPathToAlias): Add parameter, and
    update callers.
    (qemuDomainSetBlockIoTune): Don't lose previous unrelated
    settings.  Make live changes reflect to dumpxml output.
    * tools/virsh.pod (blkdeviotune): Update documentation.

Comment 8 Daniel Veillard 2012-03-13 10:10:21 UTC
Added, back to ON_QA,

Daniel

Comment 9 Wayne Sun 2012-03-14 08:16:25 UTC
packages:
libvirt-0.9.10-5.el6.x86_64
libvirt-python-0.9.10-5.el6.x86_64
qemu-kvm-0.12.1.2-2.247.el6.x86_64
kernel-2.6.32-244.el6.x86_64

steps:
1. prepare a running domain and check iotune status
# virsh list 
 Id    Name                           State
----------------------------------------------------
 2     rhel6u2                        running

# virsh blkdeviotune rhel6u2 hda
error: Unable to get block I/O throttle parameters
error: internal error cannot read total_bytes_sec

# virsh blkdeviotune rhel6u2 hda --config
total_bytes_sec: 0
read_bytes_sec : 0
write_bytes_sec: 0
total_iops_sec : 0
read_iops_sec  : 0
write_iops_sec : 0

2. set iotune total_bytes_sec live
# virsh blkdeviotune rhel6u2 hda --total_bytes_sec 1000
error: Unable to change block I/O throttle
error: internal error Unexpected error

# virsh dumpxml rhel6u2
...
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw' cache='none'/>
      <source file='/var/lib/libvirt/images/rhel6u2'/>
      <target dev='hda' bus='ide'/>
      <iotune>
        <total_bytes_sec>1000</total_bytes_sec>
      </iotune>
      <alias name='ide0-0-0'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
...

Due to lack qemu support, operation fail, but domain xml updated.

3. set iotune read_bytes_sec with --config
# virsh blkdeviotune rhel6u2 hda --read_bytes_sec 1024000 --config

# virsh blkdeviotune rhel6u2 hda --config
total_bytes_sec: 0
read_bytes_sec : 1024000
write_bytes_sec: 0
total_iops_sec : 0
read_iops_sec  : 0
write_iops_sec : 0

4. set iotune write_bytes_sec with --config
# virsh blkdeviotune rhel6u2 hda --write_bytes_sec 1000000 --config

[root@intel-e7420-128-1 ~]# virsh blkdeviotune rhel6u2 hda --config
total_bytes_sec: 0
read_bytes_sec : 0
write_bytes_sec: 1000000
total_iops_sec : 0
read_iops_sec  : 0
write_iops_sec : 0

write_bytes_sec updated but read_bytes_sec reseted.

continue with other options

# virsh blkdeviotune rhel6u2 hda --read_iops_sec 1000 --config

# virsh blkdeviotune rhel6u2 hda --config
total_bytes_sec: 0
read_bytes_sec : 0
write_bytes_sec: 1000000
total_iops_sec : 0
read_iops_sec  : 1000
write_iops_sec : 0

# virsh blkdeviotune rhel6u2 hda --write_iops_sec 1024 --config

[root@intel-e7420-128-1 ~]# virsh blkdeviotune rhel6u2 hda --config
total_bytes_sec: 0
read_bytes_sec : 0
write_bytes_sec: 1000000
total_iops_sec : 0
read_iops_sec  : 0
write_iops_sec : 1024

write_iops_sec will reset read_iops_sec, iops setting will not reset bytes setting.

# virsh blkdeviotune rhel6u2 hda --total_bytes_sec 1024000 --config

# virsh blkdeviotune rhel6u2 hda --config
total_bytes_sec: 1024000
read_bytes_sec : 0
write_bytes_sec: 0
total_iops_sec : 0
read_iops_sec  : 0
write_iops_sec : 1024

# virsh blkdeviotune rhel6u2 hda --total_iops_sec 1000 --config

# virsh blkdeviotune rhel6u2 hda --config
total_bytes_sec: 1024000
read_bytes_sec : 0
write_bytes_sec: 0
total_iops_sec : 1000
read_iops_sec  : 0
write_iops_sec : 0

So, setting between bytes and iops will not interfere each other, but inside bytes or iops will reset others.

Is this expected?

Comment 10 Eric Blake 2012-03-16 19:48:59 UTC
(In reply to comment #9)
> 
> # virsh blkdeviotune rhel6u2 hda
> error: Unable to get block I/O throttle parameters
> error: internal error cannot read total_bytes_sec

No idea when qemu plans on supporting this; so you may be stuck with
just testing --config.

> 2. set iotune total_bytes_sec live
> # virsh blkdeviotune rhel6u2 hda --total_bytes_sec 1000
> error: Unable to change block I/O throttle
> error: internal error Unexpected error

Matches with the fact that qemu doesn't report it for live domains,
therefore you can't set it for live domains.

> 
> # virsh dumpxml rhel6u2
> ...
>     <disk type='file' device='disk'>
>       <driver name='qemu' type='raw' cache='none'/>
>       <source file='/var/lib/libvirt/images/rhel6u2'/>
>       <target dev='hda' bus='ide'/>
>       <iotune>
>         <total_bytes_sec>1000</total_bytes_sec>
>       </iotune>
>       <alias name='ide0-0-0'/>
>       <address type='drive' controller='0' bus='0' target='0' unit='0'/>
>     </disk>
> ...
> 
> Due to lack qemu support, operation fail, but domain xml updated.

Hmm, live xml should probably not be updated if the qemu command
failed; we may still have a bug.  I'll have to look closer.

> 
> 3. set iotune read_bytes_sec with --config
> # virsh blkdeviotune rhel6u2 hda --read_bytes_sec 1024000 --config

note that per bug 796526, the preferred spelling of this should be
--read-bytes-sec, if you are using libvirt-0.9.10-5 or newer; but
either spelling works for the QA testing.

> 
> So, setting between bytes and iops will not interfere each other, but inside
> bytes or iops will reset others.
> 
> Is this expected?

Yes, that's the documented behavior.  Valid combinations are:
total  read   write
  0      0     0
non-0    0     0
  0    non-0  non-0
  0    non-0   0
  0      0    non-0
and any attempts to set one value (even if you set it explicitly to
zero) clears out the other two values.  You can set two non-zero
values in only the 'read+write' case, and it is your choice whether
you set explicit zero (on up to all three arguments) or omit the
arguments unrelated to the one you are changing.  Attempts to set
non-zero values in an unsupported combination (such as 'total+read')
should be rejected.

Comment 14 Wayne Sun 2012-05-04 16:55:07 UTC
This bug is verified according to comment 9, comment 10 and comment 13.
The spotted issue now is on track in bug 819014.

Thx all for help.

Comment 16 errata-xmlrpc 2012-06-20 06:40:26 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

http://rhn.redhat.com/errata/RHSA-2012-0748.html