Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/lib/disk
diff options
context:
space:
mode:
authorcodefiles <11915375+codefiles@users.noreply.github.com>2024-03-11 03:09:26 -0400
committerGitHub <noreply@github.com>2024-03-11 08:09:26 +0100
commitc210cdcb8f0883ac13a6ee22aebb8f01f3043e09 (patch)
tree2d6b33e57f8a9cfc1052bd6e8a231859acc194a3 /archinstall/lib/disk
parent1064f74846035afb3ffcf05e49d968d5da6d5521 (diff)
Fix Btrfs mount options (#2404)
Diffstat (limited to 'archinstall/lib/disk')
-rw-r--r--archinstall/lib/disk/device_handler.py26
-rw-r--r--archinstall/lib/disk/device_model.py36
-rw-r--r--archinstall/lib/disk/partitioning_menu.py39
-rw-r--r--archinstall/lib/disk/subvolume_menu.py27
4 files changed, 52 insertions, 76 deletions
diff --git a/archinstall/lib/disk/device_handler.py b/archinstall/lib/disk/device_handler.py
index 59ee150d..c06247e6 100644
--- a/archinstall/lib/disk/device_handler.py
+++ b/archinstall/lib/disk/device_handler.py
@@ -437,9 +437,19 @@ class DeviceHandler(object):
if not luks_handler.mapper_dev:
raise DiskError('Failed to unlock luks device')
- self.mount(luks_handler.mapper_dev, self._TMP_BTRFS_MOUNT, create_target_mountpoint=True)
+ self.mount(
+ luks_handler.mapper_dev,
+ self._TMP_BTRFS_MOUNT,
+ create_target_mountpoint=True,
+ options=part_mod.mount_options
+ )
else:
- self.mount(part_mod.safe_dev_path, self._TMP_BTRFS_MOUNT, create_target_mountpoint=True)
+ self.mount(
+ part_mod.safe_dev_path,
+ self._TMP_BTRFS_MOUNT,
+ create_target_mountpoint=True,
+ options=part_mod.mount_options
+ )
for sub_vol in part_mod.btrfs_subvols:
debug(f'Creating subvolume: {sub_vol.name}')
@@ -451,18 +461,6 @@ class DeviceHandler(object):
SysCommand(f"btrfs subvolume create {subvol_path}")
- if sub_vol.nodatacow:
- try:
- SysCommand(f'chattr +C {subvol_path}')
- except SysCallError as err:
- raise DiskError(f'Could not set nodatacow attribute at {subvol_path}: {err}')
-
- if sub_vol.compress:
- try:
- SysCommand(f'chattr +c {subvol_path}')
- except SysCallError as err:
- raise DiskError(f'Could not set compress attribute at {subvol_path}: {err}')
-
if luks_handler is not None and luks_handler.mapper_dev is not None:
self.umount(luks_handler.mapper_dev)
luks_handler.lock()
diff --git a/archinstall/lib/disk/device_model.py b/archinstall/lib/disk/device_model.py
index d4563faa..423c65e4 100644
--- a/archinstall/lib/disk/device_model.py
+++ b/archinstall/lib/disk/device_model.py
@@ -315,6 +315,11 @@ class Size:
return self._normalize() >= other._normalize()
+class BtrfsMountOption(Enum):
+ compress = 'compress=zstd'
+ nodatacow = 'nodatacow'
+
+
@dataclass
class _BtrfsSubvolumeInfo:
name: Path
@@ -458,8 +463,6 @@ class _DeviceInfo:
class SubvolumeModification:
name: Path
mountpoint: Optional[Path] = None
- compress: bool = False
- nodatacow: bool = False
@classmethod
def from_existing_subvol_info(cls, info: _BtrfsSubvolumeInfo) -> SubvolumeModification:
@@ -475,31 +478,11 @@ class SubvolumeModification:
mountpoint = Path(entry['mountpoint']) if entry['mountpoint'] else None
- compress = entry.get('compress', False)
- nodatacow = entry.get('nodatacow', False)
-
- if compress and nodatacow:
- raise ValueError('compress and nodatacow flags cannot be enabled simultaneously on a btfrs subvolume')
-
- mods.append(
- SubvolumeModification(
- entry['name'],
- mountpoint,
- compress,
- nodatacow
- )
- )
+ mods.append(SubvolumeModification(entry['name'], mountpoint))
return mods
@property
- def mount_options(self) -> List[str]:
- options = []
- options += ['compress'] if self.compress else []
- options += ['nodatacow'] if self.nodatacow else []
- return options
-
- @property
def relative_mountpoint(self) -> Path:
"""
Will return the relative path based on the anchor
@@ -516,12 +499,7 @@ class SubvolumeModification:
return False
def json(self) -> Dict[str, Any]:
- return {
- 'name': str(self.name),
- 'mountpoint': str(self.mountpoint),
- 'compress': self.compress,
- 'nodatacow': self.nodatacow
- }
+ return {'name': str(self.name), 'mountpoint': str(self.mountpoint)}
def table_data(self) -> Dict[str, Any]:
return self.json()
diff --git a/archinstall/lib/disk/partitioning_menu.py b/archinstall/lib/disk/partitioning_menu.py
index a9478158..823605e3 100644
--- a/archinstall/lib/disk/partitioning_menu.py
+++ b/archinstall/lib/disk/partitioning_menu.py
@@ -5,7 +5,7 @@ from pathlib import Path
from typing import Any, Dict, TYPE_CHECKING, List, Optional, Tuple
from .device_model import PartitionModification, FilesystemType, BDevice, Size, Unit, PartitionType, PartitionFlag, \
- ModificationStatus, DeviceGeometry, SectorSize
+ ModificationStatus, DeviceGeometry, SectorSize, BtrfsMountOption
from ..hardware import SysInfo
from ..menu import Menu, ListManager, MenuSelection, TextInput
from ..output import FormattedOutput, warn
@@ -30,6 +30,7 @@ class PartitioningList(ListManager):
'mark_bootable': str(_('Mark/Unmark as bootable')),
'set_filesystem': str(_('Change filesystem')),
'btrfs_mark_compressed': str(_('Mark/Unmark as compressed')), # btrfs only
+ 'btrfs_mark_nodatacow': str(_('Mark/Unmark as nodatacow')), # btrfs only
'btrfs_set_subvolumes': str(_('Set subvolumes')), # btrfs only
'delete_partition': str(_('Delete partition'))
}
@@ -71,12 +72,17 @@ class PartitioningList(ListManager):
self._actions['set_filesystem'],
self._actions['mark_bootable'],
self._actions['btrfs_mark_compressed'],
+ self._actions['btrfs_mark_nodatacow'],
self._actions['btrfs_set_subvolumes']
]
# non btrfs partitions shouldn't get btrfs options
if selection.fs_type != FilesystemType.Btrfs:
- not_filter += [self._actions['btrfs_mark_compressed'], self._actions['btrfs_set_subvolumes']]
+ not_filter += [
+ self._actions['btrfs_mark_compressed'],
+ self._actions['btrfs_mark_nodatacow'],
+ self._actions['btrfs_set_subvolumes']
+ ]
else:
not_filter += [self._actions['assign_mountpoint']]
@@ -122,7 +128,9 @@ class PartitioningList(ListManager):
if fs_type == FilesystemType.Btrfs:
entry.mountpoint = None
case 'btrfs_mark_compressed' if entry:
- self._set_compressed(entry)
+ self._toggle_mount_option(entry, BtrfsMountOption.compress)
+ case 'btrfs_mark_nodatacow' if entry:
+ self._toggle_mount_option(entry, BtrfsMountOption.nodatacow)
case 'btrfs_set_subvolumes' if entry:
self._set_btrfs_subvolumes(entry)
case 'delete_partition' if entry:
@@ -141,13 +149,28 @@ class PartitioningList(ListManager):
else:
return [d for d in data if d != entry]
- def _set_compressed(self, partition: PartitionModification):
- compression = 'compress=zstd'
+ def _toggle_mount_option(
+ self,
+ partition: PartitionModification,
+ option: BtrfsMountOption
+ ):
+ if option.value not in partition.mount_options:
+ if option == BtrfsMountOption.compress:
+ partition.mount_options = [
+ o for o in partition.mount_options
+ if o != BtrfsMountOption.nodatacow.value
+ ]
+
+ partition.mount_options = [
+ o for o in partition.mount_options
+ if not o.startswith(BtrfsMountOption.compress.name)
+ ]
- if compression in partition.mount_options:
- partition.mount_options = [o for o in partition.mount_options if o != compression]
+ partition.mount_options.append(option.value)
else:
- partition.mount_options.append(compression)
+ partition.mount_options = [
+ o for o in partition.mount_options if o != option.value
+ ]
def _set_btrfs_subvolumes(self, partition: PartitionModification):
partition.btrfs_subvols = SubvolumeMenu(
diff --git a/archinstall/lib/disk/subvolume_menu.py b/archinstall/lib/disk/subvolume_menu.py
index 2b70d7b2..48afa829 100644
--- a/archinstall/lib/disk/subvolume_menu.py
+++ b/archinstall/lib/disk/subvolume_menu.py
@@ -2,7 +2,7 @@ from pathlib import Path
from typing import Dict, List, Optional, Any, TYPE_CHECKING
from .device_model import SubvolumeModification
-from ..menu import Menu, TextInput, MenuSelectionType, ListManager
+from ..menu import TextInput, ListManager
from ..output import FormattedOutput
if TYPE_CHECKING:
@@ -36,23 +36,6 @@ class SubvolumeMenu(ListManager):
def selected_action_display(self, subvolume: SubvolumeModification) -> str:
return str(subvolume.name)
- def _prompt_options(self, editing: Optional[SubvolumeModification] = None) -> List[str]:
- preset_options = []
- if editing:
- preset_options = editing.mount_options
-
- choice = Menu(
- str(_("Select the desired subvolume options ")),
- ['nodatacow', 'compress'],
- skip=True,
- preset_values=preset_options,
- ).run()
-
- if choice.type_ == MenuSelectionType.Selection:
- return choice.value # type: ignore
-
- return []
-
def _add_subvolume(self, editing: Optional[SubvolumeModification] = None) -> Optional[SubvolumeModification]:
name = TextInput(f'\n\n{_("Subvolume name")}: ', editing.name if editing else '').run()
@@ -64,13 +47,7 @@ class SubvolumeMenu(ListManager):
if not mountpoint:
return None
- options = self._prompt_options(editing)
-
- subvolume = SubvolumeModification(Path(name), Path(mountpoint))
- subvolume.compress = 'compress' in options
- subvolume.nodatacow = 'nodatacow' in options
-
- return subvolume
+ return SubvolumeModification(Path(name), Path(mountpoint))
def handle_action(
self,