Kashyap Chamarthy
2014-Jul-02 19:12 UTC
[libvirt-users] virsh blockcopy: doesn't seem to flatten the chain by default
Versions -------- (Libvirt locally built from a recent git commit -ec7b922): $ rpm -q libvirt-daemon-kvm qemu-system-x86 libvirt-daemon-kvm-1.2.6-1.fc20.x86_64 qemu-system-x86-2.0.0-1.fc21.x86_64 Test ---- [All images are qcow2 files.] We have this simple chain: base <- snap1 Let's quickly examine the contents of 'base' and 'snap1' images: 'base' has just a single file: foo $ guestfish --ro -a base.qcow2 [. . .] ><fs> ls / ><fs> run ><fs> mount /dev/sda1 / ><fs> ls / foo lost+found ><fs> quit 'snap1' has files: bar, baz, jazz $ guestfish --ro -a snap1.qcow2 [. . .] ><fs> run ><fs> mount /dev/sda1 / ><fs> ls / bar baz jazz lost+found ><fs> Now, let's do a live blockcopy (with a '--finish' to graecully finish the mirroring): $ virsh blockcopy --domain testvm2 vda \ /export/dst/copy.qcow2 \ --wait --verbose --finish Examine the contents of the above 'copy': $ guestfish --ro -a copy.qcow2 [. . .] ><fs> run ><fs> mount /dev/sda1 / ><fs> ls / bar baz jazz lost+found ><fs> quit If I'm reading the man page of 'blockcopy' correctly, shouldn't it 'flatten' the entire chain, by also copying the contents of base into copy.qcow2? i.e. the 'copy' should have files (including the file foo from 'base': foo, bar, baz, jazz True or false? PS: I've tested the cases of --pivot, --shallow and --reuse-external, will post my notes about them on a wiki. -- /kashyap
Kashyap Chamarthy
2014-Jul-02 21:23 UTC
Re: [libvirt-users] virsh blockcopy: doesn't seem to flatten the chain by default
On Thu, Jul 03, 2014 at 12:42:20AM +0530, Kashyap Chamarthy wrote: [. . .] Forgot to note: Before blockcopy, the current block device is snap1.qcow2 (after too, it's the same, since we didn't `--pivot` to the copy.> Now, let's do a live blockcopy (with a '--finish' to graecully finish > the mirroring): > > $ virsh blockcopy --domain testvm2 vda \ > /export/dst/copy.qcow2 \ > --wait --verbose --finish > > > Examine the contents of the above 'copy': > > $ guestfish --ro -a copy.qcow2 > [. . .] > ><fs> run > ><fs> mount /dev/sda1 / > ><fs> ls / > bar > baz > jazz > lost+found > ><fs> quit > > If I'm reading the man page of 'blockcopy' correctly, shouldn't it > 'flatten' the entire chain, by also copying the contents of base into > copy.qcow2? i.e. the 'copy' should have files (including the file foo > from 'base': > > foo, bar, baz, jazz > > > True or false? >-- /kashyap
shyu
2014-Jul-03 09:07 UTC
Re: [libvirt-users] virsh blockcopy: doesn't seem to flatten the chain by default
On 07/03/2014 03:12 AM, Kashyap Chamarthy wrote:> Versions > -------- > > (Libvirt locally built from a recent git commit -ec7b922): > > $ rpm -q libvirt-daemon-kvm qemu-system-x86 > libvirt-daemon-kvm-1.2.6-1.fc20.x86_64 > qemu-system-x86-2.0.0-1.fc21.x86_64 > > > Test > ---- > > [All images are qcow2 files.] > > > We have this simple chain: > > base <- snap1 > > Let's quickly examine the contents of 'base' and 'snap1' images: > > 'base' has just a single file: foo > > $ guestfish --ro -a base.qcow2 > [. . .] > ><fs> ls / > ><fs> run > ><fs> mount /dev/sda1 / > ><fs> ls / > foo > lost+found > ><fs> quit > > 'snap1' has files: bar, baz, jazz > > $ guestfish --ro -a snap1.qcow2 > [. . .] > ><fs> run > ><fs> mount /dev/sda1 / > ><fs> ls / > bar > baz > jazz > lost+found > ><fs> > > Now, let's do a live blockcopy (with a '--finish' to graecully finish > the mirroring): > > $ virsh blockcopy --domain testvm2 vda \ > /export/dst/copy.qcow2 \ > --wait --verbose --finish > > > Examine the contents of the above 'copy': > > $ guestfish --ro -a copy.qcow2 > [. . .] > ><fs> run > ><fs> mount /dev/sda1 / > ><fs> ls / > bar > baz > jazz > lost+found > ><fs> quit > > If I'm reading the man page of 'blockcopy' correctly, shouldn't it > 'flatten' the entire chain, by also copying the contents of base into > copy.qcow2? i.e. the 'copy' should have files (including the file foo > from 'base': > > foo, bar, baz, jazzI do test on my fedora20 with libvirt build from libvirt.git # cd libvirt && git describe v1.2.6-9-g5098f67 # rpm -q qemu-kvm qemu-kvm-2.0.0-7.fc20.x86_64 It work well for me. I can see the file 'foo'(from base.qcow2) in copy file "copy.qcow2" I also boot guest with image copy.qcow2, login guest and found file "foo" is existing.> > True or false? > > > PS: I've tested the cases of --pivot, --shallow and --reuse-external, > will post my notes about them on a wiki. >-- Regards shyu
Kashyap Chamarthy
2014-Jul-03 10:18 UTC
[libvirt-users] [Resolved] Re: virsh blockcopy: doesn't seem to flatten the chain by default
On Thu, Jul 03, 2014 at 05:07:40PM +0800, shyu wrote:> > On 07/03/2014 03:12 AM, Kashyap Chamarthy wrote:[. . ] Okay, I clearly must have done something wrong during guestfish disk creations plus a mix of libvirt/QEMU manipulations (backing chains were created using `qemu-img`). If I consistently use libvirt across the board, it, of course, works fine. I just did a retest by building libvirt & QEMU from git: libvirt: $ git rev-parse --short HEAD && git describe 5098f67 v1.2.6-9-g5098f67 QEMU: $ git rev-parse --short HEAD && git describe 92259b7 v2.1.0-rc0 Test w/ a Fedora-20 image ------------------------- Start the guest: $ virsh start vm1 Make it transient: $ virsh dumpxml --inactive vm1 > /var/tmp/vm1.xml [Add some content into base.qcow2] Take a live, external disk-only snapshot: $ virsh snapshot-create-as \ --domain vm1 snap1 snap1-with-foo \ --diskspec vda,file=/export/images/snap1.qcow2 \ --disk-only [Add some content into snap1.qcow2] Perform live blockcopy and finish the mirroring gracefully: $ virsh blockcopy \ --domain vm1 \ --path vda /export/images/copy.qcow2 \ --wait --verbose --finish [Examine copy.qcow2 contents - it should reflect all content] Define the guest to make it persistent again: $ virsh define /var/tmp/vm1.xml -- /kashyap
Eric Blake
2014-Jul-03 17:08 UTC
Re: [libvirt-users] virsh blockcopy: doesn't seem to flatten the chain by default
On 07/02/2014 01:12 PM, Kashyap Chamarthy wrote:> We have this simple chain: > > base <- snap1 > > Let's quickly examine the contents of 'base' and 'snap1' images: >> Now, let's do a live blockcopy (with a '--finish' to graecully finish > the mirroring): > > $ virsh blockcopy --domain testvm2 vda \ > /export/dst/copy.qcow2 \ > --wait --verbose --finishThis defaults to a full copy (copy.qcow2 will contain everything in the latest state of the original chain, but with no backing file).> > If I'm reading the man page of 'blockcopy' correctly, shouldn't it > 'flatten' the entire chain, by also copying the contents of base into > copy.qcow2? i.e. the 'copy' should have files (including the file foo > from 'base': > > foo, bar, baz, jazz > > > True or false?False. This is NOT a union mount. Sometime in between base and snap1, you deleted foo. That is recorded in snap1, and when reading a chain, you stop at the first level of the chain that provides information. When flattening, it means you are inherently losing any information about the state that existed before snap1 changed the state, at least when using the flattened chain to try and find that information. Graphically (well, using ASCII), let's look at it like this. When you start your guest originally, you have a big blank disk being tracked by the base image, and write into some sectors of that disk. So, use "A" to represent the initial OS install, and "X" to represent a sector not yet written: base: AAAAXXXXXXXXXXXX ===guest: AAAAXXXXXXXXXXXX Then, you modify the guest to write the file foo, represent that with "B" for the sectors that were modified: base: AAABBBBBXXXXXXXX ===guest: AAABBBBBXXXXXXXX then you take a snapshot, at the point you take it, snap1 is completely empty, but notice that the guest view of the world is still unchanged: base: AAABBBBBXXXXXXXX snap1: XXXXXXXXXXXXXXXX ===guest: AAABBBBBXXXXXXXX now you do some more modification, such as deleting foo, and creating bar (note that deleting a file can be done by writing one sector, and may still leave remnants of the file behind in other sectors, but in such a way that the guest file system will never retrieve those contents). Represent these changes with "C" base: AAABBBBBXXXXXXXX snap1: XXXCXXXXCCCCXXXX ===guest: AAACBBBBCCCCXXXX When you are doing a full blockcopy, you are asking to create a new file whose contents match what the guest sees. When the copy finally reaches sync, you have: base: AAABBBBBXXXXXXXX snap1: XXXCXXXXCCCCXXXX copy: AAACBBBBCCCCXXXX ===guest: AAACBBBBCCCCXXXX The copy operation lasts as long as you want; in that time, the guest can make even more changes, let's call them "D" base: AAABBBBBXXXXXXXX snap1: XXXDXXXXCCCCDDDD copy: AAADBBBBCCCCDDDD ===guest: AAADBBBBCCCCDDDD then you finally abort or pivot the copy. Let's try a pivot, where the next action in the guest causes changes to the disk labeled "E": base: AAABBBBBXXXXXXXX snap1: XXXDXXXXCCCCDDDD copy: AAAEBBBBCCCCDDDD ===guest: AAAEBBBBCCCCDDDD> > > PS: I've tested the cases of --pivot, --shallow and --reuse-external, > will post my notes about them on a wiki.I hope those help you figure out what's going on. You seem to be hoping for a magic bullet that gives you file system union mounts (merge the contents of two different timestamps of a directories existence in a common file system) - but that is NOT what disk snapshots do. All libvirt and qemu can do is block level manipulations, not file system manipulations. I'm not even sure if a file system tool exists that can do file system checkpoints and/or union mount merges; but if it does, it would be something you use in the guest at the file system level, and not something libvirt can manage at the block device sector level. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Eric Blake
2014-Jul-03 17:11 UTC
Re: [libvirt-users] virsh blockcopy: doesn't seem to flatten the chain by default
On 07/02/2014 03:23 PM, Kashyap Chamarthy wrote:> On Thu, Jul 03, 2014 at 12:42:20AM +0530, Kashyap Chamarthy wrote: > > [. . .] > > Forgot to note: Before blockcopy, the current block device is > snap1.qcow2 (after too, it's the same, since we didn't `--pivot` to the > copy. >Not pivoting doesn't matter. The point of a copy is that once the copy is synced, you have two files that both get all new edits, and then you break the sync leaving one file containing what the guest saw at that point in time while the other file continues to track guest changes. Aborting leaves the copy as the point in time, pivoting leaves the original as the point in time.>> >> If I'm reading the man page of 'blockcopy' correctly, shouldn't it >> 'flatten' the entire chain, by also copying the contents of base into >> copy.qcow2? i.e. the 'copy' should have files (including the file foo >> from 'base':A blockcopy only copies sectors of base into copy in the case where those sectors were not already overwritten by sectors in snap1. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
shyu
2014-Jul-04 06:05 UTC
Re: [libvirt-users] virsh blockcopy: doesn't seem to flatten the chain by default
On 07/04/2014 01:08 AM, Eric Blake wrote:> On 07/02/2014 01:12 PM, Kashyap Chamarthy wrote: > >> We have this simple chain: >> >> base <- snap1 >> >> Let's quickly examine the contents of 'base' and 'snap1' images: >> >> Now, let's do a live blockcopy (with a '--finish' to graecully finish >> the mirroring): >> >> $ virsh blockcopy --domain testvm2 vda \ >> /export/dst/copy.qcow2 \ >> --wait --verbose --finish > This defaults to a full copy (copy.qcow2 will contain everything in the > latest state of the original chain, but with no backing file). > > >> If I'm reading the man page of 'blockcopy' correctly, shouldn't it >> 'flatten' the entire chain, by also copying the contents of base into >> copy.qcow2? i.e. the 'copy' should have files (including the file foo >> from 'base': >> >> foo, bar, baz, jazz >> >> >> True or false? > False. This is NOT a union mount. Sometime in between base and snap1, > you deleted foo. That is recorded in snap1, and when reading a chain, > you stop at the first level of the chain that provides information. > When flattening, it means you are inherently losing any information > about the state that existed before snap1 changed the state, at least > when using the flattened chain to try and find that information. > > Graphically (well, using ASCII), let's look at it like this. When you > start your guest originally, you have a big blank disk being tracked by > the base image, and write into some sectors of that disk. So, use "A" > to represent the initial OS install, and "X" to represent a sector not > yet written: > > base: AAAAXXXXXXXXXXXX > ===> guest: AAAAXXXXXXXXXXXX > > Then, you modify the guest to write the file foo, represent that with > "B" for the sectors that were modified: > > base: AAABBBBBXXXXXXXX > ===> guest: AAABBBBBXXXXXXXX > > then you take a snapshot, at the point you take it, snap1 is completely > empty, but notice that the guest view of the world is still unchanged: > > base: AAABBBBBXXXXXXXX > snap1: XXXXXXXXXXXXXXXX > ===> guest: AAABBBBBXXXXXXXX > > now you do some more modification, such as deleting foo, and creating > bar (note that deleting a file can be done by writing one sector, and > may still leave remnants of the file behind in other sectors, but in > such a way that the guest file system will never retrieve those > contents). Represent these changes with "C" > > base: AAABBBBBXXXXXXXX > snap1: XXXCXXXXCCCCXXXX > ===> guest: AAACBBBBCCCCXXXX > > When you are doing a full blockcopy, you are asking to create a new file > whose contents match what the guest sees. When the copy finally reaches > sync, you have: > > base: AAABBBBBXXXXXXXX > snap1: XXXCXXXXCCCCXXXX > copy: AAACBBBBCCCCXXXX > ===> guest: AAACBBBBCCCCXXXX > > The copy operation lasts as long as you want; in that time, the guest > can make even more changes, let's call them "D" > > base: AAABBBBBXXXXXXXX > snap1: XXXDXXXXCCCCDDDD > copy: AAADBBBBCCCCDDDD > ===> guest: AAADBBBBCCCCDDDD > > then you finally abort or pivot the copy. Let's try a pivot, where the > next action in the guest causes changes to the disk labeled "E": > > base: AAABBBBBXXXXXXXX > snap1: XXXDXXXXCCCCDDDD > > copy: AAAEBBBBCCCCDDDD > ===> guest: AAAEBBBBCCCCDDDD > >> >> PS: I've tested the cases of --pivot, --shallow and --reuse-external, >> will post my notes about them on a wiki. > I hope those help you figure out what's going on. You seem to be hoping > for a magic bullet that gives you file system union mounts (merge the > contents of two different timestamps of a directories existence in a > common file system) - but that is NOT what disk snapshots do. All > libvirt and qemu can do is block level manipulations, not file system > manipulations. I'm not even sure if a file system tool exists that can > do file system checkpoints and/or union mount merges; but if it does, it > would be something you use in the guest at the file system level, and > not something libvirt can manage at the block device sector level. >Wow, very helpful to me. Eric, thank you so much for your explanation. I used to be a little confused with this in bug https://bugzilla.redhat.com/show_bug.cgi?id=1089921#c3. Now I understand. Also I do a simple test, really, the result validate the explanation. The last questions is, "When you are doing a full blockcopy, you are asking to create a new file whose contents match what the guest sees."(should that mean a file system level manipulation?) while you also say "All libvirt and qemu can do is block level manipulations, not file system manipulations."> > > _______________________________________________ > libvirt-users mailing list > libvirt-users@redhat.com > https://www.redhat.com/mailman/listinfo/libvirt-users-- Regards shyu
Kashyap Chamarthy
2014-Jul-04 17:12 UTC
Re: [libvirt-users] virsh blockcopy: doesn't seem to flatten the chain by default
On Thu, Jul 03, 2014 at 11:08:15AM -0600, Eric Blake wrote:> On 07/02/2014 01:12 PM, Kashyap Chamarthy wrote: > > > We have this simple chain: > > > > base <- snap1 > > > > Let's quickly examine the contents of 'base' and 'snap1' images: > > > > > Now, let's do a live blockcopy (with a '--finish' to graecully finish > > the mirroring): > > > > $ virsh blockcopy --domain testvm2 vda \ > > /export/dst/copy.qcow2 \ > > --wait --verbose --finish > > This defaults to a full copy (copy.qcow2 will contain everything in the > latest state of the original chain, but with no backing file). > > > > > > If I'm reading the man page of 'blockcopy' correctly, shouldn't it > > 'flatten' the entire chain, by also copying the contents of base into > > copy.qcow2? i.e. the 'copy' should have files (including the file foo > > from 'base': > > > > foo, bar, baz, jazz > > > > > > True or false? > > False. This is NOT a union mount. Sometime in between base and snap1, > you deleted foo.Hmm, I do realize that if I deleted 'foo' in between the above two points you mentioned, it _does_ reflect in snap1. I realized it's me who made a silly mistake, as I quickly did another test which validates your (very eloquent) details further below. For completness' sake, a correct test below -- it's the simplest case of blockcopy with a depth of chain of 1. 1. Create base image: $ qemu-img create -f qcow2 base.qcow2 1G 2. Create a file system on the disk & add file 'foo': --------------------------------- $ guestfish --rw -a /path/disk.qcow2 [. . .] ><fs> run ><fs> part-disk /dev/sda mbr ><fs> mkfs ext4 /dev/sda1 ><fs> list-filesystems ><fs> mount /dev/sda1 / ><fs> touch /foo ><fs> touch /bar ><fs> ls / foo lost+found ><fs>exit -------------------------------- 2. Create a snapshot, 'snap1' with backing file as 'base': $ qemu-img create -f qcow2 -b base.qcow2 \ -o backing_fmt=qcow2 snap1.qcow2 2.1. Examine contents of 'snap1', add a couple more files: bar, baz, jazz: -------------------------------- $ guestfish --rw -a snap1.qcow2 [. . .] ><fs> run ><fs> mout /dev/sda1 / mout: unknown command ><fs> mount /dev/sda1 / ><fs> ls / foo lost+found ><fs> touch /bar ><fs> touch /baz ><fs> touch /jazz ><fs> ls / bar baz foo jazz lost+found -------------------------------- 3. Provide SELinux context: $ chcon -t svirt_image_t base.qcow2 snap1.qcow2 4. Create a persistent XML file: ---------- $ cat <<EOF > /etc/libvirt/qemu/testvm.xml <domain type='kvm'> <name>testvm</name> <memory unit='MiB'>512</memory> <vcpu>1</vcpu> <os> <type arch='x86_64'>hvm</type> </os> <devices> <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/export/src/snap1.qcow2'/> <target dev='vda' bus='virtio'/> </disk> </devices> </domain> EOF ---------- 5. Perform blockcopy: $ virsh blockcopy --domain testvm vda \ /export/dst/copy.qcow2 \ --wait --verbose --finish Block Copy: [100 %] Successfully copied 6. Examine contents of copy.qcow2: -------------------------------- $ guestfish --ro -a /export/dst/copy.qcow2 ><fs> run ><fs> mount /dev/sda1 / ><fs> ls / bar baz foo jazz lost+found ><fs> quit -------------------------------- 6.1. Enumerate the backing chain of copy.qcow2, it should be a standalone image: -------------------------------- $ qemu-img info --backing-chain /export/dst/copy.qcow2 image: /export/dst/copy.qcow2 file format: qcow2 virtual size: 1.0G (1073741824 bytes) disk size: 18M cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false --------------------------------> That is recorded in snap1, and when reading a chain, > you stop at the first level of the chain that provides information. > When flattening, it means you are inherently losing any information > about the state that existed before snap1 changed the state, at least > when using the flattened chain to try and find that information. > > Graphically (well, using ASCII), let's look at it like this. When you > start your guest originally, you have a big blank disk being tracked by > the base image, and write into some sectors of that disk. So, use "A" > to represent the initial OS install, and "X" to represent a sector not > yet written: > > base: AAAAXXXXXXXXXXXX > ===> guest: AAAAXXXXXXXXXXXX > > Then, you modify the guest to write the file foo, represent that with > "B" for the sectors that were modified: > > base: AAABBBBBXXXXXXXX > ===> guest: AAABBBBBXXXXXXXX > > then you take a snapshot, at the point you take it, snap1 is completely > empty, but notice that the guest view of the world is still unchanged: > > base: AAABBBBBXXXXXXXX > snap1: XXXXXXXXXXXXXXXX > ===> guest: AAABBBBBXXXXXXXX > > now you do some more modification, such as deleting foo, and creating > bar (note that deleting a file can be done by writing one sector, and > may still leave remnants of the file behind in other sectors, but in > such a way that the guest file system will never retrieve those > contents). Represent these changes with "C" > > base: AAABBBBBXXXXXXXX > snap1: XXXCXXXXCCCCXXXX > ===> guest: AAACBBBBCCCCXXXX > > When you are doing a full blockcopy, you are asking to create a new file > whose contents match what the guest sees. When the copy finally reaches > sync, you have: > > base: AAABBBBBXXXXXXXX > snap1: XXXCXXXXCCCCXXXX > copy: AAACBBBBCCCCXXXX > ===> guest: AAACBBBBCCCCXXXX > > The copy operation lasts as long as you want; in that time, the guest > can make even more changes, let's call them "D" > > base: AAABBBBBXXXXXXXX > snap1: XXXDXXXXCCCCDDDD > copy: AAADBBBBCCCCDDDD > ===> guest: AAADBBBBCCCCDDDD > > then you finally abort or pivot the copy. Let's try a pivot, where the > next action in the guest causes changes to the disk labeled "E": > > base: AAABBBBBXXXXXXXX > snap1: XXXDXXXXCCCCDDDD > > copy: AAAEBBBBCCCCDDDD > ===> guest: AAAEBBBBCCCCDDDD > > > > > > > PS: I've tested the cases of --pivot, --shallow and --reuse-external, > > will post my notes about them on a wiki. > > I hope those help you figure out what's going on.They do, thanks for taking time to write these abundantly clear details. As my newer test provied it was a PEBKAC. I really liked the way you denote the 'guest' view and the disk/snapshot views.> You seem to be hoping > for a magic bullet that gives you file system union mounts (merge the > contents of two different timestamps of a directories existence in a > common file system) - but that is NOT what disk snapshots do.In reality I wasn't expecting union mounts at all :-) I didn't think of it actively untill you explicitly mentioned the topic with so much of details.> All > libvirt and qemu can do is block level manipulations, not file system > manipulations. I'm not even sure if a file system tool exists that can > do file system checkpoints and/or union mount merges; but if it does, it > would be something you use in the guest at the file system level, and > not something libvirt can manage at the block device sector level.Understood. Thanks again, for all these details, Eric. -- /kashyap