summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-05-07 15:04:55 +0200
committerGitHub <noreply@github.com>2021-05-07 15:04:55 +0200
commitac2c088939de5aba5a06bee00dbc6c89a2809534 (patch)
tree7a67286af61e2de6fe4d2cf50813bad304941f81 /src
parent2a9cfe6b07c41a88b57813afc4f73f4332ac74d2 (diff)
parentcd4d2b17771ce0a2cc9487d9f26cc2e210d0fa5a (diff)
downloadsystemd-ac2c088939de5aba5a06bee00dbc6c89a2809534.tar.gz
Merge pull request #19391 from poettering/dissect-grow
optionally, grow file systems to partition size when mounting them via GPT auto-discovery
Diffstat (limited to 'src')
-rw-r--r--src/core/namespace.c3
-rw-r--r--src/dissect/dissect.c20
-rw-r--r--src/firstboot/firstboot.c3
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c27
-rw-r--r--src/journal/journalctl.c2
-rw-r--r--src/machine-id-setup/machine-id-setup-main.c3
-rw-r--r--src/nspawn/nspawn.c4
-rw-r--r--src/partition/repart.c56
-rwxr-xr-xsrc/partition/test-repart.sh30
-rw-r--r--src/shared/dissect-image.c83
-rw-r--r--src/shared/dissect-image.h2
-rw-r--r--src/shared/generator.c8
-rw-r--r--src/shared/gpt.c11
-rw-r--r--src/shared/gpt.h4
-rw-r--r--src/sysusers/sysusers.c3
-rw-r--r--src/tmpfiles/tmpfiles.c3
16 files changed, 203 insertions, 59 deletions
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 77fb0d4394..acf8d14b67 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1818,7 +1818,8 @@ int setup_namespace(
DISSECT_IMAGE_DISCARD_ON_LOOP |
DISSECT_IMAGE_RELAX_VAR_CHECK |
DISSECT_IMAGE_FSCK |
- DISSECT_IMAGE_USR_NO_ROOT;
+ DISSECT_IMAGE_USR_NO_ROOT |
+ DISSECT_IMAGE_GROWFS;
size_t n_mounts;
int r;
diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c
index 745366837f..ef11faaf42 100644
--- a/src/dissect/dissect.c
+++ b/src/dissect/dissect.c
@@ -49,7 +49,8 @@ static DissectImageFlags arg_flags =
DISSECT_IMAGE_DISCARD_ON_LOOP |
DISSECT_IMAGE_RELAX_VAR_CHECK |
DISSECT_IMAGE_FSCK |
- DISSECT_IMAGE_USR_NO_ROOT;
+ DISSECT_IMAGE_USR_NO_ROOT |
+ DISSECT_IMAGE_GROWFS;
static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0;
@@ -75,6 +76,7 @@ static int help(void) {
" --no-legend Do not show the headers and footers\n"
" -r --read-only Mount read-only\n"
" --fsck=BOOL Run fsck before mounting\n"
+ " --growfs=BOOL Grow file system to partition size, if marked\n"
" --mkdir Make mount directory before mounting, if missing\n"
" --discard=MODE Choose 'discard' mode (disabled, loop, all, crypto)\n"
" --root-hash=HASH Specify root hash for verity\n"
@@ -112,6 +114,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_LEGEND,
ARG_DISCARD,
ARG_FSCK,
+ ARG_GROWFS,
ARG_ROOT_HASH,
ARG_ROOT_HASH_SIG,
ARG_VERITY_DATA,
@@ -128,6 +131,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "read-only", no_argument, NULL, 'r' },
{ "discard", required_argument, NULL, ARG_DISCARD },
{ "fsck", required_argument, NULL, ARG_FSCK },
+ { "growfs", required_argument, NULL, ARG_GROWFS },
{ "root-hash", required_argument, NULL, ARG_ROOT_HASH },
{ "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG },
{ "verity-data", required_argument, NULL, ARG_VERITY_DATA },
@@ -264,6 +268,14 @@ static int parse_argv(int argc, char *argv[]) {
SET_FLAG(arg_flags, DISSECT_IMAGE_FSCK, r);
break;
+ case ARG_GROWFS:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --growfs= parameter: %s", optarg);
+
+ SET_FLAG(arg_flags, DISSECT_IMAGE_GROWFS, r);
+ break;
+
case ARG_JSON:
r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
@@ -467,7 +479,7 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
return log_oom();
}
- t = table_new("rw", "designator", "partition uuid", "partition label", "fstype", "architecture", "verity", "node", "partno");
+ t = table_new("rw", "designator", "partition uuid", "partition label", "fstype", "architecture", "verity", "growfs", "node", "partno");
if (!t)
return log_oom();
@@ -511,6 +523,10 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
if (r < 0)
return table_log_add_error(r);
+ r = table_add_many(t, TABLE_BOOLEAN, (int) p->growfs);
+ if (r < 0)
+ return table_log_add_error(r);
+
if (p->partno < 0) /* no partition table, naked file system */ {
r = table_add_cell(t, NULL, TABLE_STRING, arg_image);
if (r < 0)
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 896c2e7b0a..2cb4f80d5d 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -1357,7 +1357,8 @@ static int run(int argc, char *argv[]) {
DISSECT_IMAGE_REQUIRE_ROOT |
DISSECT_IMAGE_VALIDATE_OS |
DISSECT_IMAGE_RELAX_VAR_CHECK |
- DISSECT_IMAGE_FSCK,
+ DISSECT_IMAGE_FSCK |
+ DISSECT_IMAGE_GROWFS,
&unlink_dir,
&loop_device,
&decrypted_image);
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index d3af814136..705e138b8d 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -194,6 +194,7 @@ static int add_mount(
const char *where,
const char *fstype,
bool rw,
+ bool growfs,
const char *options,
const char *description,
const char *post) {
@@ -271,8 +272,18 @@ static int add_mount(
if (r < 0)
return log_error_errno(r, "Failed to write unit file %s: %m", p);
- if (post)
- return generator_add_symlink(arg_dest, post, "requires", unit);
+ if (growfs) {
+ r = generator_hook_up_growfs(arg_dest, where, post);
+ if (r < 0)
+ return r;
+ }
+
+ if (post) {
+ r = generator_add_symlink(arg_dest, post, "requires", unit);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
@@ -321,6 +332,7 @@ static int add_partition_mount(
where,
p->fstype,
p->rw,
+ p->growfs,
NULL,
description,
SPECIAL_LOCAL_FS_TARGET);
@@ -385,6 +397,7 @@ static int add_automount(
const char *where,
const char *fstype,
bool rw,
+ bool growfs,
const char *options,
const char *description,
usec_t timeout) {
@@ -406,6 +419,7 @@ static int add_automount(
where,
fstype,
rw,
+ growfs,
opt,
description,
NULL);
@@ -481,7 +495,8 @@ static int add_xbootldr(DissectedPartition *p) {
p->node,
"/boot",
p->fstype,
- true,
+ /* rw= */ true,
+ /* growfs= */ false,
esp_or_xbootldr_options(p),
"Boot Loader Partition",
120 * USEC_PER_SEC);
@@ -555,7 +570,8 @@ static int add_esp(DissectedPartition *p, bool has_xbootldr) {
p->node,
esp_path,
p->fstype,
- true,
+ /* rw= */ true,
+ /* growfs= */ false,
esp_or_xbootldr_options(p),
"EFI System Partition Automount",
120 * USEC_PER_SEC);
@@ -651,7 +667,8 @@ static int add_root_mount(void) {
"/dev/gpt-auto-root",
in_initrd() ? "/sysroot" : "/",
NULL,
- arg_root_rw > 0,
+ /* rw= */ arg_root_rw > 0,
+ /* growfs= */ false,
NULL,
"Root Partition",
in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index b4a8bd1bfb..c8fb726d42 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -2154,7 +2154,7 @@ int main(int argc, char *argv[]) {
DISSECT_IMAGE_REQUIRE_ROOT |
DISSECT_IMAGE_VALIDATE_OS |
DISSECT_IMAGE_RELAX_VAR_CHECK |
- (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK : DISSECT_IMAGE_READ_ONLY),
+ (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS : DISSECT_IMAGE_READ_ONLY),
&unlink_dir,
&loop_device,
&decrypted_image);
diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c
index 9539c39c4e..5af6bfeafe 100644
--- a/src/machine-id-setup/machine-id-setup-main.c
+++ b/src/machine-id-setup/machine-id-setup-main.c
@@ -146,7 +146,8 @@ static int run(int argc, char *argv[]) {
DISSECT_IMAGE_REQUIRE_ROOT |
DISSECT_IMAGE_VALIDATE_OS |
DISSECT_IMAGE_RELAX_VAR_CHECK |
- DISSECT_IMAGE_FSCK,
+ DISSECT_IMAGE_FSCK |
+ DISSECT_IMAGE_GROWFS,
&unlink_dir,
&loop_device,
&decrypted_image);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 41ae043c6e..53b9fa84a7 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -3577,7 +3577,7 @@ static int outer_child(
DISSECT_IMAGE_MOUNT_ROOT_ONLY|
DISSECT_IMAGE_DISCARD_ON_LOOP|
DISSECT_IMAGE_USR_NO_ROOT|
- (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK)|
+ (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS)|
(arg_start_mode == START_BOOT ? DISSECT_IMAGE_VALIDATE_OS : 0));
if (r < 0)
return r;
@@ -3670,7 +3670,7 @@ static int outer_child(
DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY|
DISSECT_IMAGE_DISCARD_ON_LOOP|
DISSECT_IMAGE_USR_NO_ROOT|
- (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK));
+ (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS));
if (r == -EUCLEAN)
return log_error_errno(r, "File system check for image failed: %m");
if (r < 0)
diff --git a/src/partition/repart.c b/src/partition/repart.c
index 3b31109952..51b8f20dbc 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -170,6 +170,7 @@ struct Partition {
uint64_t gpt_flags;
int read_only;
+ int growfs;
LIST_FIELDS(Partition, partitions);
};
@@ -243,6 +244,7 @@ static Partition *partition_new(void) {
.copy_blocks_fd = -1,
.copy_blocks_size = UINT64_MAX,
.read_only = -1,
+ .growfs = -1,
};
return p;
@@ -1316,6 +1318,7 @@ static int partition_read_definition(Partition *p, const char *path) {
{ "Partition", "Encrypt", config_parse_encrypt, 0, &p->encrypt },
{ "Partition", "Flags", config_parse_gpt_flags, 0, &p->gpt_flags },
{ "Partition", "ReadOnly", config_parse_tristate, 0, &p->read_only },
+ { "Partition", "GrowFileSystem", config_parse_tristate, 0, &p->growfs },
{}
};
int r;
@@ -1363,6 +1366,11 @@ static int partition_read_definition(Partition *p, const char *path) {
p->read_only < 0)
p->read_only = true;
+ /* Default to "growfs" on, unless read-only */
+ if (gpt_partition_type_knows_growfs(p->type_uuid) &&
+ p->read_only <= 0)
+ p->growfs = true;
+
return 0;
}
@@ -3255,6 +3263,38 @@ static int set_gpt_flags(struct fdisk_partition *q, uint64_t flags) {
return fdisk_partition_set_attrs(q, a);
}
+static uint64_t partition_merge_flags(Partition *p) {
+ uint64_t f;
+
+ assert(p);
+
+ f = p->gpt_flags;
+
+ if (p->read_only >= 0) {
+ if (gpt_partition_type_knows_read_only(p->type_uuid))
+ SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
+ else {
+ char buffer[ID128_UUID_STRING_MAX];
+ log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
+ yes_no(p->read_only),
+ gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
+ }
+ }
+
+ if (p->growfs >= 0) {
+ if (gpt_partition_type_knows_growfs(p->type_uuid))
+ SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
+ else {
+ char buffer[ID128_UUID_STRING_MAX];
+ log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
+ yes_no(p->growfs),
+ gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
+ }
+ }
+
+ return f;
+}
+
static int context_mangle_partitions(Context *context) {
Partition *p;
int r;
@@ -3323,7 +3363,6 @@ static int context_mangle_partitions(Context *context) {
_cleanup_(fdisk_unref_partitionp) struct fdisk_partition *q = NULL;
_cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *t = NULL;
char ids[ID128_UUID_STRING_MAX];
- uint64_t f;
assert(!p->new_partition);
assert(p->offset % 512 == 0);
@@ -3371,19 +3410,8 @@ static int context_mangle_partitions(Context *context) {
if (r < 0)
return log_error_errno(r, "Failed to set partition label: %m");
- /* Merge the read only setting with the literal flags */
- f = p->gpt_flags;
- if (p->read_only >= 0) {
- if (gpt_partition_type_knows_read_only(p->type_uuid))
- SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
- else {
- char buffer[ID128_UUID_STRING_MAX];
- log_warning("Configured ReadOnly=yes for partition type '%s' that doesn't support it, ignoring.",
- gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
- }
- }
-
- r = set_gpt_flags(q, f);
+ /* Merge the read only + growfs setting with the literal flags, and set them for the partition */
+ r = set_gpt_flags(q, partition_merge_flags(p));
if (r < 0)
return log_error_errno(r, "Failed to set GPT partition flags: %m");
diff --git a/src/partition/test-repart.sh b/src/partition/test-repart.sh
index 8598a99887..525be8e56a 100755
--- a/src/partition/test-repart.sh
+++ b/src/partition/test-repart.sh
@@ -65,9 +65,9 @@ device: $D/zzz
unit: sectors
first-lba: 2048
last-lba: 2097118
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
EOF
@@ -100,9 +100,9 @@ device: $D/zzz
unit: sectors
first-lba: 2048
last-lba: 2097118
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
$D/zzz5 : start= 1908696, size= 188416, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
EOF
@@ -120,9 +120,9 @@ device: $D/zzz
unit: sectors
first-lba: 2048
last-lba: 4194270
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
EOF
@@ -150,9 +150,9 @@ device: $D/zzz
unit: sectors
first-lba: 2048
last-lba: 6291422
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
$D/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name="block-copy"
@@ -187,9 +187,9 @@ device: $D/zzz
unit: sectors
first-lba: 2048
last-lba: 6389726
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
$D/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name="block-copy"
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index fe3186db99..1f7ea3ec5b 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -46,6 +46,7 @@
#include "path-util.h"
#include "process-util.h"
#include "raw-clone.h"
+#include "resize-fs.h"
#include "signal-util.h"
#include "stat-util.h"
#include "stdio-util.h"
@@ -534,7 +535,8 @@ int dissect_image(
sd_id128_t usr_uuid = SD_ID128_NULL, usr_verity_uuid = SD_ID128_NULL;
#endif
bool is_gpt, is_mbr, multiple_generic = false,
- generic_rw = false; /* initialize to appease gcc */
+ generic_rw = false, /* initialize to appease gcc */
+ generic_growfs = false;
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
_cleanup_(blkid_free_probep) blkid_probe b = NULL;
@@ -795,7 +797,7 @@ int dissect_image(
int architecture = _ARCHITECTURE_INVALID;
const char *stype, *sid, *fstype = NULL, *label;
sd_id128_t type_id, id;
- bool rw = true;
+ bool rw = true, growfs = false;
sid = blkid_partition_get_uuid(pp);
if (!sid)
@@ -813,23 +815,25 @@ int dissect_image(
if (sd_id128_equal(type_id, GPT_HOME)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_HOME;
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, GPT_SRV)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_SRV;
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, GPT_ESP)) {
@@ -846,18 +850,19 @@ int dissect_image(
} else if (sd_id128_equal(type_id, GPT_XBOOTLDR)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_XBOOTLDR;
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
}
#ifdef GPT_ROOT_NATIVE
else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
@@ -869,6 +874,7 @@ int dissect_image(
designator = PARTITION_ROOT;
architecture = native_architecture();
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) {
@@ -892,7 +898,7 @@ int dissect_image(
#ifdef GPT_ROOT_SECONDARY
else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
@@ -904,6 +910,7 @@ int dissect_image(
designator = PARTITION_ROOT_SECONDARY;
architecture = SECONDARY_ARCHITECTURE;
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) {
@@ -927,7 +934,7 @@ int dissect_image(
#ifdef GPT_USR_NATIVE
else if (sd_id128_equal(type_id, GPT_USR_NATIVE)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
@@ -939,6 +946,7 @@ int dissect_image(
designator = PARTITION_USR;
architecture = native_architecture();
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, GPT_USR_NATIVE_VERITY)) {
@@ -962,7 +970,7 @@ int dissect_image(
#ifdef GPT_USR_SECONDARY
else if (sd_id128_equal(type_id, GPT_USR_SECONDARY)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
@@ -974,6 +982,7 @@ int dissect_image(
designator = PARTITION_USR_SECONDARY;
architecture = SECONDARY_ARCHITECTURE;
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, GPT_USR_SECONDARY_VERITY)) {
@@ -1006,7 +1015,7 @@ int dissect_image(
} else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
@@ -1016,6 +1025,7 @@ int dissect_image(
else {
generic_nr = nr;
generic_rw = !(pflags & GPT_FLAG_READ_ONLY);
+ generic_growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
generic_uuid = id;
generic_node = strdup(node);
if (!generic_node)
@@ -1024,17 +1034,18 @@ int dissect_image(
} else if (sd_id128_equal(type_id, GPT_TMP)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_TMP;
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, GPT_VAR)) {
- check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+ check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
if (pflags & GPT_FLAG_NO_AUTO)
continue;
@@ -1062,6 +1073,7 @@ int dissect_image(
designator = PARTITION_VAR;
rw = !(pflags & GPT_FLAG_READ_ONLY);
+ growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
}
if (designator != _PARTITION_DESIGNATOR_INVALID) {
@@ -1108,6 +1120,7 @@ int dissect_image(
.found = true,
.partno = nr,
.rw = rw,
+ .growfs = growfs,
.architecture = architecture,
.node = TAKE_PTR(n),
.fstype = TAKE_PTR(t),
@@ -1131,6 +1144,7 @@ int dissect_image(
else {
generic_nr = nr;
generic_rw = true;
+ generic_growfs = false;
generic_node = strdup(node);
if (!generic_node)
return -ENOMEM;
@@ -1166,6 +1180,7 @@ int dissect_image(
.found = true,
.partno = nr,
.rw = true,
+ .growfs = false,
.architecture = _ARCHITECTURE_INVALID,
.node = TAKE_PTR(n),
.uuid = id,
@@ -1254,6 +1269,7 @@ int dissect_image(
m->partitions[PARTITION_ROOT] = (DissectedPartition) {
.found = true,
.rw = generic_rw,
+ .growfs = generic_growfs,
.partno = generic_nr,
.architecture = _ARCHITECTURE_INVALID,
.node = TAKE_PTR(generic_node),
@@ -1316,6 +1332,9 @@ int dissect_image(
if (p->fstype && fstype_is_ro(p->fstype))
p->rw = false;
+
+ if (!p->rw)
+ p->growfs = false;
}
*ret = TAKE_PTR(m);
@@ -1411,6 +1430,43 @@ static int run_fsck(const char *node, const char *fstype) {
return 0;
}
+static int fs_grow(const char *node_path, const char *mount_path) {
+ _cleanup_close_ int mount_fd = -1, node_fd = -1;
+ char fb[FORMAT_BYTES_MAX];
+ uint64_t size, newsize;
+ int r;
+
+ node_fd = open(node_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+ if (node_fd < 0)
+ return log_debug_errno(errno, "Failed to open node device %s: %m", node_path);
+
+ if (ioctl(node_fd, BLKGETSIZE64, &size) != 0)
+ return log_debug_errno(errno, "Failed to get block device size of %s: %m", node_path);
+
+ mount_fd = open(mount_path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
+ if (mount_fd < 0)
+ return log_debug_errno(errno, "Failed to open mountd file system %s: %m", mount_path);
+
+ log_debug("Resizing \"%s\" to %"PRIu64" bytes...", mount_path, size);
+ r = resize_fs(mount_fd, size, &newsize);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to resize \"%s\" to %"PRIu64" bytes: %m", mount_path, size);
+
+ if (newsize == size)
+ log_debug("Successfully resized \"%s\" to %s bytes.",
+ mount_path,
+ format_bytes(fb, sizeof fb, newsize));
+ else {
+ assert(newsize < size);
+ log_debug("Successfully resized \"%s\" to %s bytes (%"PRIu64" bytes lost due to blocksize).",
+ mount_path,
+ format_bytes(fb, sizeof fb, newsize),
+ size - newsize);
+ }
+
+ return 0;
+}
+
static int mount_partition(
DissectedPartition *m,
const char *where,
@@ -1519,6 +1575,9 @@ static int mount_partition(
if (r < 0)
return r;
+ if (rw && m->growfs && FLAGS_SET(flags, DISSECT_IMAGE_GROWFS))
+ (void) fs_grow(node, p);
+
return 1;
}
diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h
index 88106ee4f3..b2f5c5dc96 100644
--- a/src/shared/dissect-image.h
+++ b/src/shared/dissect-image.h
@@ -18,6 +18,7 @@ typedef struct VeritySettings VeritySettings;
struct DissectedPartition {
bool found:1;
bool rw:1;
+ bool growfs:1;
int partno; /* -1 if there was no partition and the images contains a file system directly */
int architecture; /* Intended architecture: either native, secondary or unset (-1). */
sd_id128_t uuid; /* Partition entry UUID as reported by the GPT */
@@ -110,6 +111,7 @@ typedef enum DissectImageFlags {
DISSECT_IMAGE_MOUNT_READ_ONLY = 1 << 17, /* Make mounts read-only */
DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY |
DISSECT_IMAGE_MOUNT_READ_ONLY,
+ DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
} DissectImageFlags;
struct DissectedImage {
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 0bb3efa700..4be1dd4ff4 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -503,6 +503,9 @@ int generator_hook_up_growfs(
const char *unit_file;
int r;
+ assert(dir);
+ assert(where);
+
escaped = cescape(where);
if (!escaped)
return log_oom();
@@ -534,9 +537,10 @@ int generator_hook_up_growfs(
"BindsTo=%%i.mount\n"
"Conflicts=shutdown.target\n"
"After=%%i.mount\n"
- "Before=shutdown.target %s\n",
+ "Before=shutdown.target%s%s\n",
program_invocation_short_name,
- target);
+ target ? " " : "",
+ strempty(target));
if (empty_or_root(where)) /* Make sure the root fs is actually writable before we resize it */
fprintf(f,
diff --git a/src/shared/gpt.c b/src/shared/gpt.c
index 69da6c7280..558b69c487 100644
--- a/src/shared/gpt.c
+++ b/src/shared/gpt.c
@@ -163,3 +163,14 @@ bool gpt_partition_type_knows_read_only(sd_id128_t id) {
gpt_partition_type_is_root_verity(id) || /* pretty much implied, but let's set the bit to make things really clear */
gpt_partition_type_is_usr_verity(id); /* ditto */
}
+
+bool gpt_partition_type_knows_growfs(sd_id128_t id) {
+ return gpt_partition_type_is_root(id) ||
+ gpt_partition_type_is_usr(id) ||
+ sd_id128_in_set(id,
+ GPT_HOME,
+ GPT_SRV,
+ GPT_VAR,
+ GPT_TMP,
+ GPT_XBOOTLDR);
+}
diff --git a/src/shared/gpt.h b/src/shared/gpt.h
index f3a74813f0..6581973793 100644
--- a/src/shared/gpt.h
+++ b/src/shared/gpt.h
@@ -112,7 +112,8 @@
* auto-discovery. These happen to be identical to what Microsoft defines for its own Basic Data Partitions,
* but that's just because we saw no point in defining any other values here. */
#define GPT_FLAG_READ_ONLY (1ULL << 60)
-#define GPT_FLAG_NO_AUTO (1ULL << 63)
+#define GPT_FLAG_NO_AUTO (1ULL << 63)
+#define GPT_FLAG_GROWFS (1ULL << 59)
const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
const char *gpt_partition_type_uuid_to_string_harder(
@@ -135,3 +136,4 @@ bool gpt_partition_type_is_usr(sd_id128_t id);
bool gpt_partition_type_is_usr_verity(sd_id128_t id);
bool gpt_partition_type_knows_read_only(sd_id128_t id);
+bool gpt_partition_type_knows_growfs(sd_id128_t id);
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 465b2dd9f5..35ae3ae4af 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -1997,7 +1997,8 @@ static int run(int argc, char *argv[]) {
DISSECT_IMAGE_REQUIRE_ROOT |
DISSECT_IMAGE_VALIDATE_OS |
DISSECT_IMAGE_RELAX_VAR_CHECK |
- DISSECT_IMAGE_FSCK,
+ DISSECT_IMAGE_FSCK |
+ DISSECT_IMAGE_GROWFS,
&unlink_dir,
&loop_device,
&decrypted_image);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index b6de1e74b2..98f14bbbe7 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -3446,7 +3446,8 @@ static int run(int argc, char *argv[]) {
DISSECT_IMAGE_REQUIRE_ROOT |
DISSECT_IMAGE_VALIDATE_OS |
DISSECT_IMAGE_RELAX_VAR_CHECK |
- DISSECT_IMAGE_FSCK,
+ DISSECT_IMAGE_FSCK |
+ DISSECT_IMAGE_GROWFS,
&unlink_dir,
&loop_device,
&decrypted_image);