diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index 6c2168a8e..6977ccad1 100644 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -183,7 +183,7 @@ class FstabGenerator(object): print(FSTAB_HEADER, file=fstab_file) for partition in self.partitions: - # Special treatment for a btrfs root with @ and @home + # Special treatment for a btrfs root with @, @home and @swap # subvolumes if (partition["fs"] == "btrfs" and partition["mountPoint"] == "/"): @@ -206,6 +206,13 @@ class FstabGenerator(object): 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) @@ -319,14 +326,19 @@ def create_swapfile(root_mount_point, root_btrfs): The swapfile-creation covers progress from 0.2 to 0.5 """ libcalamares.job.setprogress(0.2) - swapfile_path = os.path.join(root_mount_point, "swapfile") - with open(swapfile_path, "wb") as f: - pass if root_btrfs: + # btrfs swapfiles must reside on a subvolume that is not snapshotted to prevent file system corruption + swapfile_path = os.path.join(root_mount_point, "swap/swapfile") + with open(swapfile_path, "wb") as f: + pass o = subprocess.check_output(["chattr", "+C", swapfile_path]) libcalamares.utils.debug("swapfile attributes: {!s}".format(o)) o = subprocess.check_output(["btrfs", "property", "set", swapfile_path, "compression", "none"]) libcalamares.utils.debug("swapfile compression: {!s}".format(o)) + else: + swapfile_path = os.path.join(root_mount_point, "swapfile") + with open(swapfile_path, "wb") as f: + pass # Create the swapfile; swapfiles are small-ish zeroes = bytes(16384) with open(swapfile_path, "wb") as f: @@ -374,7 +386,12 @@ def run(): swap_choice = swap_choice.get( "swap", None ) if swap_choice and swap_choice == "file": # There's no formatted partition for it, so we'll sneak in an entry - partitions.append( dict(fs="swap", mountPoint=None, claimed=True, device="/swapfile", uuid=None) ) + root_partitions = [ p["fs"].lower() for p in partitions if p["mountPoint"] == "/" ] + root_btrfs = (root_partitions[0] == "btrfs") if root_partitions else False + if root_btrfs: + partitions.append( dict(fs="swap", mountPoint=None, claimed=True, device="/swap/swapfile", uuid=None) ) + else: + partitions.append( dict(fs="swap", mountPoint=None, claimed=True, device="/swapfile", uuid=None) ) else: swap_choice = None diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 1313fca49..3982176df 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -38,6 +38,7 @@ def mount_partition(root_mount_point, partition, partitions): """ # Create mount point with `+` rather than `os.path.join()` because # `partition["mountPoint"]` starts with a '/'. + global_storage = libcalamares.globalstorage raw_mount_point = partition["mountPoint"] if not raw_mount_point: return @@ -77,6 +78,7 @@ def mount_partition(root_mount_point, partition, partitions): # 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. if fstype == "btrfs" and partition["mountPoint"] == '/': has_home_mount_point = False @@ -86,6 +88,12 @@ def mount_partition(root_mount_point, partition, partitions): if p["mountPoint"] == "/home": has_home_mount_point = True break + 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 + '/@']) @@ -93,6 +101,9 @@ def mount_partition(root_mount_point, partition, partitions): 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']) subprocess.check_call(["umount", "-v", root_mount_point]) @@ -113,6 +124,13 @@ def mount_partition(root_mount_point, partition, partitions): fstype, ",".join(["subvol=@home", 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)) def run():