nix-community / disko

Declarative disk partitioning and formatting using nix [maintainers=@Lassulus @Enzime]
MIT License
1.65k stars 181 forks source link

LUKS BTRFS swap subvolume ignoring mountOptions #493

Closed zambetti closed 8 months ago

zambetti commented 8 months ago

The disk configuration below does successfully run, but when verifying the result with mount the swap subvolume does not respect the mountOptions in the configuration ("nodatacow" "nodatasum" and no compression).

Might anyone be able to shed light on this? Does this seem like a reasonable approach overall?

[root@nixos:~]# mount | grep /mnt
overlay on /nix/store type overlay (rw,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/store,workdir=/mnt-root/nix/.rw-store/work)
overlay on /nix/store type overlay (ro,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/store,workdir=/mnt-root/nix/.rw-store/work)
/dev/mapper/system on /mnt type btrfs (rw,noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=256,subvol=/@)
/dev/nvme1n1p1 on /mnt/boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
/dev/mapper/system on /mnt/home type btrfs (rw,noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=257,subvol=/@/home)
/dev/mapper/system on /mnt/nix type btrfs (rw,noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=259,subvol=/@/nix)
/dev/mapper/system on /mnt/swap type btrfs (rw,noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=260,subvol=/@/swap)
{
  disko.devices =
  {
    disk =
    {
      nvme1n1 =
      {
        type = "disk";
        device = "/dev/nvme1n1";
        content =
        {
          type = "gpt";
          partitions =
          {
            boot =
            {
              size = "1G";
              type = "EF00";
              content =
              {
                type = "filesystem";
                format = "vfat";
                mountpoint = "/boot";
                mountOptions = ["defaults"];
              };
            };
            system =
            {
              size = "100%";
              content =
              {
                type = "luks";
                name = "system";
                askPassword = true;
                settings.allowDiscards = true;
                content =
                {
                  type = "btrfs";
                  extraArgs = ["-f"]; # Override existing partition
                  subvolumes =
                  {
                    "@/" =
                    {
                      mountpoint = "/";
                      mountOptions = ["noatime" "compress=zstd:1" "discard=async"];
                    };
                    "@/home" =
                    {
                      mountpoint = "/home";
                      mountOptions = ["noatime" "compress=zstd:1" "discard=async"];
                    };
                    "@/nix" =
                    {
                      mountpoint = "/nix";
                      mountOptions = ["noatime" "compress=zstd:1" "discard=async"];
                    };
                    "@/swap" =
                    {
                      mountpoint = "/swap";
                      mountOptions = ["noatime" "nodatacow" "nodatasum" "discard=async"];
                      swap =
                      {
                        swap-0.size = "38G";
                        swap-0.path = "swap-0";
                      };
                    };
                  };
                };
              };
            };
          };
        };
      };
    };
  };
}
JorgeMPG commented 8 months ago

My understanding from reading the archlinux wiki is that subvolumes cannot be mounted with different cow on the same file system: https://wiki.archlinux.org/title/btrfs It is also mentioned in btrfs documentations (https://btrfs.readthedocs.io/en/latest/Administration.html):

Most mount options apply to the whole filesystem and only options in the first mounted subvolume will take effect. This is due to lack of implementation and may change in the future. This means that (for example) you can’t set per-subvolume nodatacow, nodatasum, or compress using mount options. This should eventually be fixed, but it has proved to be difficult to implement correctly within the Linux VFS framework.

In this case a workaround may be to explicitly set nodatacow as attribute for the folder, such as chattr +C /swap. Perhaps this can be automated inside disko with a post-hook or similar.

zambetti commented 8 months ago

Thank you for pointing me in the right direction; the documentation that you pointed me to helped a lot.

After getting a bit further with the installation, despite the subvolume /swap being mounted with compression and COW enabled, the swap file itself is configured correctly (without COW and without compression). I suppose this is because disko calls btrfs filesystem mkswapfile and that configures the swapfile as it should be.

All seems to be working perfectly.

$ mount | grep swap
/dev/mapper/system on /swap type btrfs (rw,noatime,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=260,subvol=/@swap)
# lsattr -l /swap/swapfile-0
/swap/swapfile-0             No_COW
$ swapon
NAME             TYPE SIZE USED PRIO
/swap/swapfile-0 file  38G   0B   -2
Mic92 commented 8 months ago

Ok. So this is one is solved, right?