Bug 1318993 - vol-create-from failed for logical pool
Summary: vol-create-from failed for logical pool
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: libvirt
Version: 7.3
Hardware: x86_64
OS: Linux
medium
medium
Target Milestone: rc
: ---
Assignee: John Ferlan
QA Contact: Virtualization Bugs
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2016-03-18 10:54 UTC by yisun
Modified: 2016-11-03 18:39 UTC (History)
9 users (show)

Fixed In Version: libvirt-1.3.5-1.el7
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2016-11-03 18:39:55 UTC
Target Upstream Version:


Attachments (Terms of Use)


Links
System ID Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2016:2577 normal SHIPPED_LIVE Moderate: libvirt security, bug fix, and enhancement update 2016-11-03 12:07:06 UTC

Description yisun 2016-03-18 10:54:18 UTC
Decription
vol-create-from failed for logical pool

Versions:
libvirt-1.3.2-1.el7.x86_64
kernel-3.10.0-365.el7.x86_64

How reprodicible:
100%


PLEASE NOTE:
- This is a regression bug, and not reproducible with libvirt-1.2.17-13.el7
- This happens with vol-create-form command in following scenarios:
	from logical pool to logical pool
	from iscsi pool to logical pool
	from scsi pool to logical pool



Steps:
1. create a logical pool with /dev/sdj
# lsblk | grep sdj
sdj                       8:144  0   4.9G  0 disk 
//sdj's backend is a iscsi lun. 


#pvcreate /dev/sdj

#vgcreate vg_logical /dev/sdj

#lvcreate --name default_lv --size 1M vg_logical

#/bin/virsh pool-create-as --name virt-logical-pool --type logical --target /dev/vg_logical --source-name vg_logical

# virsh pool-dumpxml virt-logical-pool
<pool type='logical'>
  <name>virt-logical-pool</name>
  <uuid>e2c24f82-724f-477f-a7c9-f8c4ac84e609</uuid>
  <capacity unit='bytes'>5234491392</capacity>
  <allocation unit='bytes'>1077936128</allocation>
  <available unit='bytes'>4156555264</available>
  <source>
    <name>vg_logical</name>
    <format type='lvm2'/>
  </source>
  <target>
    <path>/dev/vg_logical</path>
  </target>
</pool>


# virsh vol-list virt-logical-pool --details
 Name        Path                        Type   Capacity  Allocation
---------------------------------------------------------------------
 default_lv  /dev/vg_logical/default_lv  block  4.00 MiB    4.00 MiB



2. make sure there is another existing iscsi pool named "iscsi" as follow:
# virsh vol-list iscsi --details
 Name        Path                                                                                    Type   Capacity  Allocation
---------------------------------------------------------------------------------------------------------------------------------
 unit:0:0:1  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt-manual-lun-1  block  1.00 GiB    1.00 GiB
 unit:0:0:2  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt-manual-lun-2  block  1.00 GiB    1.00 GiB
 unit:0:0:3  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt-manual-lun-3  block  1.00 GiB    1.00 GiB

3. Try to use vol-create-from to create a vol in virt-logical-pool, and use unit:0:0:1 in iscsi pool as source
# cat vol.xml 
<volume>
  <name>dest_vol1</name>
  <capacity unit='bytes'>1048576</capacity>
  <target>
    <format type='raw'/>
  </target>
</volume>


# /bin/virsh vol-create-from --pool virt-logical-pool --file vol.xml --vol unit:0:0:1 --inputpool iscsi
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/vg_logical/dest_vol1': Input/output error
<==== here error happened. 



actual result:
vol-create-from failed as above

expected result:
it should be successful








additional info:
you can use following cmd lines to prepare a local iscsi disk and use it as sdj mentioned above

yum install targetcli -y
mkdir -p /var/tmp/avocado_glngTO/
dd if=/dev/zero of=/var/tmp/avocado_glngTO/logical-pool count=5000 bs=1024K
setenforce permissive
targetcli /backstores/fileio/ create device.logical-pool /var/tmp/avocado_glngTO/logical-pool
targetcli /iscsi/ create iqn.2016-03.com.virttest:logical-pool.target
targetcli /iscsi/iqn.2016-03.com.virttest:logical-pool.target/tpg1/portals ls
targetcli /iscsi/iqn.2016-03.com.virttest:logical-pool.target/tpg1/luns/ create /backstores/fileio/device.logical-pool
setenforce enforcing
targetcli /iscsi/iqn.2016-03.com.virttest:logical-pool.target/tpg1/ set attribute authentication=0 demo_mode_write_protect=0 generate_node_acls=1 cache_dynamic_acls=1
targetcli / saveconfig
systemctl restart iscsid.service
iscsiadm -m discovery -t sendtargets -p 127.0.0.1
iscsiadm --mode node --login --targetname iqn.2016-03.com.virttest:logical-pool.target --portal 127.0.0.1
iscsiadm --mode session
iscsiadm -m session -P 3

Comment 3 John Ferlan 2016-04-25 19:44:26 UTC
Are you sure this worked before?

You're trying to upload a 1G disk :

unit:0:0:1  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt-manual-lun-1  block  1.00 GiB    1.00 GiB

into a 1M volume:

<volume>
  <name>dest_vol1</name>
  <capacity unit='bytes'>1048576</capacity>    <=====
  <target>
    <format type='raw'/>
  </target>
</volume>

1024*1024 => 1048576
1024*1024*1024 => 1073741824

That's bound to fail....

If I change the vol.xml to have:

  <capacity unit='G'>1</capacity>

Then given the "following" setup, things work for me.  Although I will admit it took me a bit to get there because reading disk sizes in bytes is always painful for the eyes...

Set up was a little confusing, but here's my environment (f23, upstream 1.3.4 libvirt)... 

1. Create some storage (I have)

dd if=/dev/zero of=/home/vm-storage/iSCSI/src-pool/lun10G.img bs=1M seek=10240 count=0
dd if=/dev/zero of=/home/vm-storage/iSCSI/1g-disks/vol1.img bs=1M seek=1024 count=0
dd if=/dev/zero of=/home/vm-storage/iSCSI/1g-disks/vol2.img bs=1M seek=1024 count=0
dd if=/dev/zero of=/home/vm-storage/iSCSI/1g-disks/vol3.img bs=1M seek=1024 count=0

2. Modify /etc/tgt/targets.conf to add:

<target iqn.2013-12.com.example:iscsi-src-pool>
backing-store /home/vm-storage/iSCSI/src-pool/lun10G.img
</target>

<target iqn.2013-12.com.example:iscsi-1g-disks>
backing-store /home/vm-storage/iSCSI/1g-disks/vol1.img
backing-store /home/vm-storage/iSCSI/1g-disks/vol2.img
backing-store /home/vm-storage/iSCSI/1g-disks/vol3.img
</target>

3. service tgtd restart
   service iscsid restart

4. Create some libvirt pools

cat iscsi-src-pool.xml
<pool type='iscsi'>
  <name>iscsi-src-pool</name>
  <source>
    <host name='192.168.122.1'/>
    <device path='iqn.2013-12.com.example:iscsi-src-pool'/>
  </source>
  <target>
    <path>/dev/disk/by-path</path>
  </target>
</pool>

virsh pool-create iscsi-src-pool.xml
virsh vol-list iscsi-src-pool --details
 Name        Path                                                                                            Type     Capacity  Allocation
-------------------------------------------------------------------------------------------------------------------------------------------
 unit:0:0:1  /dev/disk/by-path/ip-192.168.122.1:3260-iscsi-iqn.2013-12.com.example:iscsi-src-pool-lun-1  block   10.00 GiB   10.00 GiB



lsscsi -tg
...
[10:0:0:0]   storage iqn.2013-12.com.example:iscsi-src-pool,t,0x1  -          /dev/sg6 
[10:0:0:1]   disk    iqn.2013-12.com.example:iscsi-src-pool,t,0x1  /dev/sde   /dev/sg7 
[11:0:0:0]   storage iqn.2013-12.com.example:iscsi-1g-disks,t,0x1  -          /dev/sg9 
[11:0:0:1]   disk    iqn.2013-12.com.example:iscsi-1g-disks,t,0x1  /dev/sdg   /dev/sg10
[11:0:0:2]   disk    iqn.2013-12.com.example:iscsi-1g-disks,t,0x1  /dev/sdh   /dev/sg11
[11:0:0:3]   disk    iqn.2013-12.com.example:iscsi-1g-disks,t,0x1  /dev/sdi   /dev/sg12
...



pvcreate /dev/sde    
vgcreate vg_logical /dev/sde
lvcreate --name default_lv --size 1M vg_logical
virsh pool-create-as --name virt-logical-pool --type logical --target /dev/vg_logical --source-name vg_logical


cat iscsi-1g-disks.xml
<pool type='iscsi'>
  <name>iscsi-1g-disks</name>
  <source>
    <host name='192.168.122.1'/>
    <device path='iqn.2013-12.com.example:iscsi-1g-disks'/>
  </source>
  <target>
    <path>/dev/disk/by-path</path>
  </target>
</pool>

virsh pool-create iscsi-1g-disks.xml
virsh vol-list iscsi-1g-disks --details
Name        Path                                                                                        Type      Capacity   Allocation
-----------------------------------------------------------------------------------------------------------------------------------------
 unit:0:0:1  /dev/disk/by-path/ip-192.168.122.1:3260-iscsi-iqn.2013-12.com.example:iscsi-1g-disks-lun-1  block  1000.00 MiB  1000.00 MiB
 unit:0:0:2  /dev/disk/by-path/ip-192.168.122.1:3260-iscsi-iqn.2013-12.com.example:iscsi-1g-disks-lun-2  block  1000.00 MiB  1000.00 MiB
 unit:0:0:3  /dev/disk/by-path/ip-192.168.122.1:3260-iscsi-iqn.2013-12.com.example:iscsi-1g-disks-lun-3  block  1000.00 MiB  1000.00 MiB


Using your exact setup, I edited the code to temporarily comment out the fdatasync() call that was failing... That would allow the volume to be created and showed me the following lvs output:

lvs -v vg_logical
    Using logical volume(s) on command line.
  LV         VG         #Seg Attr       LSize Maj Min KMaj KMin Pool Origin              Data%  Meta%  Move Cpy%Sync Log Convert LV UUID                                LProfile
  default_lv vg_logical    1 -wi-a----- 4.00m  -1  -1  253    5                                                                  hhDo9p-3Drx-FErw-478i-ov9O-ku8Q-3sKsKh         
  dest_vol1  vg_logical    1 swi-I-s--- 4.00m  -1  -1  253    9      [dest_vol1_vorigin] 100.00                                  yMMhJr-8hHS-fgYw-uC0j-dgdp-FSjr-RKZaRS         

NOTE: The "I" in the attributes and the 100.00 filled.

That says the partition is inactive.  A bit of google research turns up (ironically) bz 975052 and in particular https://bugzilla.redhat.com/show_bug.cgi?id=975052#c4 which is precisely why the fdatasync is failing.


BTW: I tried the same exact steps as you on a second system that I have which is running libvirt 1.2.18 and it too exhibited the same problem you saw. Of course changing the vol.xml to use 1G allowed things to work.

Before I close this as not a bug - could you double check your environment. If you can reproduced in a 1.2.17 environment, then I would like access to that environment so I can debug.

Comment 6 John Ferlan 2016-04-28 15:44:25 UTC
Well it seems to be an inadvertent side effect of changes made for bz 1130739 (commit id 'dd519a29'). Specifically, removing the 'newvol->target.allocation' means capacity != allocation possibly - allowing a sparse volume possibility. That doesn't work the same for a logical backend as it does perhaps for other backends. This is possibly exacerbated by not requiring capacity to be added into the XML (bz 958510 commit id '155ca616').

The allocation changes were made in 1.2.18 which is why my second system was failing and 1.2.17 succeeds...

Because the 'allocation' adjustment was removed from storage_driver.c, the 'createVol' will generate a 'thin snapshot' volume, so when the copy is attempted, from a larger volume whatever size goes above the "default" minimum size (in my case 4.00m) LVM will 'invalidate' the volume (e.g. that "I" in the attributes).  That causes the fdatasync to fail.

I'll look into a couple of options to resolve...

I also realized after wondering why my result was different than yours that the iscsi pool isn't as shown in the description, it's currently:

# virsh vol-list iscsi --details
 Name        Path                                                                                                      Type    Capacity  Allocation
----------------------------------------------------------------------------------------------------------------------------------------------------
 unit:0:0:1  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt.shyu-qe-consumption-auto-lun-1  block   1.00 GiB    1.00 GiB
 unit:0:0:2  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt.shyu-qe-consumption-auto-lun-2  block  50.00 MiB   50.00 MiB
 unit:0:0:3  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt.shyu-qe-consumption-auto-lun-3  block   1.00 GiB    1.00 GiB
 unit:0:0:4  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt.shyu-qe-consumption-auto-lun-4  block   1.00 GiB    1.00 GiB
 unit:0:0:5  /dev/disk/by-path/ip-10.66.5.88:3260-iscsi-iqn.2014-12.com.redhat:libvirt.shyu-qe-consumption-auto-lun-5  block   1.00 GiB    1.00 GiB
# 

Note that "50.00 MiB" for unit:0:0:2, so of course when you copied you were showing a different value than I got. Your output has 52.00 on the target pool, while I had 1000.00 MiB for copying my unit:0:0:1...

Comment 7 Ján Tomko 2016-04-29 08:32:21 UTC
The problem is that libvirt fills out 'allocation' in the XML parser by copying the 'capacity' value and we have no way of knowing if the value came from the user or not.

For <capacity>, we treat '0' the same as 'not specified', since a zero size volume does not make much sense.

But for <allocation>, 0 could also be considered as "as small as possible".

I think we should mark whether the allocation comes from the user or not and fill it out in the storage driver instead of the XML parser, at least for the CreateVolFrom path (with VIR_VOL_XML_PARSE_NO_CAPACITY set).

Comment 8 John Ferlan 2016-04-29 12:36:41 UTC
Posted a patch upstream today:

http://www.redhat.com/archives/libvir-list/2016-April/msg01958.html

Comment 9 John Ferlan 2016-04-29 15:35:13 UTC
Ugh - didn't see Jan's comment before posting patch - hazards of ignoring mail volume from bugzilla <sigh>

OK so the "provided" <allocation> of 0 would be a problem with the patch; however, let's also take this time to consider the resetting of <capacity> in storage_driver.c to the copy-from-vol <capacity> would be correct.

Consider the following... I have in my default pool 'sparse.img':

# qemu-img info /home/vm-images/sparse.img
image: /home/vm-images/sparse.img
file format: raw
virtual size: 20M (20971520 bytes)
disk size: 8.0M

Without the patch in place, I get the following  
# cat sparse-file.xml
<volume>
  <name>sparse.img.clone</name>
  <capacity unit='MiB'>10</capacity>
  <target>
    <format type='raw'/>
  </target>
</volume>

# virsh vol-create-from --pool default --file sparse-file.xml --vol sparse.img --inputpool default
Vol sparse.img.clone created from input vol sparse.img

# qemu-img info /home/vm-images/sparse.img.clone
image: /home/vm-images/sparse.img.clone
file format: raw
virtual size: 20M (20971520 bytes)
disk size: 0

#

With the above patch in place I get:

# qemu-img info /home/vm-images/sparse.img.clone
image: /home/vm-images/sparse.img.clone
file format: raw
virtual size: 10M (10485760 bytes)
disk size: 0


The difference being if the XML has a <capacity> value, then storage driver won't overwrite the value (since we're allowing it to not be provided). 

If someone provides a 0 capacity, then regardless of whether the current code or the above patch is in place, the created volume has a virtual size of 20M (or whatever the source capacity is).

The 'simplest' method to determine whether allocation has been provided or not and if it has whether it's been set to 0 would seem to be to set a boolean indicating it has been provided.  That feels ugly, but gets the answer.

A patch has been sent to make that adjustment as well.

Comment 10 John Ferlan 2016-05-11 13:22:47 UTC
Comment 9 description of capacity adjustment was removed.  All that changes is to check if allocation was not provided in the XML, then use capacity.

Changes have been pushed upstream:

commit 2c52ec43aa283a1f3221e420f0c392706bdaedcc
Author: John Ferlan <jferlan@redhat.com>
Date:   Fri Apr 29 07:43:57 2016 -0400

    storage: Fix regression cloning volume into a logical pool
    
...

$ git describe 2c52ec43aa283a1f3221e420f0c392706bdaedcc
v1.3.4-208-g2c52ec4
$

Comment 12 Yang Yang 2016-08-11 09:37:30 UTC
John,

Following cases confuse me. I am not sure whether the actual result is expected

I have a full allocated volume in logical pool

# virsh vol-create-as VG01 lv01 200M
Vol lv01 created

# virsh vol-list VG01
 Name                 Path                                    
------------------------------------------------------------------------------
 lv01                 /dev/VG01/lv01             

# virsh vol-info lv01 VG01
Name:           lv01
Type:           block
Capacity:       200.00 MiB
Allocation:     200.00 MiB

# lvs -v VG01
  LV   VG   #Seg Attr       LSize   Maj Min KMaj KMin Pool Origin Data%  Meta%  Move Cpy%Sync Log Convert LV UUID                                LProfile
  lv01 VG01    1 -wi-a----- 200.00m  -1  -1  253    8                                                     CfccJ7-0fPU-yrB4-ao92-7rU6-5niP-iJNG7Q         

#

1. specify newvol's allocation no larger than 200M and newvol's allocation less than newvol's capacity

# cat vol.xml 
<volume>  
<name>new_vol</name> 
<capacity unit='M'>300</capacity>
<allocation unit='M'>200</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

#

I get an error

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

2. specify newvol's allocation no larger than 200M

# cat vol.xml 
<volume>  
<name>new_vol</name> 
<capacity unit='M'>100</capacity>
<allocation unit='M'>100</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

#

I get an error

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

3. Given capacity of new_vol less than that of original vol, allocation is not provided

# cat vol.xml 
<volume>  
<name>new_vol</name> 
<capacity unit='M'>100</capacity>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
Vol new_vol created from input vol lv01

#

I get new volume with 200M, the <capacity> I specified is overwritten. Is it by design?

# virsh vol-info new_vol VG01
Name:           new_vol
Type:           block
Capacity:       200.00 MiB
Allocation:     200.00 MiB

Comment 13 Yang Yang 2016-08-11 10:19:06 UTC
I got the same error when cloning a thin volume into a thin volume

I have an original thin volume

# virsh vol-create-as VG01 lv01 --capacity 200M --allocation 100M
Vol lv01 created

# virsh vol-info lv01 VG01
Name:           lv01
Type:           block
Capacity:       200.00 MiB
Allocation:     100.00 MiB

#

Upload into a thin volume

# cat vol.xml 
<volume>  
<name>new_vol</name> 
<capacity unit='MiB'>200</capacity>
<allocation unit='MiB'>100</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

#

I get the error

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

#

Consider to specify <allocation> only

# cat vol.xml 
<volume>  
<name>new_vol</name> 
<allocation unit='MiB'>100</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

#

I get the error again

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

Comment 14 John Ferlan 2016-08-18 13:44:24 UTC
Sorry this has taken so long to return to - I was away last week and catching up on things has taken time...

With respect to Comment 12 - 

First off - logical pools always cause extra thought and pain...  Second, libvirt doesn't technically use the "thin" lv logic, it's using an older "sparse" lv model. Thin pool support has been requested in bz1060287.

Anyway, w/r/t your first example:

<volume>  
<name>new_vol</name> 
<capacity unit='M'>300</capacity>
<allocation unit='M'>200</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

Equates to the command

lvcreate --name new_vol -L 200M --type snapshot --virtualsize 300M VG01

That is create a 200M volume that presents itself as having 300M of space, but in reality there's only 200M of space. As the documentation says, "For example, the logical pool will not automatically expand volume's allocation when it gets full; the user is responsible for doing that or configuring dmeventd to do so automatically.".  IOW: You start with 200M, you can go as far as 300M according to lvm, but in order to get there you have to add extents to the 200M.

So, the XML if executed outside libvirt results in :
 
lvs -v VG01
...
  new_vol    VG01        1 swi-a-s--- 200.00m  -1  -1  253   15      [x_vorigin]       0.00                                    EgYZRN-2VxC-cBlM-EYZt-mLcA-XbPG-o1k1Ni         

OK so far right?  But then because you're using lv01 to "copy from", an attempt is made to copy in/over 200M into 'new_vol'.  But since you really don't have a fully 200M available (always space for metadata in logical volumes), the copy ends up failing during virStorageBackendCopyToFD.

*IF* you hadn't used the "--inputpool" command and copied from, then you'd see the volume as:

# virsh vol-list VG01 --details
 Name        Path                      Type     Capacity  Allocation
---------------------------------------------------------------------
...
 new_vol     /dev/VG01/new_vol         block  300.00 MiB  200.00 MiB
...


So for this one, although a really tough error to understand - I believe the code is doing what it should be doing.  If you had flipped your capacity and allocation, then after the copy the volume would have shown to be 67% full according to the 'lvs -v VG01' output.  That's because you would have created a 300M volume that only *looked like* it was 200M, thus leaving yourself some space for overflowing the volume.  Yes, odd to think like that.

The second XML snippet:

<volume>  
<name>new_vol</name> 
<capacity unit='M'>100</capacity>
<target>    
<format type='raw'/>  
</target>
</volume>

results in the command 

lvcreate --name new_vol -L 100M VG01

and a copy of data from lv01 to new_vol works because there are extents/space left in the VG01 pool and lvm allows for that to happen.

Comment 15 John Ferlan 2016-08-18 15:34:26 UTC
With respect to comment 13:

This is a copy from a sparse lv into a sparse lv with a twist - you have 'lv01' advertising it has 200M, with really only 100M of data

Following the logic from the previous response... The XML:

<volume>  
<name>new_vol</name> 
<capacity unit='MiB'>200</capacity>
<allocation unit='MiB'>100</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

equates to

lvcreate --name new_vol -L 100M --type snapshot --virtualsize 200M VG01

and likewise creates a 100M volume that appears to be 200M to a client. This time we're trying to copy 200M from the client into a target with only 100M available, but advertising 200M. This is bound to fail for similar reasons as the previous case. Now let's say you modify the XML to have:

<capacity unit='MiB'>300</capacity>
<allocation unit='MiB'>201</allocation>

Then the create would probably succeed. I say probably because it is possible to fail depending on the 'minimum size' allowed for a "full physical extent". Go back to the original lvcreate with a 1M volume. Doing this on my system results in :

lvcreate --name default_lv --size 1M VG01
  Rounding up size to full physical extent 4.00 MiB
  Logical volume "default_lv" created.

and an lvs -v VG01 of:

 Name        Path                      Type   Capacity  Allocation
-------------------------------------------------------------------
 default_lv  /dev/VG01/default_lv      block  4.00 MiB    4.00 MiB
 
So, for that 300/201 volume I created, I get:

  new_vol    VG01        1 swi-a-s--- 204.00m  -1  -1  253   14      [new_vol_vorigin] 98.43                                   vLnCcv-1TN8-0XdC-G2Sw-2TMe-avZq-z8GMQX         

Note: It's essentially full @98.43 (and 200/204 == 98.03 - so again consider "overhead").


As for the second XML snippet specifying allocation only:


<volume>  
<name>new_vol</name> 
<allocation unit='MiB'>100</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

Now we're into a case where the code (storage driver) for a "CreateFrom" will :

    /* Use the original volume's capacity in case the new capacity
     * is less than that, or it was omitted */
    if (newvol->target.capacity < origvol->target.capacity)
        newvol->target.capacity = origvol->target.capacity;

So we're left with the same :

capacity = 200M
allocation = 100M

and of course a similar failure. 

Now "ironcally", if you alter this second one to have value of 201, then the create from will succeed.  Creating a sparse volume having 204M allocation, 200M capacity.


Still working as expected - OK at least with respect to how LVM works.

Comment 16 Yang Yang 2016-08-22 02:41:26 UTC
Verified in libvirt-2.0.0-5.el7.x86_64

Create a full allocated source volume
# virsh vol-create-as VG01 lv01 200M
Vol lv01 created

[root@rhel7_test ~]# virsh vol-list VG01
 Name                 Path                                    
------------------------------------------------------------------------------
 lv01                 /dev/VG01/lv01            

# virsh vol-info lv01 VG01
Name:           lv01
Type:           block
Capacity:       200.00 MiB
Allocation:     200.00 MiB

Create target volume from the source volume
1. neither capacity nor allocation is specified
# cat vol.xml
<volume>  
<name>new_vol</name>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01

Vol new_vol created from input vol lv01

[root@rhel7_test ~]# virsh vol-info new_vol VG01
Name:           new_vol
Type:           block
Capacity:       200.00 MiB
Allocation:     200.00 MiB

2. Given capacity of new_vol less than that of original vol, allocation is not provided
# cat vol.xml
<volume>  
<name>new_vol</name>
<capacity unit='M'>100</capacity>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
 
Vol new_vol created from input vol lv01

# virsh vol-info new_vol VG01
Name:           new_vol
Type:           block
Capacity:       200.00 MiB
Allocation:     200.00 MiB

3.Given capacity of new_vol larger than that of original vol, allocation is not provided
# cat vol.xml
<volume>  
<name>new_vol</name>
<capacity unit='M'>300</capacity>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
 
Vol new_vol created from input vol lv01

[root@rhel7_test ~]#
[root@rhel7_test ~]# virsh vol-info new_vol VG01
Name:           new_vol
Type:           block
Capacity:       300.00 MiB
Allocation:     300.00 MiB

4. specify allocation=0
# cat vol.xml
<volume>  
<name>new_vol</name>
<capacity unit='M'>200</capacity>
<allocation unit='M'>0</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

5. specify allocation less than capacity
# cat vol.xml
<volume>  
<name>new_vol</name>
<capacity unit='M'>200</capacity>
<allocation unit='M'>100</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

# cat vol.xml
<volume>  
<name>new_vol</name>
<capacity unit='M'>300</capacity>
<allocation unit='M'>200</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

<volume>  
<name>new_vol</name>
<capacity unit='M'>100</capacity>
<allocation unit='M'>100</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

6. specify allocation larger than capacity
# cat vol.xml
<volume>  
<name>new_vol</name>
<capacity unit='M'>100</capacity>
<allocation unit='M'>200</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
Vol new_vol created from input vol lv01

[root@rhel7_test ~]# virsh vol-info lv01 VG01
Name:           lv01
Type:           block
Capacity:       200.00 MiB
Allocation:     200.00 MiB

7. specify allocation only
# cat vol.xml
<volume>  
<name>new_vol</name>
<allocation unit='M'>200</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
Vol new_vol created from input vol lv01


============================================================================
Create a sparse source volume

# virsh vol-create-as VG01 lv01 --capacity 200M --allocation 100M
Vol lv01 created

[root@rhel7_test ~]# virsh vol-info lv01 VG01
Name:           lv01
Type:           block
Capacity:       200.00 MiB
Allocation:     100.00 MiB

create target volume from source volume
1. neither capacity nor allocation is specified
# cat vol.xml
<volume>  
<name>new_vol</name>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01

Vol new_vol created from input vol lv01

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
Vol new_vol created from input vol lv01

[root@rhel7_test ~]# virsh vol-info new_vol VG01
Name:           new_vol
Type:           block
Capacity:       200.00 MiB
Allocation:     200.00 MiB


2. specify capacity only, it's less than that of original volume
# cat vol.xml
<volume>  
<name>new_vol</name>
<capacity unit='M'>100</capacity>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
Vol new_vol created from input vol lv01

[root@rhel7_test ~]# virsh vol-info new_vol VG01
Name:           new_vol
Type:           block
Capacity:       200.00 MiB
Allocation:     200.00 MiB

# cat vol.xml
<volume>  
<name>new_vol</name>
<capacity unit='M'>200</capacity>
<allocation unit='M'>100</allocation>
<target>    
<format type='raw'/>  
</target>
</volume>

# virsh vol-create-from --pool VG01 --file vol.xml --vol lv01 --inputpool VG01
error: Failed to create vol from vol.xml
error: cannot sync data to file '/dev/VG01/new_vol': Input/output error

According to comment#14 and comment#15, move it to verified status

Comment 18 errata-xmlrpc 2016-11-03 18:39:55 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://rhn.redhat.com/errata/RHSA-2016-2577.html


Note You need to log in before you can comment on or make changes to this bug.