mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #34190 from DaanDeMeyer/repart-compress
repart: Add compression support
This commit is contained in:
commit
02e875e1c2
@ -811,6 +811,68 @@
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Compression=</varname></term>
|
||||
|
||||
<listitem><para>Specify the compression algorithm to use for the filesystem configured with
|
||||
<varname>Format=</varname>. Takes a single argument specifying the compression algorithm.</para>
|
||||
|
||||
<para>Note that this setting is only taken into account when the filesystem configured with
|
||||
<varname>Format=</varname> supports compression (btrfs, squashfs, erofs). Here's an incomplete list
|
||||
of compression algorithms supported by the filesystems known to
|
||||
<command>systemd-repart</command>:</para>
|
||||
|
||||
<table>
|
||||
<title>File System Compression Algorithms</title>
|
||||
|
||||
<tgroup cols='3' align='left' colsep='1' rowsep='1'>
|
||||
<colspec colname="filesystem" />
|
||||
<colspec colname="algorithms" />
|
||||
<colspec colname="manpage" />
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry>File System</entry>
|
||||
<entry>Compression Algorithms</entry>
|
||||
<entry>Documentation</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><constant>squashfs</constant></entry>
|
||||
<entry>gzip, lzo, lz4, xz, zstd, lzma</entry>
|
||||
<entry><member><citerefentry project='man-pages'><refentrytitle>mksquashfs</refentrytitle><manvolnum>1</manvolnum></citerefentry></member></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><constant>erofs</constant></entry>
|
||||
<entry>lz4, lz4hc, lzma, deflate, libdeflate, zstd</entry>
|
||||
<entry><member><citerefentry project='man-pages'><refentrytitle>mkfs.erofs</refentrytitle><manvolnum>1</manvolnum></citerefentry></member></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>CompressionLevel=</varname></term>
|
||||
|
||||
<listitem><para>Specify the compression level to use for the filesystem configured with
|
||||
<varname>Format=</varname>. Takes a single argument specifying the compression level to use for the
|
||||
configured compression algorithm. The possible compression levels and their meaning are filesystem
|
||||
specific (refer to the filesystem's documentation for the exact meaning of a particular compression
|
||||
level).</para>
|
||||
|
||||
<para>Note that this setting is only taken into account when the filesystem configured with
|
||||
<varname>Format=</varname> supports compression and the <varname>Compression=</varname> setting is
|
||||
configured explicitly.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -73,12 +73,7 @@ wrap=(
|
||||
lvm
|
||||
mdadm
|
||||
mkfs.btrfs
|
||||
mkfs.erofs
|
||||
mkfs.ext4
|
||||
mkfs.vfat
|
||||
mkfs.xfs
|
||||
mksquashfs
|
||||
mkswap
|
||||
multipath
|
||||
multipathd
|
||||
nvme
|
||||
|
@ -2378,6 +2378,8 @@ int home_create_luks(
|
||||
user_record_luks_discard(h),
|
||||
/* quiet = */ true,
|
||||
/* sector_size = */ 0,
|
||||
/* compression = */ NULL,
|
||||
/* compression_level= */ NULL,
|
||||
extra_mkfs_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -78,6 +78,8 @@ static int run(int argc, char *argv[]) {
|
||||
/* discard = */ true,
|
||||
/* quiet = */ true,
|
||||
/* sector_size = */ 0,
|
||||
/* compression = */ NULL,
|
||||
/* compression_level = */ NULL,
|
||||
/* extra_mkfs_options = */ NULL);
|
||||
}
|
||||
|
||||
|
@ -385,6 +385,8 @@ typedef struct Partition {
|
||||
MinimizeMode minimize;
|
||||
uint64_t verity_data_block_size;
|
||||
uint64_t verity_hash_block_size;
|
||||
char *compression;
|
||||
char *compression_level;
|
||||
|
||||
uint64_t gpt_flags;
|
||||
int no_auto;
|
||||
@ -545,6 +547,8 @@ static Partition* partition_free(Partition *p) {
|
||||
ordered_hashmap_free(p->subvolumes);
|
||||
free(p->default_subvolume);
|
||||
free(p->verity_match_key);
|
||||
free(p->compression);
|
||||
free(p->compression_level);
|
||||
|
||||
iovec_done(&p->roothash);
|
||||
|
||||
@ -581,6 +585,8 @@ static void partition_foreignize(Partition *p) {
|
||||
p->subvolumes = ordered_hashmap_free(p->subvolumes);
|
||||
p->default_subvolume = mfree(p->default_subvolume);
|
||||
p->verity_match_key = mfree(p->verity_match_key);
|
||||
p->compression = mfree(p->compression);
|
||||
p->compression_level = mfree(p->compression_level);
|
||||
|
||||
p->priority = 0;
|
||||
p->weight = 1000;
|
||||
@ -2088,38 +2094,40 @@ static int partition_finalize_fstype(Partition *p, const char *path) {
|
||||
static int partition_read_definition(Partition *p, const char *path, const char *const *conf_file_dirs) {
|
||||
|
||||
ConfigTableItem table[] = {
|
||||
{ "Partition", "Type", config_parse_type, 0, &p->type },
|
||||
{ "Partition", "Label", config_parse_label, 0, &p->new_label },
|
||||
{ "Partition", "UUID", config_parse_uuid, 0, p },
|
||||
{ "Partition", "Priority", config_parse_int32, 0, &p->priority },
|
||||
{ "Partition", "Weight", config_parse_weight, 0, &p->weight },
|
||||
{ "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight },
|
||||
{ "Partition", "SizeMinBytes", config_parse_size4096, -1, &p->size_min },
|
||||
{ "Partition", "SizeMaxBytes", config_parse_size4096, 1, &p->size_max },
|
||||
{ "Partition", "PaddingMinBytes", config_parse_size4096, -1, &p->padding_min },
|
||||
{ "Partition", "PaddingMaxBytes", config_parse_size4096, 1, &p->padding_max },
|
||||
{ "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset },
|
||||
{ "Partition", "CopyBlocks", config_parse_copy_blocks, 0, p },
|
||||
{ "Partition", "Format", config_parse_fstype, 0, &p->format },
|
||||
{ "Partition", "CopyFiles", config_parse_copy_files, 0, &p->copy_files },
|
||||
{ "Partition", "ExcludeFiles", config_parse_exclude_files, 0, &p->exclude_files_source },
|
||||
{ "Partition", "ExcludeFilesTarget", config_parse_exclude_files, 0, &p->exclude_files_target },
|
||||
{ "Partition", "MakeDirectories", config_parse_make_dirs, 0, &p->make_directories },
|
||||
{ "Partition", "Encrypt", config_parse_encrypt, 0, &p->encrypt },
|
||||
{ "Partition", "Verity", config_parse_verity, 0, &p->verity },
|
||||
{ "Partition", "VerityMatchKey", config_parse_string, 0, &p->verity_match_key },
|
||||
{ "Partition", "Flags", config_parse_gpt_flags, 0, &p->gpt_flags },
|
||||
{ "Partition", "ReadOnly", config_parse_tristate, 0, &p->read_only },
|
||||
{ "Partition", "NoAuto", config_parse_tristate, 0, &p->no_auto },
|
||||
{ "Partition", "GrowFileSystem", config_parse_tristate, 0, &p->growfs },
|
||||
{ "Partition", "SplitName", config_parse_string, 0, &p->split_name_format },
|
||||
{ "Partition", "Minimize", config_parse_minimize, 0, &p->minimize },
|
||||
{ "Partition", "Subvolumes", config_parse_subvolumes, 0, &p->subvolumes },
|
||||
{ "Partition", "DefaultSubvolume", config_parse_default_subvolume, 0, &p->default_subvolume },
|
||||
{ "Partition", "VerityDataBlockSizeBytes", config_parse_block_size, 0, &p->verity_data_block_size },
|
||||
{ "Partition", "VerityHashBlockSizeBytes", config_parse_block_size, 0, &p->verity_hash_block_size },
|
||||
{ "Partition", "MountPoint", config_parse_mountpoint, 0, p },
|
||||
{ "Partition", "EncryptedVolume", config_parse_encrypted_volume, 0, p },
|
||||
{ "Partition", "Type", config_parse_type, 0, &p->type },
|
||||
{ "Partition", "Label", config_parse_label, 0, &p->new_label },
|
||||
{ "Partition", "UUID", config_parse_uuid, 0, p },
|
||||
{ "Partition", "Priority", config_parse_int32, 0, &p->priority },
|
||||
{ "Partition", "Weight", config_parse_weight, 0, &p->weight },
|
||||
{ "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight },
|
||||
{ "Partition", "SizeMinBytes", config_parse_size4096, -1, &p->size_min },
|
||||
{ "Partition", "SizeMaxBytes", config_parse_size4096, 1, &p->size_max },
|
||||
{ "Partition", "PaddingMinBytes", config_parse_size4096, -1, &p->padding_min },
|
||||
{ "Partition", "PaddingMaxBytes", config_parse_size4096, 1, &p->padding_max },
|
||||
{ "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset },
|
||||
{ "Partition", "CopyBlocks", config_parse_copy_blocks, 0, p },
|
||||
{ "Partition", "Format", config_parse_fstype, 0, &p->format },
|
||||
{ "Partition", "CopyFiles", config_parse_copy_files, 0, &p->copy_files },
|
||||
{ "Partition", "ExcludeFiles", config_parse_exclude_files, 0, &p->exclude_files_source },
|
||||
{ "Partition", "ExcludeFilesTarget", config_parse_exclude_files, 0, &p->exclude_files_target },
|
||||
{ "Partition", "MakeDirectories", config_parse_make_dirs, 0, &p->make_directories },
|
||||
{ "Partition", "Encrypt", config_parse_encrypt, 0, &p->encrypt },
|
||||
{ "Partition", "Verity", config_parse_verity, 0, &p->verity },
|
||||
{ "Partition", "VerityMatchKey", config_parse_string, 0, &p->verity_match_key },
|
||||
{ "Partition", "Flags", config_parse_gpt_flags, 0, &p->gpt_flags },
|
||||
{ "Partition", "ReadOnly", config_parse_tristate, 0, &p->read_only },
|
||||
{ "Partition", "NoAuto", config_parse_tristate, 0, &p->no_auto },
|
||||
{ "Partition", "GrowFileSystem", config_parse_tristate, 0, &p->growfs },
|
||||
{ "Partition", "SplitName", config_parse_string, 0, &p->split_name_format },
|
||||
{ "Partition", "Minimize", config_parse_minimize, 0, &p->minimize },
|
||||
{ "Partition", "Subvolumes", config_parse_subvolumes, 0, &p->subvolumes },
|
||||
{ "Partition", "DefaultSubvolume", config_parse_default_subvolume, 0, &p->default_subvolume },
|
||||
{ "Partition", "VerityDataBlockSizeBytes", config_parse_block_size, 0, &p->verity_data_block_size },
|
||||
{ "Partition", "VerityHashBlockSizeBytes", config_parse_block_size, 0, &p->verity_hash_block_size },
|
||||
{ "Partition", "MountPoint", config_parse_mountpoint, 0, p },
|
||||
{ "Partition", "EncryptedVolume", config_parse_encrypted_volume, 0, p },
|
||||
{ "Partition", "Compression", config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, &p->compression },
|
||||
{ "Partition", "CompressionLevel", config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, &p->compression_level },
|
||||
{}
|
||||
};
|
||||
_cleanup_free_ char *filename = NULL;
|
||||
@ -5469,7 +5477,8 @@ static int context_mkfs(Context *context) {
|
||||
|
||||
r = make_filesystem(partition_target_path(t), p->format, strempty(p->new_label), root,
|
||||
p->fs_uuid, arg_discard, /* quiet = */ false,
|
||||
context->fs_sector_size, extra_mkfs_options);
|
||||
context->fs_sector_size, p->compression, p->compression_level,
|
||||
extra_mkfs_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -7033,6 +7042,8 @@ static int context_minimize(Context *context) {
|
||||
fs_uuid,
|
||||
arg_discard, /* quiet = */ false,
|
||||
context->fs_sector_size,
|
||||
p->compression,
|
||||
p->compression_level,
|
||||
extra_mkfs_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -7114,6 +7125,8 @@ static int context_minimize(Context *context) {
|
||||
arg_discard,
|
||||
/* quiet = */ false,
|
||||
context->fs_sector_size,
|
||||
p->compression,
|
||||
p->compression_level,
|
||||
extra_mkfs_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -323,6 +323,8 @@ int make_filesystem(
|
||||
bool discard,
|
||||
bool quiet,
|
||||
uint64_t sector_size,
|
||||
char *compression,
|
||||
char *compression_level,
|
||||
char * const *extra_mkfs_args) {
|
||||
|
||||
_cleanup_free_ char *mkfs = NULL, *mangled_label = NULL;
|
||||
@ -570,12 +572,19 @@ int make_filesystem(
|
||||
root, node,
|
||||
"-noappend");
|
||||
|
||||
if (compression) {
|
||||
if (strv_extend_many(&argv, "-comp", compression) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (compression_level && strv_extend_many(&argv, "-Xcompression-level", compression_level) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
/* mksquashfs -quiet option is pretty new so let's redirect stdout to /dev/null instead. */
|
||||
if (quiet)
|
||||
stdio_fds[1] = -EBADF;
|
||||
|
||||
} else if (streq(fstype, "erofs")) {
|
||||
|
||||
argv = strv_new(mkfs,
|
||||
"-U", vol_id,
|
||||
node, root);
|
||||
@ -583,6 +592,20 @@ int make_filesystem(
|
||||
if (quiet && strv_extend(&argv, "--quiet") < 0)
|
||||
return log_oom();
|
||||
|
||||
if (compression) {
|
||||
_cleanup_free_ char *c = NULL;
|
||||
|
||||
c = strjoin("-z", compression);
|
||||
if (!c)
|
||||
return log_oom();
|
||||
|
||||
if (compression_level && !strextend(&c, ",level=", compression_level))
|
||||
return log_oom();
|
||||
|
||||
if (strv_extend(&argv, c) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
} else
|
||||
/* Generic fallback for all other file systems */
|
||||
argv = strv_new(mkfs, node);
|
||||
|
@ -20,6 +20,8 @@ int make_filesystem(
|
||||
bool discard,
|
||||
bool quiet,
|
||||
uint64_t sector_size,
|
||||
char *compression,
|
||||
char *compression_level,
|
||||
char * const *extra_mkfs_args);
|
||||
|
||||
int mkfs_options_from_env(const char *component, const char *fstype, char ***ret);
|
||||
|
@ -251,16 +251,16 @@ static int run(int argc, char *argv[]) {
|
||||
assert_se(r >= 0);
|
||||
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_ESP].node, "vfat", "EFI", NULL, id, true, false, 0, NULL) >= 0);
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_ESP].node, "vfat", "EFI", NULL, id, true, false, 0, NULL, NULL, NULL) >= 0);
|
||||
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_XBOOTLDR].node, "vfat", "xbootldr", NULL, id, true, false, 0, NULL) >= 0);
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_XBOOTLDR].node, "vfat", "xbootldr", NULL, id, true, false, 0, NULL, NULL, NULL) >= 0);
|
||||
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_ROOT].node, "ext4", "root", NULL, id, true, false, 0, NULL) >= 0);
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_ROOT].node, "ext4", "root", NULL, id, true, false, 0, NULL, NULL, NULL) >= 0);
|
||||
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", NULL, id, true, false, 0, NULL) >= 0);
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", NULL, id, true, false, 0, NULL, NULL, NULL) >= 0);
|
||||
|
||||
dissected = dissected_image_unref(dissected);
|
||||
|
||||
|
@ -3,5 +3,6 @@
|
||||
integration_tests += [
|
||||
integration_test_template + {
|
||||
'name' : fs.name(meson.current_source_dir()),
|
||||
'vm' : true,
|
||||
},
|
||||
]
|
||||
|
@ -1067,11 +1067,6 @@ EOF
|
||||
testcase_minimize() {
|
||||
local defs imgs output
|
||||
|
||||
if systemd-detect-virt --quiet --container; then
|
||||
echo "Skipping minimize test in container."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "*** minimization ***"
|
||||
|
||||
defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
|
||||
@ -1114,6 +1109,11 @@ EOF
|
||||
|
||||
# Check that we can dissect, mount and unmount a minimized image.
|
||||
|
||||
if systemd-detect-virt --quiet --container; then
|
||||
echo "Skipping minimize dissect, mount and unmount test in container."
|
||||
return
|
||||
fi
|
||||
|
||||
systemd-dissect "$imgs/zzz"
|
||||
systemd-dissect "$imgs/zzz" -M "$imgs/mnt"
|
||||
systemd-dissect -U "$imgs/mnt"
|
||||
@ -1312,6 +1312,41 @@ testcase_list_devices() {
|
||||
systemd-repart --list-devices
|
||||
}
|
||||
|
||||
testcase_compression() {
|
||||
local workdir image defs
|
||||
|
||||
workdir="$(mktemp --directory "/tmp/test-repart.compression.XXXXXXXXXX")"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '${workdir:?}'" RETURN
|
||||
|
||||
image="$workdir/image.img"
|
||||
defs="$workdir/defs"
|
||||
mkdir "$defs"
|
||||
|
||||
# TODO: add btrfs once btrfs-progs v6.11 is available in distributions.
|
||||
for format in squashfs erofs; do
|
||||
if ! command -v "mkfs.$format" && ! command -v mksquashfs >/dev/null; then
|
||||
continue
|
||||
fi
|
||||
|
||||
[[ "$format" == "squashfs" ]] && compression=zstd
|
||||
[[ "$format" == "erofs" ]] && compression=lz4hc
|
||||
|
||||
tee "$defs/10-root.conf" <<EOF
|
||||
[Partition]
|
||||
Type=root
|
||||
Format=$format
|
||||
Compression=$compression
|
||||
CompressionLevel=3
|
||||
CopyFiles=$defs:/def
|
||||
SizeMinBytes=48M
|
||||
EOF
|
||||
|
||||
rm -f "$image"
|
||||
systemd-repart --empty=create --size=auto --pretty=yes --dry-run=no --definitions="$defs" "$image"
|
||||
done
|
||||
}
|
||||
|
||||
OFFLINE="yes"
|
||||
run_testcases
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user