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"
+
+
+def disk_name_for_partition(partition):
+ name = os.path.basename(partition["device"])
+ return re.sub("[0-9]+$", "", name)
+
+
+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
+
+ 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"])
- fs = FS_MAP.get(fs, fs)
-
- if not mount_point and not fs == "swap":
- return
-
- options = "defaults"
-
- if mount_point == "/":
- check = 1
- elif mount_point:
- check = 2
- else:
- check = 0
-
- return "UUID={} {:<14} {:<7} {:<10} 0 {}".format(
- partition["uuid"],
- mount_point or "none",
- fs,
- options,
- check)
+def run():
+ gs = libcalamares.globalstorage
+ conf = libcalamares.job.configuration
+ partitions = gs.value("partitions")
+ root_mount_point = gs.value("rootMountPoint")
+ mount_options = conf["mountOptions"]
+ ssd_extra_mount_options = conf.get("ssdExtraMountOptions", {})
-def run():
- partitions = libcalamares.globalstorage.value("partitions")
- root_mount_point = libcalamares.globalstorage.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)
-
- # 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