> DERUMIER, Alexandre <alexandre.derum...@groupe-cyllene.com> hat am 02.04.2025 > 10:01 CEST geschrieben: > > > > > > @@ -716,7 +721,11 @@ sub filesystem_path { > > > > my $dir = $class->get_subdir($scfg, $vtype); > > > > - $dir .= "/$vmid" if $vtype eq 'images'; > > + if ($scfg->{snapext} && $snapname) { > > + $name = $class->get_snap_volname($volname, $snapname); > > + } else { > > + $dir .= "/$vmid" if $vtype eq 'images'; > > + } > > >>this is a bit weird, as it mixes volnames (with the `$vmid/` prefix) > >>and names (without), it's only called twice in this patch, and this > >>here already has $volname parsed, so could we maybe let > >>get_snap_volname take and return the $name part without the dir? > > ok! > > > > > my $path = "$dir/$name"; > > > > @@ -873,7 +882,7 @@ sub clone_image { > > } > > > > sub alloc_image { > > - my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_; > > + my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size, > > $backing) = @_; > > >>this extends the storage API, so it should actually do that.. and > >>probably $backing should not be an arbitrary path, but something that > >>is resolved locally? > > I'll send the $snapname as param instead
see my comments on the qemu-server side, I think it would be even better if we could just get rid of extending alloc_image like this, and instead always go via volume_snapshot.. > > > > + > > + if($backing) { > > + push @$cmd, '-b', $backing, '-F', 'qcow2'; > > + push @$options, 'extended_l2=on','cluster_size=128k'; > > + }; > > + push @$options, preallocation_cmd_option($scfg, $fmt); > > + push @$cmd, '-o', join(',', @$options) if @$options > 0; > > + push @$cmd, '-f', $fmt, $path; > > + push @$cmd, "${size}K" if !$backing; > > >>is this because it will automatically take the size from the backing > >>image? > > Yes, it take size from the backing. (and refuse if you specify size > param at the same time than backing file) we pass a size and a backing file in qemu-server, so I guess that is wrong there? ;) > > > > + my $path = $class->path($scfg, $volname, $storeid); > > + my $snappath = $class->path($scfg, $volname, $storeid, $snap); > > + #rename current volume to snap volume > > + die "snapshot volume $snappath already exist\n" if -e $snappath; > > + rename($path, $snappath) if -e $path; > > >>this is still looking weird.. I don't think it makes sense interface > >>wise to allow snapshotting a volume that doesn't even exist.. > > This is more by security, I'm still unsure of the behaviour if you have > multiple disks, and that snapshot is dying in the middle. (1 disk > rename, the other not renamed). I am not sure what we gain by this other than papering over issues. for multi-disks what we'd need to do is: - loop over volumes -- take a snapshot of volume -- as part of error handling directly in taking a snapshot, undo all steps done until the point of error - if an error occurs, loop over all already correctly snapshotted volumes -- undo snapshot of each such volume > > > + > > + my ($vtype, $name, $vmid, undef, undef, $isBase, $format) = > > + $class->parse_volname($volname); > > + > > + $class->alloc_image($storeid, $scfg, $vmid, 'qcow2', $name, undef, > > $snappath); > > + if ($@) { > > + eval { $class->free_image($storeid, $scfg, $volname, 0) }; > > + warn $@ if $@; > > >>missing cleanup - this should undo the rename from above > > Do you have an idea how to do it with mutiple disk ? > (revert renaming of other disks elsewhere in the code? just keep them > like this)? see above, the volume_snapshot task should clean up what it did up to the point of error, and its caller is responsible for undoing already completed volume_snapshot calls. obviously this won't always work (for example, if the snapshot fails because the storage has a problem, it's very likely that undoing things is not possible either and manual cleanup will be required) > > > > > > @@ -1187,9 +1251,15 @@ sub volume_snapshot_rollback { > > > > my $path = $class->filesystem_path($scfg, $volname); > > > > - my $cmd = ['/usr/bin/qemu-img', 'snapshot','-a', $snap, $path]; > > - > > - run_command($cmd); > > + if ($scfg->{snapext}) { > > + #simply delete the current snapshot and recreate it > > + my $path = $class->filesystem_path($scfg, $volname); > > + unlink($path); > > + $class->volume_snapshot($scfg, $storeid, $volname, $snap); > > >>instead of volume_snapshot, this could simply call alloc_image with > >>the backing file? then volume_snapshot could always rename and always > >>cleanup properly.. > > Yes , better like this indeed I think alloc_image should be split into an internal helper that takes the backing file parameter, and the existing alloc_image that shouldn't get that parameter though > > > > > + } else { > > + #we rebase the child image on the parent as new backing image > > >>should we extend this to make it clear what this means? it means > >>copying any parts of $snap that are not in $parent and not yet > >>overwritten by $child into $child, right? > >> > yes, > intermediate snapshot: (rebase) > ------------------------------- > snap1 (10G)-->snap2 (1G)----current(1G) > ---> delete snap2 > > rebase current on snap1 > > snap1(10G)----->current(2G) > > > or > > snap1 (10G)-->snap2 (1G)----> snap3 (1G)--->current(1G) > ---> delete snap2 > > rebase snap3 on snap1 > > snap1 (10G)---> snap3 (2G)--->current(1G) > > > > >>so how expensive this is depends on: > >>- how many changes are between $parent and $snap (increases cost) > >>- how many of those are overwritten by changes between $snap and > >>$child (decreases cost) > > > but yes, the final size of the child is not 100% the additional content > of the deleted snapshot, if some blocks has already been overwriten in > the child > > > so, we could call it: "merge diff content of the delete snap to the > childsnap" > > > > > > >>+sub get_snap_volname { > >>+ my ($class, $volname, $snapname) = @_; > >>+ > >>+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, > >>$format) = $class->parse_volname($volname); > + $name = !$snapname || $snapname eq 'current' ? $volname : > "$vmid/snap-$snapname-$name"; > > >>other way round would be better to group by volume first IMHO > ($vmid/snap-$name-$snapname), as this is similar to how we encode > >>snapshots often on the storage level (volume@snap). we also need to > >>have some delimiter between snapshot and volume name that is not > >>allowed in either (hard for volname since basically everything but > >>'/' goes, but snapshots have a restricted character set (configid, > >>which means alphanumeric, hyphen and underscore), so we could use > >>something like '.' as delimiter? or we switch to directories and do > >>$vmid/snap/$snap/$name?) > > Personnaly, I prefer a '.' delimiter than sub directory. (better to > have the info in the filename itself) we can still bikeshed this later once other issue are ironed out, I just wanted to note it - it's very unfortunate that volume names currently are so unrestricted, but we have to live with it for now. I just realized that even snap-XXX.qcow2 would be recognized/returned as image, so we need something else or filter them out anyway. _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel