From 4ab30569c2dc21e6c528edfb86eb26069b66632a Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 26 Jan 2021 21:31:33 +0200 Subject: [PATCH 01/18] Add default configuration --- src/modules/mount/mount.conf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/modules/mount/mount.conf b/src/modules/mount/mount.conf index 3a117d32c..19732b4d3 100644 --- a/src/modules/mount/mount.conf +++ b/src/modules/mount/mount.conf @@ -19,6 +19,10 @@ # The device is not mounted if the mountPoint is unset or if the fs is # set to unformatted. # +--- +# Btrfs subvolumes to create if root filesystem is on btrfs volume. +# If mountpoint is mounted already to another partition, it is ignored. +# Separate subvolume for swapfile is handled separately and automatically. extraMounts: - device: proc fs: proc @@ -40,3 +44,13 @@ extraMountsEfi: - device: efivarfs fs: efivarfs mountPoint: /sys/firmware/efi/efivars + +btrfsSubvolumes: + - mountPoint: / + subvolume: @ + - mountPoint: /home + subvolume: @home + - mountPoint: /var/cache + subvolume: @cache + - mountPoint: /var/log + subvolume: @log \ No newline at end of file From b5cfa5109ecc81d0b7671d7b65494cf9f6dafdfc Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 26 Jan 2021 21:34:11 +0200 Subject: [PATCH 02/18] Add schema definition --- src/modules/mount/mount.schema.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/modules/mount/mount.schema.yaml b/src/modules/mount/mount.schema.yaml index 2d5e4d4a0..fb5dfb69c 100644 --- a/src/modules/mount/mount.schema.yaml +++ b/src/modules/mount/mount.schema.yaml @@ -29,3 +29,12 @@ properties: mountPoint: { type: string } options: { type: string } required: [ device, mountPoint ] + btrfsSubvolumes: + type: array + items: + type: object + additionalProperties: false + properties: + mountPoint: { type: string } + subvolume: { type: string } + required: [ subvolume, mountPoint ] From 945effb048102d2b6dc6ea763b554e889a9e85ab Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 26 Jan 2021 22:13:29 +0200 Subject: [PATCH 03/18] Amend subvolumes to include path --- src/modules/mount/mount.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/mount/mount.conf b/src/modules/mount/mount.conf index 19732b4d3..b96d4576a 100644 --- a/src/modules/mount/mount.conf +++ b/src/modules/mount/mount.conf @@ -47,10 +47,10 @@ extraMountsEfi: btrfsSubvolumes: - mountPoint: / - subvolume: @ + subvolume: /@ - mountPoint: /home - subvolume: @home + subvolume: /@home - mountPoint: /var/cache - subvolume: @cache + subvolume: /@cache - mountPoint: /var/log - subvolume: @log \ No newline at end of file + subvolume: /@log \ No newline at end of file From 942221c764a8622c9b23d29b1db291404af0f63b Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 26 Jan 2021 22:24:50 +0200 Subject: [PATCH 04/18] Generalize subvolume handling --- src/modules/mount/main.py | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 3982176df..4b0e911e3 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -81,26 +81,29 @@ def mount_partition(root_mount_point, partition, partitions): # If a swapfile is used, we also create a subvolume "@swap". # Finally we remount all of the above on the correct paths. if fstype == "btrfs" and partition["mountPoint"] == '/': - has_home_mount_point = False + # Root has been mounted to btrfs volume -> create subvolumes from configuration + btrfs_subvolumes = libcalamares.job.configuration.get("btrfsSubvolumes") or [] + subvolume_mountpoints = [d['mountPoint'] for d in btrfs_subvolumes] + # Check if listed mountpoints besides / are already present and don't create subvolume for those for p in partitions: if "mountPoint" not in p or not p["mountPoint"]: continue - if p["mountPoint"] == "/home": - has_home_mount_point = True - break + if p["mountpoint"] in subvolume_mountpoints and p["mountpoint"] != '/': + # mountpoint is already define, remove subvolume from the list + btrfs_subvolumes = [d for d in btrfs_subvolumes if d['mountPoint'] != p["mountpoint"]] + # Now we shouold have a valid list of needed subvolumes, so all subvolumes can be created and mounted + for s in btrfs_subvolumes: + # Create the subvolume + subprocess.check_call(['btrfs', 'subvolume', 'create', + root_mount_point + s['subvolume']]) + + # Handle swap subvolume separately needs_swap_subvolume = False swap_choice = global_storage.value( "partitionChoices" ) if swap_choice: swap_choice = swap_choice.get( "swap", None ) if swap_choice and swap_choice == "file": needs_swap_subvolume = True - - subprocess.check_call(['btrfs', 'subvolume', 'create', - root_mount_point + '/@']) - - if not has_home_mount_point: - subprocess.check_call(['btrfs', 'subvolume', 'create', - root_mount_point + '/@home']) if needs_swap_subvolume: subprocess.check_call(['btrfs', 'subvolume', 'create', root_mount_point + '/@swap']) @@ -112,17 +115,13 @@ def mount_partition(root_mount_point, partition, partitions): if "luksMapperName" in partition: device = os.path.join("/dev/mapper", partition["luksMapperName"]) - if libcalamares.utils.mount(device, + # Mount the subvolumes + for s in btrfs_subvolumes: + mount_option = f"subvol={s[subvolume]}" + if libcalamares.utils.mount(device, mount_point, fstype, - ",".join(["subvol=@", partition.get("options", "")])) != 0: - libcalamares.utils.warning("Cannot mount {}".format(device)) - - if not has_home_mount_point: - if libcalamares.utils.mount(device, - root_mount_point + "/home", - fstype, - ",".join(["subvol=@home", partition.get("options", "")])) != 0: + ",".join([mount_option, partition.get("options", "")])) != 0: libcalamares.utils.warning("Cannot mount {}".format(device)) if needs_swap_subvolume: From 4b6718b354d1831b8336946798b6113e0aebc71f Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 26 Jan 2021 22:35:42 +0200 Subject: [PATCH 05/18] Further generalize subvolume handling --- src/modules/mount/main.py | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 4b0e911e3..9e7be8a68 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -89,24 +89,19 @@ def mount_partition(root_mount_point, partition, partitions): if "mountPoint" not in p or not p["mountPoint"]: continue if p["mountpoint"] in subvolume_mountpoints and p["mountpoint"] != '/': - # mountpoint is already define, remove subvolume from the list + # mountpoint is already defined, remove subvolume from the list btrfs_subvolumes = [d for d in btrfs_subvolumes if d['mountPoint'] != p["mountpoint"]] - # Now we shouold have a valid list of needed subvolumes, so all subvolumes can be created and mounted - for s in btrfs_subvolumes: - # Create the subvolume - subprocess.check_call(['btrfs', 'subvolume', 'create', - root_mount_point + s['subvolume']]) - - # Handle swap subvolume separately + # Check if we need a subvolume for swap file needs_swap_subvolume = False swap_choice = global_storage.value( "partitionChoices" ) if swap_choice: swap_choice = swap_choice.get( "swap", None ) if swap_choice and swap_choice == "file": - needs_swap_subvolume = True - if needs_swap_subvolume: + btrfs_subvolumes.append({'mountPoint': '/swap', 'subvolume': '/@swap'}) + # Create the subvolumes that are in the completed list + for s in btrfs_subvolumes: subprocess.check_call(['btrfs', 'subvolume', 'create', - root_mount_point + '/@swap']) + root_mount_point + s['subvolume']]) subprocess.check_call(["umount", "-v", root_mount_point]) @@ -122,14 +117,7 @@ def mount_partition(root_mount_point, partition, partitions): mount_point, fstype, ",".join([mount_option, partition.get("options", "")])) != 0: - libcalamares.utils.warning("Cannot mount {}".format(device)) - - if needs_swap_subvolume: - if libcalamares.utils.mount(device, - root_mount_point + "/swap", - fstype, - ",".join(["subvol=@swap", partition.get("options", "")])) != 0: - libcalamares.utils.warning("Cannot mount {}".format(device)) + libcalamares.utils.warning(f"Cannot mount {device}") def run(): From f53f43ad03b955d43be16158912540c6d82d3025 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 26 Jan 2021 22:42:35 +0200 Subject: [PATCH 06/18] Remove some unnecessary bits --- src/modules/mount/main.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 9e7be8a68..17041fdc5 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -89,10 +89,8 @@ def mount_partition(root_mount_point, partition, partitions): if "mountPoint" not in p or not p["mountPoint"]: continue if p["mountpoint"] in subvolume_mountpoints and p["mountpoint"] != '/': - # mountpoint is already defined, remove subvolume from the list btrfs_subvolumes = [d for d in btrfs_subvolumes if d['mountPoint'] != p["mountpoint"]] # Check if we need a subvolume for swap file - needs_swap_subvolume = False swap_choice = global_storage.value( "partitionChoices" ) if swap_choice: swap_choice = swap_choice.get( "swap", None ) From 092374d08ce67bdb21d77bcc02c4ad052828c302 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 26 Jan 2021 22:48:02 +0200 Subject: [PATCH 07/18] Add modified list to global storage --- src/modules/mount/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 17041fdc5..7a6c1f176 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -96,6 +96,8 @@ def mount_partition(root_mount_point, partition, partitions): swap_choice = swap_choice.get( "swap", None ) if swap_choice and swap_choice == "file": btrfs_subvolumes.append({'mountPoint': '/swap', 'subvolume': '/@swap'}) + # Store created list in global storage so it can be used in the fstab module + libcalamares.globalstorage.insert("btrfsSubvolumes", btrfs_subvolumes) # Create the subvolumes that are in the completed list for s in btrfs_subvolumes: subprocess.check_call(['btrfs', 'subvolume', 'create', From 14fbbd92dc367f56ce85c619165421e307093e84 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 26 Jan 2021 22:56:31 +0200 Subject: [PATCH 08/18] Get configured subvolumes from the global storage --- src/modules/fstab/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index 6977ccad1..ed73f2f0f 100644 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -192,7 +192,9 @@ class FstabGenerator(object): 'list', self.root_mount_point]) output_lines = output.splitlines() + btrfs_subvolumes = libcalamares.globalstorage.value("btrfsSubvolumes") for line in output_lines: + # This is where changes need to go if line.endswith(b'path @'): root_entry = partition root_entry["subvol"] = "@" From 8c0c84f162c77c440b16cee784513237288f3b2e Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Wed, 27 Jan 2021 15:41:01 +0200 Subject: [PATCH 09/18] Create all fstab entries one way instead of having special handling --- src/modules/fstab/main.py | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index ed73f2f0f..c2e221c37 100644 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -183,39 +183,19 @@ class FstabGenerator(object): print(FSTAB_HEADER, file=fstab_file) for partition in self.partitions: - # Special treatment for a btrfs root with @, @home and @swap - # subvolumes + # Special treatment for a btrfs subvolumes if (partition["fs"] == "btrfs" and partition["mountPoint"] == "/"): - output = subprocess.check_output(['btrfs', - 'subvolume', - 'list', - self.root_mount_point]) - output_lines = output.splitlines() + # Subvolume list has been created in mount.conf and curated in mount module, + # so all subvolumes here should be safe to add to fstab btrfs_subvolumes = libcalamares.globalstorage.value("btrfsSubvolumes") - for line in output_lines: - # This is where changes need to go - if line.endswith(b'path @'): - root_entry = partition - root_entry["subvol"] = "@" - dct = self.generate_fstab_line_info(root_entry) - if dct: + for s in btrfs_subvolumes: + mount_entry = partition + mount_entry["mountPoint"] = s["mountPoint"] + home_entry["subvol"] = s["subvolume"] + dct = self.generate_fstab_line_info(mount_entry) + if dct: self.print_fstab_line(dct, file=fstab_file) - elif line.endswith(b'path @home'): - home_entry = partition - home_entry["mountPoint"] = "/home" - home_entry["subvol"] = "@home" - dct = self.generate_fstab_line_info(home_entry) - if dct: - self.print_fstab_line(dct, file=fstab_file) - elif line.endswith(b'path @swap'): - swap_part_entry = partition - swap_part_entry["mountPoint"] = "/swap" - swap_part_entry["subvol"] = "@swap" - dct = self.generate_fstab_line_info(swap_part_entry) - if dct: - self.print_fstab_line(dct, file=fstab_file) - else: dct = self.generate_fstab_line_info(partition) if dct: From fcf6e2fb25fded1c0b849094dbe2632ab121d09b Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 2 Feb 2021 23:07:35 +0200 Subject: [PATCH 10/18] fix typos --- src/modules/mount/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 7a6c1f176..d12f88d71 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -88,7 +88,7 @@ def mount_partition(root_mount_point, partition, partitions): for p in partitions: if "mountPoint" not in p or not p["mountPoint"]: continue - if p["mountpoint"] in subvolume_mountpoints and p["mountpoint"] != '/': + if p["mountPoint"] in subvolume_mountpoints and p["mountPoint"] != '/': btrfs_subvolumes = [d for d in btrfs_subvolumes if d['mountPoint'] != p["mountpoint"]] # Check if we need a subvolume for swap file swap_choice = global_storage.value( "partitionChoices" ) From 1e0295dc652ec2166a7f2acee1fcb38868c2f1e1 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Wed, 3 Feb 2021 22:55:11 +0200 Subject: [PATCH 11/18] Fix name error --- src/modules/mount/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index d12f88d71..5bab086a7 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -112,7 +112,7 @@ def mount_partition(root_mount_point, partition, partitions): # Mount the subvolumes for s in btrfs_subvolumes: - mount_option = f"subvol={s[subvolume]}" + mount_option = f"subvol={s['subvolume']}" if libcalamares.utils.mount(device, mount_point, fstype, From 1896a38cccdbaab6650b69e115adb93443159346 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Sat, 6 Feb 2021 01:38:03 +0200 Subject: [PATCH 12/18] Fix a typo --- src/modules/mount/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 5bab086a7..eb2614caa 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -89,7 +89,7 @@ def mount_partition(root_mount_point, partition, partitions): if "mountPoint" not in p or not p["mountPoint"]: continue if p["mountPoint"] in subvolume_mountpoints and p["mountPoint"] != '/': - btrfs_subvolumes = [d for d in btrfs_subvolumes if d['mountPoint'] != p["mountpoint"]] + btrfs_subvolumes = [d for d in btrfs_subvolumes if d['mountPoint'] != p["mountPoint"]] # Check if we need a subvolume for swap file swap_choice = global_storage.value( "partitionChoices" ) if swap_choice: From 16bf7925a2524c81cc0bdd2fc28109cd5ea17ec0 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Sat, 6 Feb 2021 19:48:09 +0200 Subject: [PATCH 13/18] Adjust comments --- src/modules/mount/main.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index eb2614caa..50e72b316 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -74,12 +74,7 @@ def mount_partition(root_mount_point, partition, partitions): partition.get("options", "")) != 0: libcalamares.utils.warning("Cannot mount {}".format(device)) - # If the root partition is btrfs, we create a subvolume "@" - # for the root mount point. - # If a separate /home partition isn't defined, we also create - # a subvolume "@home". - # If a swapfile is used, we also create a subvolume "@swap". - # Finally we remount all of the above on the correct paths. + # Special handling for btrfs subvolumes. Create the subvolumes listed in mount.conf if fstype == "btrfs" and partition["mountPoint"] == '/': # Root has been mounted to btrfs volume -> create subvolumes from configuration btrfs_subvolumes = libcalamares.job.configuration.get("btrfsSubvolumes") or [] From 67aedd5582c3c1426331e49ed0e8768000dfd3c3 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Sat, 6 Feb 2021 19:54:29 +0200 Subject: [PATCH 14/18] Move comments closer to where they are used --- src/modules/mount/mount.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/mount/mount.conf b/src/modules/mount/mount.conf index b96d4576a..6168e97cc 100644 --- a/src/modules/mount/mount.conf +++ b/src/modules/mount/mount.conf @@ -19,10 +19,6 @@ # The device is not mounted if the mountPoint is unset or if the fs is # set to unformatted. # ---- -# Btrfs subvolumes to create if root filesystem is on btrfs volume. -# If mountpoint is mounted already to another partition, it is ignored. -# Separate subvolume for swapfile is handled separately and automatically. extraMounts: - device: proc fs: proc @@ -45,6 +41,10 @@ extraMountsEfi: fs: efivarfs mountPoint: /sys/firmware/efi/efivars +# Btrfs subvolumes to create if root filesystem is on btrfs volume. +# If mountpoint is mounted already to another partition, it is ignored. +# Separate subvolume for swapfile is handled separately and automatically. + btrfsSubvolumes: - mountPoint: / subvolume: /@ From b16bd6bb23a0bf4775e2626765f3166d1a820b23 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Sat, 6 Feb 2021 20:03:30 +0200 Subject: [PATCH 15/18] Fix name error --- src/modules/fstab/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index c2e221c37..b6d7a4b2a 100644 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -192,7 +192,7 @@ class FstabGenerator(object): for s in btrfs_subvolumes: mount_entry = partition mount_entry["mountPoint"] = s["mountPoint"] - home_entry["subvol"] = s["subvolume"] + mount_entry["subvol"] = s["subvolume"] dct = self.generate_fstab_line_info(mount_entry) if dct: self.print_fstab_line(dct, file=fstab_file) From 6d55005da07dcac8baced60c591bb6b5ee32ed2f Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Sun, 7 Feb 2021 00:16:26 +0200 Subject: [PATCH 16/18] Mount subvolumes to correct mountpoints --- src/modules/mount/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 50e72b316..27df309a3 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -108,8 +108,9 @@ def mount_partition(root_mount_point, partition, partitions): # Mount the subvolumes for s in btrfs_subvolumes: mount_option = f"subvol={s['subvolume']}" + subvolume_mountpoint = mount_point[:-1] + s['mountPoint'] if libcalamares.utils.mount(device, - mount_point, + subvolume_mountpoint, fstype, ",".join([mount_option, partition.get("options", "")])) != 0: libcalamares.utils.warning(f"Cannot mount {device}") From 0c92a36a5393114a2bafd3af654954bdb1ae9bd9 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Sun, 7 Feb 2021 15:29:30 +0200 Subject: [PATCH 17/18] Remove unnecessary comment --- src/modules/mount/main.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 27df309a3..69c994efc 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -32,9 +32,6 @@ def pretty_name(): def mount_partition(root_mount_point, partition, partitions): """ Do a single mount of @p partition inside @p root_mount_point. - - The @p partitions are used to handle btrfs special-cases: - then subvolumes are created for root and home. """ # Create mount point with `+` rather than `os.path.join()` because # `partition["mountPoint"]` starts with a '/'. From 16eff98a0653807d5a38a06cc4ccba7983c6ee10 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Sun, 7 Feb 2021 15:39:38 +0200 Subject: [PATCH 18/18] Don't use f-strings yet. --- src/modules/mount/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 69c994efc..07166dd75 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -104,13 +104,13 @@ def mount_partition(root_mount_point, partition, partitions): # Mount the subvolumes for s in btrfs_subvolumes: - mount_option = f"subvol={s['subvolume']}" + mount_option = "subvol={}".format(s['subvolume']) subvolume_mountpoint = mount_point[:-1] + s['mountPoint'] if libcalamares.utils.mount(device, subvolume_mountpoint, fstype, ",".join([mount_option, partition.get("options", "")])) != 0: - libcalamares.utils.warning(f"Cannot mount {device}") + libcalamares.utils.warning("Cannot mount {}".format(device)) def run():