Bug 1366446

Summary: vol-resize with --shrink and --allocate behaves strangely
Product: Red Hat Enterprise Linux 7 Reporter: Lili Zhu <lizhu>
Component: libvirtAssignee: Ján Tomko <jtomko>
Status: CLOSED ERRATA QA Contact: yisun
Severity: medium Docs Contact:
Priority: medium    
Version: 7.3CC: dyuan, rbalakri, xuzhang, yisun, zpeng
Target Milestone: rc   
Target Release: 7.3   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: libvirt-3.8.0-1.el7 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2018-04-10 10:36:45 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Lili Zhu 2016-08-12 02:09:49 UTC
Description of problem:
vol-resize with --shrink and --allocate should fail
 
How producible
100%

Version:
kernel-3.10.0-482.el7.x86_64
Libvirt-2.0.0-4.el7.x86_64
qemu-kvm-rhev-2.6.0-18.el7.x86_64

Setup:
1. Prepare an image with the format of ‘raw’
 # qemu-img create /var/lib/libvirt/images/volds 5G


2. Refresh the list of volumes contained in default
# virsh pool-refresh default

3. Given the information about the new volume with qemu-img
# qemu-img info /var/lib/libvirt/images/volds
image: /var/lib/libvirt/images/volds
file format: raw
virtual size: 5.0G (5368709120 bytes)
disk size: 0

4.Try to resize the capacity of the new volume, keep in mind that allocated disk size now is zero
#virsh vol-resize /var/lib/libvirt/images/volds 3G --allocate
error: Failed to change size of volume 'volds' to 3G
error: invalid argument: Can't shrink capacity below current capacity unless shrink flag explicitly specified

5. Try to resize the volume capacity, with shrink flag, it will work successfully, but
the total virtual size will not change
# virsh vol-resize /var/lib/libvirt/images/volds 3G --allocate --shrink
Size of volume 'volds' successfully changed to 3G


Actual results:
# qemu-img info /var/lib/libvirt/images/volds

image: /var/lib/libvirt/images/volds
file format: raw
virtual size: 5.0G (5368709120 bytes)
disk size: 3.0G



Expected results:
According to the manual: “The *new* capacity might be sparse unless --allocate is specified.”
There is no point to use --allocate when there is no new capacity. And the --allocate might wipe the existing data on the disk. 



Additional info:
 If I want to allocate the capacity, there is no necessity to using the shrink flag
# virsh vol-resize /var/lib/libvirt/images/volds 4G --allocate
Size of volume 'volds' successfully changed to 4G
# qemu-img info /var/lib/libvirt/images/volds
image: /var/lib/libvirt/images/volds
file format: raw
virtual size: 5.0G (5368709120 bytes)
disk size: 4.0G

2. After I confronted with this problem, vol-resize with shrink and delta flag also could also not work properly.
 # virsh vol-resize /var/lib/libvirt/images/volds --shrink --delta 500M
error: Failed to change size of volume 'volds' by 500M
error: invalid argument: can't shrink capacity below existing allocation

And also:
# virsh vol-resize /var/lib/libvirt/images/volds -0G --shrink --delta
Size of volume 'volds' successfully changed by 0G
# qemu-img info /var/lib/libvirt/images/volds
image: /var/lib/libvirt/images/volds
file format: raw
virtual size: 4.0G (4294967296 bytes)
disk size: 4.0G


Best Regards,
Lili Zhu

Comment 1 Lili Zhu 2016-08-12 05:59:29 UTC
For the additional info part:
 If I want to allocate the capacity, there is no necessity to using the shrink flag
# virsh vol-resize /var/lib/libvirt/images/volds 4G --allocate
Size of volume 'volds' successfully changed to 4G
# qemu-img info /var/lib/libvirt/images/volds
image: /var/lib/libvirt/images/volds
file format: raw
virtual size: 5.0G (5368709120 bytes)
disk size: 4.0G

What I mean actually is When I execute the above step 5 “successfully“, then I continue to execute the following command. there is no necessity to using the shrink flag at this time, and it will give the the following results

# virsh vol-resize /var/lib/libvirt/images/volds 4G --allocate
Size of volume 'volds' successfully changed to 4G
# qemu-img info /var/lib/libvirt/images/volds
image: /var/lib/libvirt/images/volds
file format: raw
virtual size: 5.0G (5368709120 bytes)
disk size: 4.0G

Comment 2 Ján Tomko 2017-09-25 15:49:36 UTC
If we treat the RESIZE_ALLOCATE flag as "Make sure that the added difference" is allocated, then mixing it with RESIZE_SHRINK does not make sense.

However we try to treat RESIZE_ALLOCATE as "make sure that the whole new size is allocated" and in that case shrinking should work too.

Upstream series to fix the allocation behavior:
https://www.redhat.com/archives/libvir-list/2017-September/msg00875.html

Comment 3 Ján Tomko 2017-09-27 12:50:06 UTC
Pushed upstream as:
commit 959fe7de1f0f6fadb86e853edead6d32c3cb3559
Author:     Ján Tomko <jtomko>
CommitDate: 2017-09-27 14:40:44 +0200

    Shrink volume even with ALLOCATE flag
    
    Calling fallocate on the new (smaller) capacity ensures
    that the whole file is allocated, but it does not reduce
    the file size.
    
    Also call ftruncate after fallocate.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1366446

git describe: v3.7.0-183-g959fe7de1

Comment 5 yisun 2017-10-30 09:55:17 UTC
test with libvirt-3.8.0-1.virtcov.el7.x86_64

According to comment 3, now the behaviour should be like:
when do --allocate and --shrink together, file will be allocated (by fallocate) and shrunk (by ftruncate).

And the test result satisfies the expectation:
1. prepare a 5G sparse file
## qemu-img create -f raw /var/lib/libvirt/images/5G.raw 5g
Formatting '/var/lib/libvirt/images/5G.raw', fmt=raw size=5368709120

## virsh pool-refresh default
Pool default refreshed

## qemu-img info /var/lib/libvirt/images/5G.raw
image: /var/lib/libvirt/images/5G.raw
file format: raw
virtual size: 5.0G (5368709120 bytes)
disk size: 0

2. resize the image to 3.0 with --allocate (without --shrink)
## virsh vol-resize /var/lib/libvirt/images/5G.raw 3G --allocate
error: Failed to change size of volume '5G.raw' to 3G
error: invalid argument: Can't shrink capacity below current capacity unless shrink flag explicitly specified
<== failed as expected

## qemu-img info /var/lib/libvirt/images/5G.raw
image: /var/lib/libvirt/images/5G.raw
file format: raw
virtual size: 5.0G (5368709120 bytes)
disk size: 0
<== not changed

2. resize the image to 3.0 with --allocate  and --shrink
## virsh vol-resize /var/lib/libvirt/images/5G.raw 3G --allocate --shrink
Size of volume '5G.raw' successfully changed to 3G

## qemu-img info /var/lib/libvirt/images/5G.raw
image: /var/lib/libvirt/images/5G.raw
file format: raw
virtual size: 3.0G (3221225472 bytes)
disk size: 3.0G
<== both 'virtual size' and 'disk size' change to 3G as expected

Comment 9 errata-xmlrpc 2018-04-10 10:36:45 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.

https://access.redhat.com/errata/RHEA-2018:0704