diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-05-07 15:04:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-07 15:04:55 +0200 |
commit | ac2c088939de5aba5a06bee00dbc6c89a2809534 (patch) | |
tree | 7a67286af61e2de6fe4d2cf50813bad304941f81 /src | |
parent | 2a9cfe6b07c41a88b57813afc4f73f4332ac74d2 (diff) | |
parent | cd4d2b17771ce0a2cc9487d9f26cc2e210d0fa5a (diff) | |
download | systemd-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.c | 3 | ||||
-rw-r--r-- | src/dissect/dissect.c | 20 | ||||
-rw-r--r-- | src/firstboot/firstboot.c | 3 | ||||
-rw-r--r-- | src/gpt-auto-generator/gpt-auto-generator.c | 27 | ||||
-rw-r--r-- | src/journal/journalctl.c | 2 | ||||
-rw-r--r-- | src/machine-id-setup/machine-id-setup-main.c | 3 | ||||
-rw-r--r-- | src/nspawn/nspawn.c | 4 | ||||
-rw-r--r-- | src/partition/repart.c | 56 | ||||
-rwxr-xr-x | src/partition/test-repart.sh | 30 | ||||
-rw-r--r-- | src/shared/dissect-image.c | 83 | ||||
-rw-r--r-- | src/shared/dissect-image.h | 2 | ||||
-rw-r--r-- | src/shared/generator.c | 8 | ||||
-rw-r--r-- | src/shared/gpt.c | 11 | ||||
-rw-r--r-- | src/shared/gpt.h | 4 | ||||
-rw-r--r-- | src/sysusers/sysusers.c | 3 | ||||
-rw-r--r-- | src/tmpfiles/tmpfiles.c | 3 |
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); |