all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
To: "Fabian Grünbichler" <f.gruenbichler@proxmox.com>
Cc: Proxmox VE development discussion <pve-devel@lists.proxmox.com>
Subject: Re: [pve-devel] [PATCH v2 storage 1/5] add BTRFS storage plugin
Date: Wed, 23 Jun 2021 14:43:31 +0200	[thread overview]
Message-ID: <20210623124331.ksyp7zej77htcvd6@olga.proxmox.com> (raw)
In-Reply-To: <1624446697.vi3jolanip.astroid@nora.none>

On Wed, Jun 23, 2021 at 02:15:00PM +0200, Fabian Grünbichler wrote:
> On June 22, 2021 2:18 pm, Wolfgang Bumiller wrote:
(...)
> > +sub plugindata {
> > +    return {
> > +	content => [
> > +	    {
> > +		images => 1,
> > +		rootdir => 1,
> > +		vztmpl => 1,
> > +		iso => 1,
> > +		backup => 1,
> > +		snippets => 1,
> > +		none => 1,
> > +	    },
> > +	    { images => 1, rootdir => 1 },
> > +	],
> > +	format => [ { raw => 1, qcow2 => 1, vmdk => 1, subvol => 1 }, 'raw', ],
> 
> I am not really convinced we need this (or rather, that it doesn't 
> cause more confusion than convenience. if I want to use btrfs without 
> any btrfs features, I can already use any btrfs-backed dir as dir 
> storage (just like with ZFS, or $storage-of-my-choice-providing-a-directory).
> 
> e.g., having a qcow2 file on btrfs storage support snapshots but not use 
> btrfs functionality for that seems... weird?

It's a directory storage after all.
But I really don't mind much if we just remove that...

> 
> > +    };
> > +}
> > +
> > +sub options {
> > +    return {
> > +	path => { fixed => 1 },
> > +	nodes => { optional => 1 },
> > +	shared => { optional => 1 },
> > +	disable => { optional => 1 },
> > +	maxfiles => { optional => 1 },
> > +	content => { optional => 1 },
> > +	format => { optional => 1 },
> > +	is_mountpoint => { optional => 1 },
> > +	# TODO: The new variant of mkdir with  `populate` vs `create`...
> > +    };
> > +}
> > +
> > +# Storage implementation
> > +#
> > +# We use the same volume names are directory plugins, but map *raw* disk image file names into a
> > +# subdirectory.
> > +#
> > +# `vm-VMID-disk-ID.raw`
> > +#   -> `images/VMID/vm-VMID-disk-ID/disk.raw`
> > +#   where the `vm-VMID-disk-ID/` subdirectory is a btrfs subvolume
> > +
> > +# Reuse `DirPlugin`'s `check_config`. This simply checks for invalid paths.
> > +sub check_config {
> > +    my ($self, $sectionId, $config, $create, $skipSchemaCheck) = @_;
> > +    return PVE::Storage::DirPlugin::check_config($self, $sectionId, $config, $create, $skipSchemaCheck);
> > +}
> > +
> > +sub activate_storage {
> > +    my ($class, $storeid, $scfg, $cache) = @_;
> > +    return PVE::Storage::DirPlugin::activate_storage($class, $storeid, $scfg, $cache);
> 
> shouldn't this check that we can actually do btrfs stuff on $path?

Right. I had a method for this at some point but hadn't used it here.
Should be easily added in a follow up.

> 
> > +}
> > +
> > +sub status {
> > +    my ($class, $storeid, $scfg, $cache) = @_;
> > +    return PVE::Storage::DirPlugin::status($class, $storeid, $scfg, $cache);
> > +}
> > +
> > +# TODO: sub get_volume_notes {}
> > +
> > +# TODO: sub update_volume_notes {}
> > +
> > +# croak would not include the caller from within this module
> > +sub __error {
> > +    my ($msg) = @_;
> > +    my (undef, $f, $n) = caller(1);
> > +    die "$msg at $f: $n\n";
> > +}
> 
> this is kind of a new style of error handling - might be worthy of a 
> mention somewhere ;)

debug helper... shouldn't be possible to reach this... I should probably
prefix the 2 subs below with a `my` though...
(I mostly ran into such stuff while playing with different ways of
naming/organising snapshot directories and not seeing *where* stuff
happened was annoying...)

> 
> > +
> > +# Given a name (eg. `vm-VMID-disk-ID.raw`), take the part up to the format suffix as the name of
> > +# the subdirectory (subvolume).
> > +sub raw_name_to_dir($) {
> > +    my ($raw) = @_;
> > +
> > +    # For the subvolume directory Strip the `.<format>` suffix:
> > +    if ($raw =~ /^(.*)\.raw$/) {
> > +	return $1;
> > +    }
> > +
> > +    __error "internal error: bad disk name: $raw";
> > +}
> > +
> > +sub raw_file_to_subvol($) {
> > +    my ($file) = @_;
> > +
> > +    if ($file =~ m|^(.*)/disk\.raw$|) {
> > +	return "$1";
> > +    }
> > +
> > +    __error "internal error: bad raw path: $file";
> > +}
> > +
(...)
> > +
> > +sub btrfs_get_subvol_id {
> > +    my ($class, $path) = @_;
> > +    my $info = $class->btrfs_cmd(['subvolume', 'show', '--', $path]);
> > +    if ($info !~ /^\s*(?:Object|Subvolume) ID:\s*(\d+)$/m) {
> > +	die "failed to get btrfs subvolume ID from: $info\n";
> 
> ugh at yet another parser for CLI tool output.. (not your fault I 
> know..)

This one I can actually replace. I just am not sure if I want to do it
all in pure perl or add some btrfs helper to the emerging `pve-rs` lib,
and since this code already existed in the old series, I postponed that
decision.


(...)
> > +    my $imagedir = $class->get_subdir($scfg, 'images');
> > +    $imagedir .= "/$vmid";
> > +    mkpath $imagedir;
> > +
> > +    my $path = $class->filesystem_path($scfg, $volname);
> > +    my $newname = $class->find_free_diskname($storeid, $scfg, $vmid, $format, 1);
> > +
> > +    # For btrfs subvolumes we don't actually need the "link":
> > +    #my $newvolname = "$basevmid/$basename/$vmid/$newname";
> > +    my $newvolname = "$vmid/$newname";
> > +    my $newpath = $class->filesystem_path($scfg, $newvolname);
> > +
> > +    my $subvol = $path;
> > +    my $newsubvol = $newpath;
> > +    if ($format eq 'raw') {
> > +	$subvol = raw_file_to_subvol($subvol);
> > +	$newsubvol = raw_file_to_subvol($newsubvol);
> > +    }
> 
> so actually these are two blocks for getting at $subvol and $newsubvol, 
> one for raw one for subvol. structuring it as such would make it more 
> readable IMHO..

Yeah I suppose those lines could look nicer. Also happens another
time...

> 
> > +
> > +    $class->btrfs_cmd(['subvolume', 'snapshot', '--', $subvol, $newsubvol]);
> > +
> > +    return $newvolname;
> > +}
> > +
> > +sub alloc_image {
> > +    my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
> > +
> > +    if ($fmt ne 'raw' && $fmt ne 'subvol') {
> > +	return PVE::Storage::DirPlugin::alloc_image(@_);
> > +    }
> > +
> > +    # From Plugin.pm:
> > +
> > +    my $imagedir = $class->get_subdir($scfg, 'images') . "/$vmid";
> > +
> > +    mkpath $imagedir;
> > +
> > +    $name = $class->find_free_diskname($storeid, $scfg, $vmid, $fmt, 1) if !$name;
> > +
> > +    my (undef, $tmpfmt) = PVE::Storage::Plugin::parse_name_dir($name);
> > +
> > +    die "illegal name '$name' - wrong extension for format ('$tmpfmt != '$fmt')\n"
> > +	if $tmpfmt ne $fmt;
> > +
> > +    # End copy from Plugin.pm
> > +
> > +    my $subvol = "$imagedir/$name";
> > +    # .raw is not part of the directory name
> > +    $subvol =~ s/\.raw$//;
> 
> why not use your helpers for this (raw_.._to_..)

Here it can refer to a `subvol` as well which the helper doesn't allow,
but sure, could be improved.

> in a similar vain, there are three "add '/disk.raw' to path" sites 
> that might warrant a helper..

ok

(...)
> > +sub volume_snapshot {
> > +    my ($class, $scfg, $storeid, $volname, $snap) = @_;
> > +
> > +    my ($name, $vmid, $format) = ($class->parse_volname($volname))[1,2,6];
> > +    if ($format ne 'subvol' && $format ne 'raw') {
> > +	return PVE::Storage::Plugin::volume_snapshot(@_);
> > +    }
> > +
> > +    my $path = $class->filesystem_path($scfg, $volname);
> > +    my $snap_path = $class->filesystem_path($scfg, $volname, $snap);
> > +
> > +    if ($format eq 'raw') {
> > +	$path = raw_file_to_subvol($path);
> > +	$snap_path = raw_file_to_subvol($snap_path);
> > +    }
> 
> this is a repeating pattern (volname + optional snapshot name => path(s) 
> based on format)

yup, mentioned it above

> 
> > +
> > +    my $snapshot_dir = $class->get_subdir($scfg, 'images') . "/$vmid";
> > +    mkpath $snapshot_dir;
> > +
> > +    $class->btrfs_cmd(['subvolume', 'snapshot', '-r', '--', $path, $snap_path]);
> > +    return undef;
> > +}
> > +
> > +sub volume_rollback_is_possible {
> > +    my ($class, $scfg, $storeid, $volname, $snap) = @_; 
> > +
> > +    return 1; 
> 
> snapshot creation was delegated to Plugin.pm for non-raw and non-subvol, 
> so if we don't drop that part the same logic would need to apply here..

Ah, good catch.

(...)
> > +sub volume_has_feature {
> > +    my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_;
> > +
> > +    my $features = {
> > +	snapshot => {
> > +	    current => { qcow2 => 1, raw => 1, subvol => 1 },
> > +	    snap => { qcow2 => 1, raw => 1, subvol => 1 }
> > +	},
> > +	clone => {
> > +	    base => { qcow2 => 1, raw => 1, subvol => 1, vmdk => 1 },
> > +	    current => { raw => 1 },
> > +	    snap => { raw => 1 },
> > +	},
> > +	template => { current => { qcow2 => 1, raw => 1, vmdk => 1, subvol => 1 } },
> > +	copy => {
> > +	    base => { qcow2 => 1, raw => 1, subvol => 1, vmdk => 1 },
> > +	    current => { qcow2 => 1, raw => 1, subvol => 1, vmdk => 1 },
> > +	    snap => { qcow2 => 1, raw => 1, subvol => 1 },
> > +	},
> > +	sparseinit => { base => {qcow2 => 1, raw => 1, vmdk => 1 },
> > +			current => {qcow2 => 1, raw => 1, vmdk => 1 } },
> > +    };
> 
> some of that is duplicated from the regular plugin, so if we don't drop 
> the qcow2/.. support here we need to forward those based on $format..

good point




  reply	other threads:[~2021-06-23 12:44 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-22 12:18 [pve-devel] [PATCH v2 multiple] btrfs, file system for the brave Wolfgang Bumiller
2021-06-22 12:18 ` [pve-devel] [PATCH v2 storage 1/5] add BTRFS storage plugin Wolfgang Bumiller
2021-06-23 12:15   ` Fabian Grünbichler
2021-06-23 12:43     ` Wolfgang Bumiller [this message]
2021-06-22 12:18 ` [pve-devel] [PATCH v2 storage 2/5] bump storage API: update import/export methods Wolfgang Bumiller
2021-06-22 12:18 ` [pve-devel] [PATCH v2 storage 3/5] btrfs: add 'btrfs' import/export format Wolfgang Bumiller
2021-06-23 12:14   ` Fabian Grünbichler
2021-06-23 12:30     ` Wolfgang Bumiller
2021-06-22 12:18 ` [pve-devel] [PATCH v2 storage 4/5] btrfs: make NOCOW optional Wolfgang Bumiller
2021-06-22 12:18 ` [pve-devel] [PATCH v2 storage 5/5] btrfs: support quota-based subvols optionally Wolfgang Bumiller
2021-06-22 12:18 ` [pve-devel] [PATCH v2 container 1/3] migration: fix snapshots boolean accounting Wolfgang Bumiller
2021-06-23 10:59   ` Fabian Grünbichler
2021-06-23 12:31     ` Wolfgang Bumiller
2021-06-22 12:18 ` [pve-devel] [PATCH v2 container 2/3] enable btrfs support via subvolumes Wolfgang Bumiller
2021-06-22 12:18 ` [pve-devel] [PATCH v2 container 3/3] special case btrfs+quotas to use subvolumes Wolfgang Bumiller
2021-06-23 13:51   ` Fabian Grünbichler
2021-06-22 12:18 ` [pve-devel] [PATCH v2 qemu-server] allow migrating raw btrfs volumes Wolfgang Bumiller
2021-06-23 10:51   ` [pve-devel] applied: " Thomas Lamprecht
2021-06-23 20:19 ` [pve-devel] applied-partially: [PATCH v2 multiple] btrfs, file system for the brave Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210623124331.ksyp7zej77htcvd6@olga.proxmox.com \
    --to=w.bumiller@proxmox.com \
    --cc=f.gruenbichler@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal