From 87367d5abdc1f067bbb829f1485023b417fa3cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Mon, 4 Aug 2014 16:16:53 +0200 Subject: [PATCH] fstab: Refactor to be able to add ssd-specific options --- src/modules/fstab/main.py | 144 +++++++++++++++++++++++++--------- src/modules/fstab/module.conf | 9 +++ 2 files changed, 117 insertions(+), 36 deletions(-) diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index c63253c4c..caef3d99d 100644 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -18,6 +18,7 @@ # along with Calamares. If not, see . import os +import re import libcalamares @@ -30,6 +31,7 @@ HEADER = """# /etc/fstab: static file system information. # # """ +# Turn Parted filesystem names into fstab names FS_MAP = { "fat": "vfat", "linuxswap": "swap", @@ -41,49 +43,119 @@ def mkdir_p(path): os.makedirs(path) -def generate_fstab_line(partition): - fs = partition["fs"] - mount_point = partition["mountPoint"] +def is_ssd_disk(disk_name): + filename = os.path.join("/sys/block", disk_name, "queue/rotational") + if not os.path.exists(filename): + # Should not happen unless sysfs changes, but better safe than sorry + return False + with open(filename) as f: + return f.read() == "0\n" - fs = FS_MAP.get(fs, fs) - if not mount_point and not fs == "swap": - return +def disk_name_for_partition(partition): + name = os.path.basename(partition["device"]) + return re.sub("[0-9]+$", "", name) - options = "defaults" - if mount_point == "/": - check = 1 - elif mount_point: - check = 2 - else: - check = 0 +class FstabGenerator(object): + def __init__(self, partitions, root_mount_point, mount_options, + ssd_extra_mount_options): + self.partitions = partitions + self.root_mount_point = root_mount_point + self.mount_options = mount_options + self.ssd_extra_mount_options = ssd_extra_mount_options + self.ssd_disks = set() + self.root_is_ssd = False - return "UUID={} {:<14} {:<7} {:<10} 0 {}".format( - partition["uuid"], - mount_point or "none", - fs, - options, - check) + def run(self): + self.find_ssd_disks() + self.generate_fstab() + self.create_mount_points() + return None + def find_ssd_disks(self): + disks = {disk_name_for_partition(x) for x in self.partitions} + self.ssd_disks = {x for x in disks if is_ssd_disk(x)} + + def generate_fstab(self): + # Create fstab + mkdir_p(os.path.join(self.root_mount_point, "etc")) + fstab_path = os.path.join(self.root_mount_point, "etc", "fstab") + with open(fstab_path, "w") as fl: + print(HEADER, file=fl) + for partition in self.partitions: + dct = self.generate_fstab_line_info(partition) + if dct: + self.print_fstab_line(dct, file=fl) + + if self.root_is_ssd: + # Mount /tmp on a tmpfs + dct = dict( + device="tmpfs", + mount_point="/tmp", + fs="tmpfs", + options="defaults,noatime,mode=1777", + check=0, + ) + self.print_fstab_line(dct, file=fl) + + def generate_fstab_line_info(self, partition): + fs = partition["fs"] + mount_point = partition["mountPoint"] + disk_name = disk_name_for_partition(partition) + is_ssd = disk_name in self.ssd_disks + + fs = FS_MAP.get(fs, fs) + + if not mount_point and not fs == "swap": + return None + + options = self.mount_options.get(fs, self.mount_options["default"]) + if is_ssd: + extra = self.ssd_extra_mount_options.get(fs) + if extra: + options += "," + extra + + if mount_point == "/": + check = 1 + elif mount_point: + check = 2 + else: + check = 0 + + if mount_point == "/": + self.root_is_ssd = is_ssd + + return dict( + device="UUID=" + partition["uuid"], + mount_point=mount_point or "none", + fs=fs, + options=options, + check=check) + + def print_fstab_line(self, dct, file=None): + line = "{:41} {:<14} {:<7} {:<10} 0 {}".format( + dct["device"], + dct["mount_point"], + dct["fs"], + dct["options"], + dct["check"]) + print(line, file=file) + + def create_mount_points(self): + for partition in self.partitions: + if partition["mountPoint"]: + mkdir_p(self.root_mount_point + partition["mountPoint"]) def run(): - partitions = libcalamares.globalstorage.value("partitions") - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") + gs = libcalamares.globalstorage + conf = libcalamares.job.configuration + partitions = gs.value("partitions") + root_mount_point = gs.value("rootMountPoint") - # Create fstab - mkdir_p(os.path.join(root_mount_point, "etc")) - fstab_path = os.path.join(root_mount_point, "etc", "fstab") - with open(fstab_path, "w") as fl: - print(HEADER, file=fl) - for partition in partitions: - line = generate_fstab_line(partition) - if line: - print(line, file=fl) + mount_options = conf["mountOptions"] + ssd_extra_mount_options = conf.get("ssdExtraMountOptions", {}) - # Create mount points - for partition in partitions: - if partition["mountPoint"]: - mkdir_p(root_mount_point + partition["mountPoint"]) - - return None + generator = FstabGenerator(partitions, root_mount_point, + mount_options, ssd_extra_mount_options) + return generator.run() diff --git a/src/modules/fstab/module.conf b/src/modules/fstab/module.conf index 2bb251135..ccae25853 100644 --- a/src/modules/fstab/module.conf +++ b/src/modules/fstab/module.conf @@ -4,3 +4,12 @@ interface: "python" requires: [] script: "main.py" configuration: + mountOptions: + default: defaults,noatime + btrfs: defaults,noatime,space_cache,autodefrag + ssdExtraMountOptions: + ext4: discard + jfs: discard + xfs: discard + swap: discard + btrfs: discard,compress=lzo