From 986445f05604def9f0483622e0f5772c508c23d1 Mon Sep 17 00:00:00 2001 From: Kira Bruneau Date: Fri, 17 Jan 2025 14:18:51 -0500 Subject: [PATCH] install-grub.pl: support bindmounts Specifically this allows bind-mounting your `/boot` directory with NixOS impermanence. --- .../modules/system/boot/loader/grub/grub.nix | 3 +- .../system/boot/loader/grub/install-grub.pl | 34 +++---------------- 2 files changed, 5 insertions(+), 32 deletions(-) diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 81f94e8639d9d..f1a352867016b 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -90,7 +90,7 @@ let timeoutStyle ; path = with pkgs; makeBinPath ( - [ coreutils gnused gnugrep findutils diffutils btrfs-progs util-linux mdadm ] + [ coreutils gnused gnugrep findutils diffutils util-linux mdadm ] ++ optional cfg.efiSupport efibootmgr ++ optionals cfg.useOSProber [ busybox os-prober ]); font = lib.optionalString (cfg.font != null) ( @@ -730,7 +730,6 @@ in install-grub-pl = pkgs.substituteAll { src = ./install-grub.pl; utillinux = pkgs.util-linux; - btrfsprogs = pkgs.btrfs-progs; inherit (config.system.nixos) distroName; }; perl = pkgs.perl.withPackages (p: with p; [ diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index c3652e8835117..71a9c5e1cff02 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -110,6 +110,7 @@ sub runCommand { # Discover information about the location of the bootPath struct(Fs => { device => '$', + root => '$', type => '$', mount => '$', }); @@ -117,12 +118,12 @@ sub runCommand { # Figure out what filesystem is used for the directory with init/initrd/kernel files sub GetFs { my ($dir) = @_; - my ($status, @pathInfo) = runCommand("@utillinux@/bin/findmnt", "-n", "-v", "-o", "SOURCE,FSTYPE,TARGET", "-T", @{[$dir]}); + my ($status, @pathInfo) = runCommand("@utillinux@/bin/findmnt", "-n", "-u", "-v", "-o", "SOURCE,FSROOT,FSTYPE,TARGET", "-T", @{[$dir]}); if ($status != 0 || @pathInfo != 1) { die "Failed to get file system (returned $status) for @{[$dir]}"; } my @fields = split /\s+/, $pathInfo[0]; - return Fs->new(device => $fields[0], type => $fields[1], mount => $fields[2]); + return Fs->new(device => $fields[0], root => $fields[1], type => $fields[2], mount => $fields[3]); } struct (Grub => { path => '$', @@ -132,10 +133,7 @@ sub GetFs { sub GrubFs { my ($dir) = @_; my $fs = GetFs($dir); - my $path = substr($dir, length($fs->mount)); - if (substr($path, 0, 1) ne "/") { - $path = "/$path"; - } + my $path = File::Spec->catdir($fs->root, substr($dir, length($fs->mount))); my $search = ""; # ZFS is completely separate logic as zpools are always identified by a label @@ -177,30 +175,6 @@ sub GrubFs { } $search .= $matches[0]; } - - # BTRFS is a special case in that we need to fix the referenced path based on subvolumes - if ($fs->type eq 'btrfs') { - my ($status, @id_info) = runCommand("@btrfsprogs@/bin/btrfs", "subvol", "show", @{[$fs->mount]}); - if ($status != 0) { - die "Failed to retrieve subvolume info for @{[$fs->mount]}\n"; - } - my @ids = join("\n", @id_info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s; - if ($#ids > 0) { - die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n" - } elsif ($#ids == 0) { - my ($status, @path_info) = runCommand("@btrfsprogs@/bin/btrfs", "subvol", "list", @{[$fs->mount]}); - if ($status != 0) { - die "Failed to find @{[$fs->mount]} subvolume id from btrfs\n"; - } - my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/; - if ($#paths > 0) { - die "Btrfs returned multiple paths for a single subvolume id, mountpoint @{[$fs->mount]}\n"; - } elsif ($#paths != 0) { - die "Btrfs did not return a path for the subvolume at @{[$fs->mount]}\n"; - } - $path = "/$paths[0]$path"; - } - } } if (not $search eq "") { $search = "search --set=drive$driveid " . $search;