1
0
mirror of https://github.com/openSUSE/snapper.git synced 2026-02-05 15:46:00 +01:00

- support sending compressed data in snbk

This commit is contained in:
Arvin Schnell
2025-10-07 14:58:15 +02:00
parent 945887a425
commit e5fd6527d8
11 changed files with 227 additions and 13 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 SUSE LLC
* Copyright (c) [2024-2025] SUSE LLC
*
* All Rights Reserved.
*
@@ -70,6 +70,10 @@ namespace snapper
get_child_value(json_file.get_root(), "ssh-identity", ssh_identity);
}
get_child_value(json_file.get_root(), "send-compressed-data", send_compressed_data);
get_child_nodes(json_file.get_root(), "send-options", send_options);
get_child_nodes(json_file.get_root(), "receive-options", receive_options);
get_child_value(json_file.get_root(), "target-btrfs-bin", target_btrfs_bin);
get_child_value(json_file.get_root(), "target-findmnt-bin", target_findmnt_bin);
get_child_value(json_file.get_root(), "target-mkdir-bin", target_mkdir_bin);

View File

@@ -70,6 +70,10 @@ namespace snapper
Shell get_source_shell() const;
Shell get_target_shell() const;
bool send_compressed_data = true;
vector<string> send_options;
vector<string> receive_options;
string target_btrfs_bin = BTRFS_BIN;
string target_findmnt_bin = FINDMNT_BIN;
string target_mkdir_bin = MKDIR_BIN;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) [2004-2015] Novell, Inc.
* Copyright (c) [2017-2024] SUSE LLC
* Copyright (c) [2017-2025] SUSE LLC
*
* All Rights Reserved.
*
@@ -21,6 +21,7 @@
*/
#include <sys/utsname.h>
#include <cstring>
#include <regex>
#include <boost/algorithm/string.hpp>
@@ -259,4 +260,88 @@ namespace snapper
return s;
}
void
CmdBtrfsVersion::query_version()
{
if (did_set_version)
return;
SystemCmd::Args cmd_args = { btrfs_bin, "--version" };
SystemCmd cmd(shellify(shell, cmd_args));
if (cmd.retcode() != 0)
{
y2err("command '" << cmd.cmd() << "' failed: " << cmd.retcode());
for (const string& tmp : cmd.get_stdout())
y2err(tmp);
for (const string& tmp : cmd.get_stderr())
y2err(tmp);
SN_THROW(Exception("'btrfs --version' failed"));
}
parse_version(cmd.get_stdout()[0]);
}
void
CmdBtrfsVersion::parse_version(const string& version)
{
// example versions: "5.14 " (yes, with a trailing space), "6.0", "6.0.2"
const regex version_rx("btrfs-progs v([0-9]+)\\.([0-9]+)(\\.([0-9]+))?( )*", regex::extended);
smatch match;
if (!regex_match(version, match, version_rx))
SN_THROW(Exception("failed to parse btrfs version '" + version + "'"));
major = stoi(match[1]);
minor = stoi(match[2]);
patchlevel = match[4].length() == 0 ? 0 : stoi(match[4]);
y2mil("major:" << major << " minor:" << minor << " patchlevel:" << patchlevel);
did_set_version = true;
}
int
CmdBtrfsVersion::supported_proto()
{
query_version();
if (major >= 6)
return 2;
return 1;
}
int
Uname::supported_proto()
{
const regex release_rx("^([0-9]+)\\.([0-9]+).*", regex::extended);
struct utsname buffer;
if (uname(&buffer) < 0)
SN_THROW(Exception("syscall uname failed"));
cmatch match;
if (!regex_match(buffer.release, match, release_rx))
SN_THROW(Exception("failed to parse uname release '" + string(buffer.release) + "'"));
int major = stoi(match[1]);
int minor = stoi(match[2]);
y2mil("major:" << major << " minor:" << minor);
if (major >= 6)
return 2;
return 1;
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) [2004-2015] Novell, Inc.
* Copyright (c) [2017-2024] SUSE LLC
* Copyright (c) [2017-2025] SUSE LLC
*
* All Rights Reserved.
*
@@ -116,6 +116,45 @@ namespace snapper
};
/**
* Lazy query of btrfs command version.
*/
class CmdBtrfsVersion
{
public:
CmdBtrfsVersion(const string& btrfs_bin, const Shell& shell)
: btrfs_bin(btrfs_bin), shell(shell)
{}
int supported_proto();
private:
void query_version();
void parse_version(const string& version);
const string btrfs_bin;
const Shell shell;
bool did_set_version = false;
int major = 0;
int minor = 0;
int patchlevel = 0;
};
class Uname
{
public:
static int supported_proto();
};
}
#endif

View File

@@ -20,7 +20,7 @@
*/
#include <stdio.h>
#include <cstdio>
#include <sys/stat.h>
#include <functional>
#include <memory>
@@ -187,6 +187,28 @@ namespace snapper
}
bool
get_child_nodes(json_object* parent, const char* name, vector<string>& values)
{
vector<json_object*> children;
if (!get_child_nodes(parent, name, children))
return false;
values.clear();
for (json_object* child : children)
{
if (!json_object_is_type(child, json_type_string))
return false;
values.push_back(json_object_get_string(child));
}
return true;
}
bool
get_child_nodes(json_object* parent, const char* name, vector<json_object*>& children)
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) [2017-2024] SUSE LLC
* Copyright (c) [2017-2025] SUSE LLC
*
* All Rights Reserved.
*
@@ -68,6 +68,9 @@ namespace snapper
get_child_value(json_object* parent, const char* name, Type& value);
bool
get_child_nodes(json_object* parent, const char* name, vector<string>& values);
bool
get_child_nodes(json_object* parent, const char* name, vector<json_object*>& children);

View File

@@ -57,7 +57,7 @@ namespace snapper
void
TheBigThing::transfer(const BackupConfig& backup_config, const TheBigThings& the_big_things,
TheBigThing::transfer(const BackupConfig& backup_config, TheBigThings& the_big_things,
bool quiet)
{
if (!quiet)
@@ -137,16 +137,29 @@ namespace snapper
// Copy snapshot to target.
const int proto = std::min({
Uname::supported_proto(),
the_big_things.source_btrfs_version.supported_proto(),
the_big_things.target_btrfs_version.supported_proto()
});
TheBigThings::const_iterator it1 = the_big_things.find_send_parent(*this);
SystemCmd::Args cmd3a_args = { BTRFS_BIN, "send" };
if (proto >= 2)
cmd3a_args << "--proto" << to_string(proto);
if (backup_config.send_compressed_data && proto >= 2)
cmd3a_args << "--compressed-data";
cmd3a_args << backup_config.send_options;
if (it1 != the_big_things.end())
cmd3a_args << "-p" << backup_config.source_path + "/" SNAPSHOTS_NAME "/" +
to_string(it1->num) + "/" SNAPSHOT_NAME;
cmd3a_args << "--" << backup_config.source_path + "/" SNAPSHOTS_NAME "/" + num_string + "/" SNAPSHOT_NAME;
SystemCmd::Args cmd3b_args = { backup_config.target_btrfs_bin, "receive", "--",
backup_config.target_path + "/" + num_string };
SystemCmd::Args cmd3b_args = { backup_config.target_btrfs_bin, "receive" };
cmd3b_args << backup_config.receive_options;
cmd3b_args << "--" << backup_config.target_path + "/" + num_string;
y2deb("source: " << cmd3a_args.get_values());
y2deb("target: " << cmd3b_args.get_values());
@@ -238,7 +251,9 @@ namespace snapper
TheBigThings::TheBigThings(const BackupConfig& backup_config, ProxySnappers* snappers, bool verbose)
: snapper(snappers->getSnapper(backup_config.config)), locker(snapper)
: source_btrfs_version(BTRFS_BIN, backup_config.get_source_shell()),
target_btrfs_version(backup_config.target_btrfs_bin, backup_config.get_target_shell()),
snapper(snappers->getSnapper(backup_config.config)), locker(snapper)
{
if (backup_config.source_path != snapper->getConfig().getSubvolume())
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 SUSE LLC
* Copyright (c) [2024-2025] SUSE LLC
*
* All Rights Reserved.
*
@@ -29,6 +29,8 @@
#include "../proxy/proxy.h"
#include "../proxy/locker.h"
#include "CmdBtrfs.h"
namespace snapper
{
@@ -52,7 +54,7 @@ namespace snapper
TheBigThing(unsigned int num) : num(num) {}
void transfer(const BackupConfig& backup_config, const TheBigThings& the_big_things, bool quiet);
void transfer(const BackupConfig& backup_config, TheBigThings& the_big_things, bool quiet);
void remove(const BackupConfig& backup_config, bool quiet);
@@ -110,6 +112,9 @@ namespace snapper
*/
const_iterator find_send_parent(const TheBigThing& the_big_thing) const;
CmdBtrfsVersion source_btrfs_version;
CmdBtrfsVersion target_btrfs_version;
private:
const ProxySnapper* snapper;

View File

@@ -2,13 +2,13 @@
<refentry id='snapper-backup-configs5'>
<refentryinfo>
<date>2025-04-09</date>
<date>2025-10-07</date>
</refentryinfo>
<refmeta>
<refentrytitle>snapper-backup-configs</refentrytitle>
<manvolnum>5</manvolnum>
<refmiscinfo class='date'>2025-04-09</refmiscinfo>
<refmiscinfo class='date'>2025-10-07</refmiscinfo>
<refmiscinfo class='version'>@VERSION@</refmiscinfo>
<refmiscinfo class='manual'>Filesystem Snapshot Management</refmiscinfo>
</refmeta>
@@ -102,6 +102,33 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>send-compressed-data</option></term>
<listitem>
<para>Per default snbk will add the option --compressed-data iff
supported by the source and target system. This can be disable by
setting this value to false.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>send-options</option></term>
<listitem>
<para>Extra options for the btrfs send command as an array
of strings. Optional.</para>
<para>Per default snbk automatically adds --proto and --compressed-data
iff supported by both the source and target.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>receive-options</option></term>
<listitem>
<para>Extra options for the btrfs receive command as an
array of strings. Optional.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>target-btrfs-bin</option></term>
<listitem>

View File

@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Tue Oct 07 14:42:16 CEST 2025 - aschnell@suse.com
- support sending compressed data in snbk
(gh#openSUSE/snapper#1059)
-------------------------------------------------------------------
Wed Sep 24 16:12:34 CEST 2025 - aschnell@suse.com

View File

@@ -1,5 +1,9 @@
#!/bin/bash
if [ "$#" -eq 1 ] && [ "$1" == "--version" ]; then
exec sudo /usr/sbin/btrfs --version
fi
if [ "$#" -lt 3 ]; then
echo "Usage: $0 <group> [subcommand] [options] -- /backup/..."
exit 1