repart: Make it possible to set persistent allow-discards activation flag

AllowDiscards= will set allow-discards in the persistent flags which will make
activating the device automatically activate with that option. This is
useful for devices discovered through gpt-auto-generator without
needing to use some kernel command line to set the option.
This commit is contained in:
Valentin David
2026-03-28 23:46:37 +01:00
committed by Daan De Meyer
parent f377be7081
commit 421bdc489f
5 changed files with 97 additions and 1 deletions
+16
View File
@@ -679,6 +679,22 @@
<xi:include href="version-info.xml" xpointer="v247"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>Discard=</varname></term>
<listitem><para>Takes a boolean argument. The default is <literal>no</literal> if
<option>--discard=no</option> is used for the invocation of <command>systemd-repart</command>
or if <varname>Integrity=inline</varname> is set. It is <literal>yes</literal> otherwise.</para>
<para>If set to <literal>yes</literal>, when creating the LUKS2 superblock for the partition, the
<literal>allow-discards</literal> activation flag will be set so that future activations will allow
discards by default.</para>
<para>This option has no effect if the partition already exists or if <varname>Encrypt=off</varname> is used.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>Verity=</varname></term>
+29 -1
View File
@@ -472,6 +472,7 @@ typedef struct Partition {
char *compression;
char *compression_level;
uint64_t fs_sector_size;
int discard;
int add_validatefs;
CopyFiles *copy_files;
@@ -728,6 +729,7 @@ static Partition *partition_new(Context *c) {
.last_percent = UINT_MAX,
.progress_ratelimit = { 100 * USEC_PER_MSEC, 1 },
.fs_sector_size = UINT64_MAX,
.discard = -1,
};
return p;
@@ -851,6 +853,7 @@ static void partition_foreignize(Partition *p) {
p->verity = VERITY_OFF;
p->add_validatefs = false;
p->fs_sector_size = UINT64_MAX;
p->discard = -1;
partition_mountpoint_free_many(p->mountpoints, p->n_mountpoints);
p->mountpoints = NULL;
@@ -2882,6 +2885,7 @@ static int partition_read_definition(
{ "Partition", "SupplementFor", config_parse_string, 0, &p->supplement_for_name },
{ "Partition", "AddValidateFS", config_parse_tristate, 0, &p->add_validatefs },
{ "Partition", "FileSystemSectorSize", config_parse_fs_sector_size, 0, &p->fs_sector_size },
{ "Partition", "Discard", config_parse_tristate, 0, &p->discard },
{}
};
_cleanup_free_ char *filename = NULL;
@@ -3032,6 +3036,14 @@ static int partition_read_definition(
"SupplementFor= cannot be combined with CopyBlocks=/Encrypt=/Verity=");
}
if (p->encrypt == ENCRYPT_OFF && p->discard > 0)
log_syntax(NULL, LOG_WARNING, path, 1, 0,
"Discard=yes has no effect with Encrypt=off.");
if (p->encrypt != ENCRYPT_OFF && p->integrity == INTEGRITY_INLINE && p->discard > 0)
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
"Integrity=inline is incompatible with Discard=yes.");
/* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */
if ((partition_designator_is_verity_hash(p->type.designator) ||
partition_designator_is_verity_sig(p->type.designator) ||
@@ -5225,6 +5237,22 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
if (r < 0)
return log_error_errno(r, "Failed to LUKS2 format future partition: %m");
bool allow_discards = p->integrity != INTEGRITY_INLINE && (arg_discard ? p->discard != 0 : p->discard > 0);
if (allow_discards) {
uint32_t flags;
r = sym_crypt_persistent_flags_get(cd, CRYPT_FLAGS_ACTIVATION, &flags);
if (r < 0)
return log_error_errno(r, "Failed to get persistent activation flags for %s: %m", node);
if (!FLAGS_SET(flags, CRYPT_ACTIVATE_ALLOW_DISCARDS)) {
flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
r = sym_crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, flags);
if (r < 0)
return log_error_errno(r, "Failed to set persistent activation flags for %s: %m", node);
}
}
if (p->encrypted_volume && p->encrypted_volume->fixate_volume_key) {
_cleanup_free_ char *key_id = NULL, *hash_option = NULL;
@@ -5543,7 +5571,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
dm_name,
NULL,
/* volume_key_size= */ volume_key_size,
(arg_discard && p->integrity != INTEGRITY_INLINE ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0) | CRYPT_ACTIVATE_PRIVATE);
(allow_discards ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0) | CRYPT_ACTIVATE_PRIVATE);
if (r < 0)
return log_error_errno(r, "Failed to activate LUKS superblock: %m");
+4
View File
@@ -42,6 +42,8 @@ DLSYM_PROTOTYPE(crypt_keyslot_destroy) = NULL;
DLSYM_PROTOTYPE(crypt_keyslot_max) = NULL;
DLSYM_PROTOTYPE(crypt_load) = NULL;
DLSYM_PROTOTYPE(crypt_metadata_locking) = NULL;
DLSYM_PROTOTYPE(crypt_persistent_flags_get) = NULL;
DLSYM_PROTOTYPE(crypt_persistent_flags_set) = NULL;
DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase) = NULL;
DLSYM_PROTOTYPE(crypt_reencrypt_run);
DLSYM_PROTOTYPE(crypt_resize) = NULL;
@@ -302,6 +304,8 @@ int dlopen_cryptsetup(void) {
DLSYM_ARG(crypt_keyslot_max),
DLSYM_ARG(crypt_load),
DLSYM_ARG(crypt_metadata_locking),
DLSYM_ARG(crypt_persistent_flags_get),
DLSYM_ARG(crypt_persistent_flags_set),
DLSYM_ARG(crypt_reencrypt_init_by_passphrase),
DLSYM_ARG(crypt_reencrypt_run),
DLSYM_ARG(crypt_resize),
+2
View File
@@ -30,6 +30,8 @@ extern DLSYM_PROTOTYPE(crypt_keyslot_destroy);
extern DLSYM_PROTOTYPE(crypt_keyslot_max);
extern DLSYM_PROTOTYPE(crypt_load);
extern DLSYM_PROTOTYPE(crypt_metadata_locking);
extern DLSYM_PROTOTYPE(crypt_persistent_flags_get);
extern DLSYM_PROTOTYPE(crypt_persistent_flags_set);
extern DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase);
extern DLSYM_PROTOTYPE(crypt_reencrypt_run);
extern DLSYM_PROTOTYPE(crypt_resize);
+46
View File
@@ -380,6 +380,8 @@ $imgs/zzz7 : start= 6291416, size= 131072, type=3B8F8425-20E0-4F3B-907F
loop="$(losetup -P --show --find "$imgs/zzz")"
udevadm wait --timeout=60 --settle "${loop:?}p7"
cryptsetup luksDump "${loop}p7" | grep 'Flags:[[:space:]]*allow-discards' >/dev/null
volume="test-repart-$RANDOM"
touch "$imgs/empty-password"
@@ -396,6 +398,50 @@ $imgs/zzz7 : start= 6291416, size= 131072, type=3B8F8425-20E0-4F3B-907F
PASSWORD="" systemd-dissect "$imgs/zzz" -M "$imgs/mount"
udevadm info /dev/disk/by-label/schrupfel | grep ID_FS_TYPE=crypto_LUKS >/dev/null
systemd-dissect -U "$imgs/mount"
echo "*** 7. Testing Discard=no ***"
tee "$defs/extra4.conf" <<EOF
[Partition]
Type=var
Label=luks-no-discards
UUID=329b9db2-dfd9-4f39-8ebf-53b582b05fcd
Format=ext4
Encrypt=yes
CopyFiles=$defs:/def
SizeMinBytes=48M
Discard=no
EOF
systemd-repart --offline="$OFFLINE" \
--definitions="$defs" \
--size=auto \
--dry-run=no \
--seed="$seed" \
"$imgs/zzz"
output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
assert_eq "$output" "label: gpt
label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
device: $imgs/zzz
unit: sectors
first-lba: 2048
last-lba: 6553566
$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
$imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\"
$imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name=\"block-copy\"
$imgs/zzz7 : start= 6291416, size= 131072, type=3B8F8425-20E0-4F3B-907F-1A25A76F98E8, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name=\"luks-format-copy\", attrs=\"GUID:59\"
$imgs/zzz8 : start= 6422488, size= 131072, type=4D21B016-B534-45C2-A9FB-5C16E091FD2D, uuid=329B9DB2-DFD9-4F39-8EBF-53B582B05FCD, name=\"luks-no-discards\", attrs=\"GUID:59\""
loop="$(losetup -P --show --find "$imgs/zzz")"
udevadm wait --timeout=60 --settle "${loop:?}p8"
cryptsetup luksDump "${loop}p8" | grep 'Flags:[[:space:]]*(no flags)' >/dev/null
losetup -d "$loop"
}
testcase_dropin() {