diff --git a/archinstall/lib/disk/device_handler.py b/archinstall/lib/disk/device_handler.py index a0eaa0e5e7..bc9ac9ecd0 100644 --- a/archinstall/lib/disk/device_handler.py +++ b/archinstall/lib/disk/device_handler.py @@ -271,6 +271,10 @@ def format( options = [] match fs_type: + case FilesystemType.Bcachefs: + # bcachefs uses a different command structure + command = 'bcachefs' + options.append('format') case FilesystemType.Btrfs | FilesystemType.Xfs: # Force overwrite options.append('-f') @@ -566,7 +570,13 @@ def _setup_partition( length=length_sector.value, ) - fs_value = part_mod.safe_fs_type.parted_value + # Parted does not have a file system type for bcachefs as of version 3.6, use + # ext4 in its place as that will results in a type of native Linux file system + if part_mod.safe_fs_type == FilesystemType.Bcachefs: + fs_value = FilesystemType.Ext4.parted_value + else: + fs_value = part_mod.safe_fs_type.parted_value + filesystem = FileSystem(type=fs_value, geometry=geometry) partition = Partition( diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index aa5781f951..40ac867f50 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -344,3 +344,12 @@ def requires_alsa_fw() -> bool: return True return False + + @staticmethod + def has_bcachefs() -> bool: + """ + Check if bcachefs kernel module is available/loaded. + Required since bcachefs was removed from mainline kernel in 6.18+ + and now requires bcachefs-dkms package. + """ + return 'bcachefs' in _sys_info.loaded_modules diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index da1941834e..dd630e1aa1 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -242,7 +242,34 @@ def sanity_check(self) -> None: # self._verify_boot_part() self._verify_service_stop() + def _verify_bcachefs_support(self) -> None: + """ + Check if bcachefs is being used and ensure the module is available. + Since bcachefs was removed from kernel 6.18+, it requires bcachefs-dkms. + """ + # Check if any partition uses bcachefs + if not any(part.fs_type == FilesystemType.Bcachefs for mod in self._disk_config.device_modifications for part in mod.partitions): + return + + # Check if module was manually loaded + if SysInfo.has_bcachefs(): + return + + info('Bcachefs filesystem selected but module not loaded') + info('Installing bcachefs packages...') + + try: + # Use mainline headers and build dkms to load modules # + Pacman.run('-Sy --noconfirm --needed linux-headers bcachefs-dkms ') + info('Bcachefs packages installed successfully. DKMS will load the module.') + except SysCallError as err: + raise RequirementError(f'Failed to install bcachefs-dkms: {err}') + def mount_ordered_layout(self) -> None: + # Ensure bcachefs support is available before attempting to mount + # only installs if bcachefs is selected and module not loaded + self._verify_bcachefs_support() + debug('Mounting ordered layout') luks_handlers: dict[Any, Luks2] = {} @@ -362,7 +389,13 @@ def _mount_partition(self, part_mod: PartitionModification) -> None: # it would be none if it's btrfs as the subvolumes will have the mountpoints defined if part_mod.mountpoint: target = self.target / part_mod.relative_mountpoint - device_handler.mount(part_mod.dev_path, target, options=part_mod.mount_options) + + if part_mod.fs_type == FilesystemType.Bcachefs: + mount_fs = part_mod.fs_type.value + else: + mount_fs = None + + device_handler.mount(part_mod.dev_path, target, mount_fs, options=part_mod.mount_options) elif part_mod.fs_type == FilesystemType.Btrfs: # Only mount BTRFS subvolumes that have mountpoints specified subvols_with_mountpoints = [sv for sv in part_mod.btrfs_subvols if sv.mountpoint is not None] @@ -854,10 +887,26 @@ def _prepare_fs_type( if (pkg := fs_type.installation_pkg) is not None: self._base_packages.append(pkg) + # Install linux-headers and bcachefs-dkms if bcachefs is selected + if fs_type == FilesystemType.Bcachefs: + self._base_packages.extend(f'{kernel}-headers' for kernel in self.kernels) + self._base_packages.append('bcachefs-dkms') + # https://github.com/archlinux/archinstall/issues/1837 - if fs_type.fs_type_mount == 'btrfs': + # https://github.com/koverstreet/bcachefs/issues/916 + if fs_type.fs_type_mount in ('btrfs', 'bcachefs'): self._disable_fstrim = True + if fs_type.fs_type_mount == 'bcachefs' and 'bcachefs' not in self._modules: + self._modules.append('bcachefs') + + if 'bcachefs' not in self._hooks: + try: + block_index = self._hooks.index('block') + self._hooks.insert(block_index + 1, 'bcachefs') + except ValueError: + pass + # There is not yet an fsck tool for NTFS. If it's being used for the root filesystem, the hook should be removed. if fs_type.fs_type_mount == 'ntfs3' and mountpoint == self.target: if 'fsck' in self._hooks: diff --git a/archinstall/lib/interactions/disk_conf.py b/archinstall/lib/interactions/disk_conf.py index 43a82529ad..3003fa6d47 100644 --- a/archinstall/lib/interactions/disk_conf.py +++ b/archinstall/lib/interactions/disk_conf.py @@ -250,6 +250,7 @@ def select_main_filesystem_format() -> FilesystemType: ] if arch_config_handler.args.advanced: + items.append(MenuItem('bcachefs', value=FilesystemType.Bcachefs)) items.append(MenuItem('ntfs', value=FilesystemType.Ntfs)) group = MenuItemGroup(items, sort_items=False) diff --git a/archinstall/lib/models/device.py b/archinstall/lib/models/device.py index 45cf06402e..115bf5acae 100644 --- a/archinstall/lib/models/device.py +++ b/archinstall/lib/models/device.py @@ -777,6 +777,7 @@ def bytes(self) -> bytes: class FilesystemType(Enum): + Bcachefs = 'bcachefs' Btrfs = 'btrfs' Ext2 = 'ext2' Ext3 = 'ext3' @@ -813,6 +814,8 @@ def parted_value(self) -> str: @property def installation_pkg(self) -> str | None: match self: + case FilesystemType.Bcachefs: + return 'bcachefs-tools' case FilesystemType.Btrfs: return 'btrfs-progs' case FilesystemType.Xfs: