Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- config/rootfiles/common/btrfs-progs | 33 +++++++++++ lfs/btrfs-progs | 85 +++++++++++++++++++++++++++++ make.sh | 1 + 3 files changed, 119 insertions(+) create mode 100644 config/rootfiles/common/btrfs-progs create mode 100644 lfs/btrfs-progs
diff --git a/config/rootfiles/common/btrfs-progs b/config/rootfiles/common/btrfs-progs new file mode 100644 index 000000000..04af32d3f --- /dev/null +++ b/config/rootfiles/common/btrfs-progs @@ -0,0 +1,33 @@ +lib/udev/rules.d/64-btrfs-dm.rules +lib/udev/rules.d/64-btrfs-zoned.rules +usr/bin/btrfs +usr/bin/btrfs-convert +usr/bin/btrfs-find-root +usr/bin/btrfs-image +usr/bin/btrfs-map-logical +usr/bin/btrfs-select-super +usr/bin/btrfsck +usr/bin/btrfstune +usr/bin/fsck.btrfs +usr/bin/mkfs.btrfs +#usr/include/btrfs +#usr/include/btrfs/ctree.h +#usr/include/btrfs/ioctl.h +#usr/include/btrfs/kerncompat.h +#usr/include/btrfs/list.h +#usr/include/btrfs/rbtree.h +#usr/include/btrfs/rbtree_types.h +#usr/include/btrfs/send-stream.h +#usr/include/btrfs/send-utils.h +#usr/include/btrfs/send.h +#usr/include/btrfs/version.h +#usr/include/btrfsutil.h +#usr/lib/libbtrfs.a +#usr/lib/libbtrfs.so +usr/lib/libbtrfs.so.0 +usr/lib/libbtrfs.so.0.1 +#usr/lib/libbtrfsutil.a +#usr/lib/libbtrfsutil.so +usr/lib/libbtrfsutil.so.1 +usr/lib/libbtrfsutil.so.1.2.0 +#usr/lib/pkgconfig/libbtrfsutil.pc diff --git a/lfs/btrfs-progs b/lfs/btrfs-progs new file mode 100644 index 000000000..caf8f0b96 --- /dev/null +++ b/lfs/btrfs-progs @@ -0,0 +1,85 @@ +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2023 IPFire Team info@ipfire.org # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see http://www.gnu.org/licenses/. # +# # +############################################################################### + +############################################################################### +# Definitions +############################################################################### + +include Config + +VER = 6.7.1 + +THISAPP = btrfs-progs-v$(VER) +DL_FILE = $(THISAPP).tar.xz +DL_FROM = $(URL_IPFIRE) +DIR_APP = $(DIR_SRC)/$(THISAPP) +TARGET = $(DIR_INFO)/$(THISAPP) + +############################################################################### +# Top-level Rules +############################################################################### + +objects = $(DL_FILE) + +$(DL_FILE) = $(DL_FROM)/$(DL_FILE) + +$(DL_FILE)_BLAKE2 = 4e05e9dd80e5531425490970318389aef280f61cc636a80aa2bbc630399afd4f1f3ce649d194822ff93ff4b1774d65a504e3bed6f1426ff60830e4c0d0ac87b0 + +install : $(TARGET) + +check : $(patsubst %,$(DIR_CHK)/%,$(objects)) + +download :$(patsubst %,$(DIR_DL)/%,$(objects)) + +b2 : $(subst %,%_BLAKE2,$(objects)) + +dist: + @$(PAK) + +############################################################################### +# Downloading, checking, b2sum +############################################################################### + +$(patsubst %,$(DIR_CHK)/%,$(objects)) : + @$(CHECK) + +$(patsubst %,$(DIR_DL)/%,$(objects)) : + @$(LOAD) + +$(subst %,%_BLAKE2,$(objects)) : + @$(B2SUM) + +############################################################################### +# Installation Details +############################################################################### + +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) + @$(PREBUILD) + @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) + $(UPDATE_AUTOMAKE) + cd $(DIR_APP) && ./autogen.sh + cd $(DIR_APP) && ./configure \ + --prefix=/usr \ + --disable-documentation \ + --disable-python + cd $(DIR_APP) && make $(MAKETUNING) + cd $(DIR_APP) && make install + @rm -rf $(DIR_APP) + @$(POSTBUILD) diff --git a/make.sh b/make.sh index 64dbef5c4..3c0b9ef27 100755 --- a/make.sh +++ b/make.sh @@ -1712,6 +1712,7 @@ buildipfire() { lfsmake2 rsnapshot lfsmake2 mympd lfsmake2 wsdd + lfsmake2 btrfs-progs
# Kernelbuild ... current we have no platform that need # multi kernel builds so KCFG is empty
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/dracut-module/module-setup.sh | 4 ++-- src/installer/hw.c | 8 ++++++++ src/installer/hw.h | 1 + src/installer/main.c | 1 + 4 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/installer/dracut-module/module-setup.sh b/src/installer/dracut-module/module-setup.sh index 26a257cf8..09564f885 100755 --- a/src/installer/dracut-module/module-setup.sh +++ b/src/installer/dracut-module/module-setup.sh @@ -30,8 +30,8 @@ install() { instmods virtio_net hv_netvsc vmxnet3
# Filesystem support - inst_multiple parted mkswap mke2fs mkfs.xfs mkfs.vfat - instmods ext4 iso9660 vfat xfs ntfs3 + inst_multiple parted mkswap mke2fs mkfs.xfs mkfs.vfat mkfs.btrfs + instmods ext4 iso9660 vfat xfs ntfs3 btrfs
# Extraction inst_multiple tar gzip zstd diff --git a/src/installer/hw.c b/src/installer/hw.c index 894b887d9..4d214c152 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -822,6 +822,10 @@ static int hw_format_filesystem(const char* path, int fs, const char* output) { } else if (fs == HW_FS_XFS) { snprintf(cmd, sizeof(cmd), "/sbin/mkfs.xfs -f %s", path);
+ // BTRFS + } else if (fs == HW_FS_BTRFS) { + snprintf(cmd, sizeof(cmd), "/usr/bin/mkfs.btrfs -f %s", path); + // FAT32 } else if (fs == HW_FS_FAT32) { snprintf(cmd, sizeof(cmd), "/sbin/mkfs.vfat %s", path); @@ -882,6 +886,10 @@ int hw_mount_filesystems(struct hw_destination* dest, const char* prefix) { filesystem = "xfs"; break;
+ case HW_FS_BTRFS: + filesystem = "btrfs"; + break; + case HW_FS_FAT32: filesystem = "vfat"; break; diff --git a/src/installer/hw.h b/src/installer/hw.h index 6a7f23aa7..e5ee65a6d 100644 --- a/src/installer/hw.h +++ b/src/installer/hw.h @@ -46,6 +46,7 @@ #define HW_FS_EXT4_WO_JOURNAL 2 #define HW_FS_XFS 3 #define HW_FS_FAT32 4 +#define HW_FS_BTRFS 5
#define HW_FS_DEFAULT HW_FS_EXT4
diff --git a/src/installer/main.c b/src/installer/main.c index cddb0d91a..47daccdaa 100644 --- a/src/installer/main.c +++ b/src/installer/main.c @@ -720,6 +720,7 @@ int main(int argc, char *argv[]) { { HW_FS_EXT4, _("ext4 Filesystem") }, { HW_FS_EXT4_WO_JOURNAL, _("ext4 Filesystem without journal") }, { HW_FS_XFS, _("XFS Filesystem") }, + { HW_FS_BTRFS, _("BTRFS Filesystem (EXPERIMENTAL)") }, { 0, NULL }, }; unsigned int num_filesystems = sizeof(filesystems) / sizeof(*filesystems);
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- config/rootfiles/common/dracut | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/config/rootfiles/common/dracut b/config/rootfiles/common/dracut index d172898ee..b08b39a30 100644 --- a/config/rootfiles/common/dracut +++ b/config/rootfiles/common/dracut @@ -189,12 +189,12 @@ usr/lib/dracut/modules.d/50drm/module-setup.sh #usr/lib/dracut/modules.d/81cio_ignore #usr/lib/dracut/modules.d/81cio_ignore/module-setup.sh #usr/lib/dracut/modules.d/81cio_ignore/parse-cio_accept.sh -#usr/lib/dracut/modules.d/90btrfs -#usr/lib/dracut/modules.d/90btrfs/80-btrfs.rules -#usr/lib/dracut/modules.d/90btrfs/btrfs_device_ready.sh -#usr/lib/dracut/modules.d/90btrfs/btrfs_finished.sh -#usr/lib/dracut/modules.d/90btrfs/btrfs_timeout.sh -#usr/lib/dracut/modules.d/90btrfs/module-setup.sh +usr/lib/dracut/modules.d/90btrfs +usr/lib/dracut/modules.d/90btrfs/80-btrfs.rules +usr/lib/dracut/modules.d/90btrfs/btrfs_device_ready.sh +usr/lib/dracut/modules.d/90btrfs/btrfs_finished.sh +usr/lib/dracut/modules.d/90btrfs/btrfs_timeout.sh +usr/lib/dracut/modules.d/90btrfs/module-setup.sh #usr/lib/dracut/modules.d/90crypt #usr/lib/dracut/modules.d/90crypt/crypt-cleanup.sh #usr/lib/dracut/modules.d/90crypt/crypt-lib.sh
Ensure to always create the /boot directory during the mounting of the various created file systems. If the /boot directory does not exist some following mount operations could not be performed correctly and the installation/mounting will fail.
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 4d214c152..969c47508 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -904,10 +904,16 @@ int hw_mount_filesystems(struct hw_destination* dest, const char* prefix) { return r;
// boot - if (*dest->part_boot) { - snprintf(target, sizeof(target), "%s%s", prefix, HW_PATH_BOOT); - mkdir(target, S_IRWXU|S_IRWXG|S_IRWXO); + snprintf(target, sizeof(target), "%s%s", prefix, HW_PATH_BOOT); + r = mkdir(target, S_IRWXU|S_IRWXG|S_IRWXO); + + if (r) { + hw_umount_filesystems(dest, prefix);
+ return r; + } + + if (*dest->part_boot) { r = hw_mount(dest->part_boot, target, filesystem, 0); if (r) { hw_umount_filesystems(dest, prefix);
--- src/installer/hw.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 969c47508..11dbcd96d 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -563,7 +563,12 @@ static int hw_calculate_partition_table(struct hw* hw, struct hw_destination* de dest->size_bootldr = 0; }
- dest->size_boot = hw_boot_size(dest); + // Disable seperate boot partition for BTRFS installations. + if(dest->filesystem == HW_FS_BTRFS) { + dest->size_boot = 0; + } else { + dest->size_boot = hw_boot_size(dest); + }
// Create an EFI partition when running in EFI mode if (hw->efi)
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 80 ++++++++++++++++++++++++++++++++++++++++++++-- src/installer/hw.h | 20 ++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 11dbcd96d..8396d83cf 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -810,6 +810,7 @@ int hw_create_partitions(struct hw_destination* dest, const char* output) {
static int hw_format_filesystem(const char* path, int fs, const char* output) { char cmd[STRING_SIZE] = "\0"; + int r;
// Swap if (fs == HW_FS_SWAP) { @@ -829,7 +830,9 @@ static int hw_format_filesystem(const char* path, int fs, const char* output) {
// BTRFS } else if (fs == HW_FS_BTRFS) { - snprintf(cmd, sizeof(cmd), "/usr/bin/mkfs.btrfs -f %s", path); + r = hw_create_btrfs_layout(path, output); + + return r;
// FAT32 } else if (fs == HW_FS_FAT32) { @@ -838,7 +841,7 @@ static int hw_format_filesystem(const char* path, int fs, const char* output) {
assert(*cmd);
- int r = mysystem(output, cmd); + r = mysystem(output, cmd);
return r; } @@ -875,6 +878,59 @@ int hw_create_filesystems(struct hw_destination* dest, const char* output) { return 0; }
+int hw_create_btrfs_layout(const char* path, const char* output) { + const struct btrfs_subvolumes* subvolume = NULL; + char cmd[STRING_SIZE]; + char volume[STRING_SIZE]; + int r; + + r = snprintf(cmd, sizeof(cmd), "/usr/bin/mkfs.btrfs -f %s", path); + if (r < 0) { + return r; + } + + // Create the main BTRFS file system. + r = mysystem(output, cmd); + + if (r) { + return r; + } + + + // We need to mount the FS in order to create any subvolumes. + r = hw_mount(path, DESTINATION_MOUNT_PATH, "btrfs", 0); + + if (r) { + return r; + } + + // Loop through the list of subvolumes to create. + for ( subvolume = btrfs_subvolumes; subvolume->name; subvolume++ ) { + r = snprintf(volume, sizeof(volume), "%s", subvolume->name); + + // Abort if snprintf fails. + if (r < 0) { + return r; + } + + // Call function to create the subvolume + r = hw_create_btrfs_subvolume(output, volume); + + if (r) { + return r; + } + } + + // Umount the main BTRFS after subvolume creation. + r = hw_umount(DESTINATION_MOUNT_PATH, 0); + + if (r) { + return r; + } + + return 0; +} + int hw_mount_filesystems(struct hw_destination* dest, const char* prefix) { char target[STRING_SIZE];
@@ -1224,3 +1280,23 @@ int hw_restore_backup(const char* output, const char* backup_path, const char* d
return 0; } + +int hw_create_btrfs_subvolume(const char* output, const char* subvolume) { + char command [STRING_SIZE]; + int r; + + // Abort if the command could not be assigned. + r = snprintf(command, sizeof(command), "/usr/bin/btrfs subvolume create %s/%s", DESTINATION_MOUNT_PATH, subvolume); + if (r < 0) { + return r; + } + + // Create the subvolume + r = mysystem(output, command); + + if (r) { + return r; + } + + return 0; +} diff --git a/src/installer/hw.h b/src/installer/hw.h index e5ee65a6d..73a5233e2 100644 --- a/src/installer/hw.h +++ b/src/installer/hw.h @@ -104,6 +104,26 @@ struct hw_destination { unsigned long long size_root; };
+// Struct to define the BTRFS subvolumes layout +static const struct btrfs_subvolumes { + const char* name; + const char* mount_path; +} btrfs_subvolumes[] = { + { "@", "/" }, + { "@snapshots", "/.snapshots" }, + { "@home", "/home" }, + { "@root", "/root" }, + { "@cache", "/var/cache" }, + { "@backups", "/var/ipfire/backup" }, + { "@lib", "/var/lib" }, + { "@logs", "/var/log" }, + { "@mails", "/var/mail" }, + { "@tmp", "/var/tmp" }, + + // Sentinel + { NULL }, +}; + struct hw* hw_init(); void hw_free(struct hw* hw);
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 8396d83cf..3fa8b889e 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -1281,6 +1281,49 @@ int hw_restore_backup(const char* output, const char* backup_path, const char* d return 0; }
+int hw_mkdir(const char *dir) { + char tmp[STRING_SIZE]; + char *p = NULL; + size_t len; + int r; + + snprintf(tmp, sizeof(tmp),"%s",dir); + len = strlen(tmp); + + if (tmp[len - 1] == '/') { + tmp[len - 1] = 0; + } + + for (p = tmp + 1; *p; p++) { + if (*p == '/') { + *p = 0; + + // Create target if it does not exist + if (access(tmp, X_OK) != 0) { + r = mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO); + + if (r) { + return r; + } + } + + *p = '/'; + } + } + + // Create target if it does not exist + if (access(tmp, X_OK) != 0) { + r = mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO); + + if (r) { + return r; + } + } + + return 0; +} + + int hw_create_btrfs_subvolume(const char* output, const char* subvolume) { char command [STRING_SIZE]; int r;
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 2 ++ src/installer/main.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 3fa8b889e..ba6064cf5 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -44,6 +44,8 @@
#include "hw.h"
+extern FILE* flog; + static int system_chroot(const char* output, const char* path, const char* cmd) { char chroot_cmd[STRING_SIZE];
diff --git a/src/installer/main.c b/src/installer/main.c index 47daccdaa..30f02d8cb 100644 --- a/src/installer/main.c +++ b/src/installer/main.c @@ -29,6 +29,8 @@
extern char url[STRING_SIZE];
+FILE* flog = NULL; + static int newtChecklist(const char* title, const char* message, unsigned int width, unsigned int height, unsigned int num_entries, const char** entries, int* states) { @@ -377,7 +379,6 @@ int main(int argc, char *argv[]) { sethostname(DISTRO_SNAME, 10);
/* Log file/terminal stuff. */ - FILE* flog = NULL; if (argc >= 2) { logfile = argv[1];
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 57 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index ba6064cf5..8ee6c5726 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -935,6 +935,7 @@ int hw_create_btrfs_layout(const char* path, const char* output) {
int hw_mount_filesystems(struct hw_destination* dest, const char* prefix) { char target[STRING_SIZE]; + int r;
assert(*prefix == '/');
@@ -962,9 +963,17 @@ int hw_mount_filesystems(struct hw_destination* dest, const char* prefix) { }
// root - int r = hw_mount(dest->part_root, prefix, filesystem, 0); - if (r) - return r; + if (dest->filesystem == HW_FS_BTRFS) { + r = hw_mount_btrfs_subvolumes(dest->part_root); + + if (r) + return r; + } else { + r = hw_mount(dest->part_root, prefix, filesystem, 0); + + if (r) + return r; + }
// boot snprintf(target, sizeof(target), "%s%s", prefix, HW_PATH_BOOT); @@ -1028,6 +1037,48 @@ int hw_mount_filesystems(struct hw_destination* dest, const char* prefix) { return 0; }
+int hw_mount_btrfs_subvolumes(const char* source) { + const struct btrfs_subvolumes* subvolume = NULL; + char path[STRING_SIZE]; + char options[STRING_SIZE]; + int r; + + // Loop through the list of known subvolumes. + for ( subvolume = btrfs_subvolumes; subvolume->name; subvolume++ ) { + // Assign subvolume path. + r = snprintf(path, sizeof(path), "%s%s", DESTINATION_MOUNT_PATH, subvolume->mount_path); + + if (r < 0) { + return r; + } + + // Assign subvolume name. + r = snprintf(options, sizeof(options), "subvol=%s,", subvolume->name); + if (r < 0) { + return r; + } + + // Create the directory. + r = hw_mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO); + + // Abort if the directory could not be created. + if(r != 0 && errno != EEXIST) + return r; + + // Print log message + fprintf(flog, "Mounting subvolume %s to %s\n", subvolume->name, subvolume->mount_path); + + // Try to mount the subvolume. + r = mount(source, path, "btrfs", NULL, options); + + if (r) { + return r; + } + } + + return 0; +} + int hw_umount_filesystems(struct hw_destination* dest, const char* prefix) { int r; char target[STRING_SIZE];
As default we are using zstd for compression with level 1
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 2 +- src/installer/hw.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 8ee6c5726..5665cb955 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -1053,7 +1053,7 @@ int hw_mount_btrfs_subvolumes(const char* source) { }
// Assign subvolume name. - r = snprintf(options, sizeof(options), "subvol=%s,", subvolume->name); + r = snprintf(options, sizeof(options), "subvol=%s,%s", subvolume->name, BTRFS_MOUNT_OPTIONS); if (r < 0) { return r; } diff --git a/src/installer/hw.h b/src/installer/hw.h index 73a5233e2..7fbea86de 100644 --- a/src/installer/hw.h +++ b/src/installer/hw.h @@ -54,6 +54,8 @@
#define SERIAL_BAUDRATE 115200
+#define BTRFS_MOUNT_OPTIONS "compress=zstd:1" + #define BYTES2MB(x) ((x) / 1024 / 1024) #define MB2BYTES(x) ((unsigned long long)(x) * 1024 * 1024)
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 72 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 5665cb955..3b26920d1 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -1123,13 +1123,83 @@ int hw_umount_filesystems(struct hw_destination* dest, const char* prefix) { return -1;
// root - r = hw_umount(prefix, NULL); + if(dest->filesystem == HW_FS_BTRFS) { + r = hw_umount_btrfs_layout(); + } else { + r = hw_umount(prefix, NULL); + } + if (r) return -1;
return 0; }
+int hw_umount_btrfs_layout() { + const struct btrfs_subvolumes* subvolume = NULL; + char path[STRING_SIZE]; + int counter = 0; + int retry = 1; + int r; + + do { + // Reset the retry marker + retry = 0; + + // Loop through the list of subvolumes + for (subvolume = btrfs_subvolumes; subvolume->name; subvolume++) { + // Abort if the subvolume path could not be assigned. + r = snprintf(path, sizeof(path), "%s%s", DESTINATION_MOUNT_PATH, subvolume->mount_path); + + if (r < 0) { + return r; + } + + // Try to umount the subvolume. + r = umount2(path, 0); + + // Handle return codes. + if (r) { + switch(errno) { + case EBUSY: + // Set marker to retry the umount. + retry = 1; + + // Ignore if the subvolume could not be unmounted yet, + // because it is still used. + continue; + + case EINVAL: + // Ignore if the subvolume already has been unmounted + continue; + case ENOENT: + // Ignore if the directory does not longer exist. + continue; + default: + fprintf(flog, "Could not umount %s from %s - Error: %d\n", subvolume->name, path, r); + return r; + } + } + + // Print log message + fprintf(flog, "Umounted %s from %s\n", subvolume->name, path); + } + + // Abort loop if all mountpoins got umounted + if (retry == 0) { + return 0; + } + + // Abort after five failed umount attempts + if (counter == 5) { + return -1; + } + + // Increment counter. + counter++; + } while (1); +} + int hw_destroy_raid_superblocks(const struct hw_destination* dest, const char* output) { char cmd[STRING_SIZE];
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 3b26920d1..77789e35e 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -1319,11 +1319,13 @@ static char* hw_get_uuid(const char* dev) { #define FSTAB_FMT "UUID=%s %-8s %-4s %-10s %d %d\n"
int hw_write_fstab(struct hw_destination* dest) { + const struct btrfs_subvolumes* subvolume = NULL; FILE* f = fopen(DESTINATION_MOUNT_PATH "/etc/fstab", "w"); if (!f) return -1;
char* uuid = NULL; + char mount_options[STRING_SIZE];
// boot if (*dest->part_boot) { @@ -1359,7 +1361,22 @@ int hw_write_fstab(struct hw_destination* dest) { // root uuid = hw_get_uuid(dest->part_root); if (uuid) { - fprintf(f, FSTAB_FMT, uuid, "/", "auto", "defaults", 1, 1); + if(dest->filesystem == HW_FS_BTRFS) { + // Loop through the list of subvolumes + for (subvolume = btrfs_subvolumes; subvolume->name; subvolume++) { + // Abort if the mount options could not be assigned + int r = snprintf(mount_options, sizeof(mount_options), "defaults,%s,subvol=%s", BTRFS_MOUNT_OPTIONS, subvolume->name); + if (r < 0) { + return r; + } + + // Write the entry to the file + fprintf(f, FSTAB_FMT, uuid, subvolume->mount_path, "btrfs", mount_options, 1, 1); + } + } else { + fprintf(f, FSTAB_FMT, uuid, "/", "auto", "defaults", 1, 1); + } + free(uuid); }