diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index 7d0c5898e23d..064d01d05c0c 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -273,6 +273,7 @@ foreach my $path (glob "/sys/class/{block,mmc_host}/*") { # Add bcache module, if needed. my @bcacheDevices = glob("/dev/bcache*"); +@bcacheDevices = grep(!qr#dev/bcachefs.*#, @bcacheDevices); if (scalar @bcacheDevices > 0) { push @initrdAvailableKernelModules, "bcache"; } @@ -483,6 +484,19 @@ EOF # boot.tmp.useTmpfs option in configuration.nix (managed declaratively). next if ($mountPoint eq "/tmp" && $fsType eq "tmpfs"); + # This should work for single and multi-device systems. + # still needs subvolume support + if ($fsType eq "bcachefs") { + my ($status, @info) = runCommand("bcachefs fs usage $rootDir$mountPoint"); + my $UUID = $info[0]; + + if ($status == 0 && $UUID =~ /^Filesystem:[ \t\n]*([0-9a-z-]+)/) { + $stableDevPath = "UUID=$1"; + } else { + print STDERR "warning: can't find bcachefs mount UUID falling back to device-path"; + } + } + # Emit the filesystem. $fileSystems .= < $out/bin/mount.bcachefs < /dev/null 2> /dev/null; then # test for encryption prompt $name until bcachefs unlock $path 2> /dev/null; do # repeat until successfully unlocked @@ -30,6 +46,8 @@ let prompt $name done printf "unlocking successful.\n" + else + echo "Cannot unlock device $uuid with path $path" >&2 fi } ''; @@ -51,28 +69,25 @@ in { config = mkIf (elem "bcachefs" config.boot.supportedFilesystems) (mkMerge [ { - # We do not want to include bachefs in the fsPackages for systemd-initrd - # because we provide the unwrapped version of mount.bcachefs - # through the extraBin option, which will make it available for use. - system.fsPackages = lib.optional (!config.boot.initrd.systemd.enable) pkgs.bcachefs-tools; - environment.systemPackages = lib.optional (config.boot.initrd.systemd.enable) pkgs.bcachefs-tools; + # needed for systemd-remount-fs + system.fsPackages = [ pkgs.bcachefs-tools ]; # use kernel package with bcachefs support until it's in mainline + # TODO replace with requireKernelConfig boot.kernelPackages = pkgs.linuxPackages_testing_bcachefs; } (mkIf ((elem "bcachefs" config.boot.initrd.supportedFilesystems) || (bootFs != {})) { # chacha20 and poly1305 are required only for decryption attempts boot.initrd.availableKernelModules = [ "bcachefs" "sha256" "chacha20" "poly1305" ]; - boot.initrd.systemd.extraBin = { + # do we need this? boot/systemd.nix:566 & boot/systemd/initrd.nix:357 "bcachefs" = "${pkgs.bcachefs-tools}/bin/bcachefs"; - "mount.bcachefs" = "${mountCommand}/bin/mount.bcachefs"; + "mount.bcachefs" = "${pkgs.bcachefs-tools}/bin/mount.bcachefs"; }; - boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.bcachefs-tools}/bin/bcachefs - copy_bin_and_libs ${mountCommand}/bin/mount.bcachefs + copy_bin_and_libs ${pkgs.bcachefs-tools}/bin/mount.bcachefs ''; boot.initrd.extraUtilsCommandsTest = '' $out/bin/bcachefs version diff --git a/pkgs/os-specific/linux/kernel/bcachefs.json b/pkgs/os-specific/linux/kernel/bcachefs.json new file mode 100644 index 000000000000..09f7ea2febaa --- /dev/null +++ b/pkgs/os-specific/linux/kernel/bcachefs.json @@ -0,0 +1,5 @@ +{ + "diffHash": "sha256-BmXd/5Hn/xr7gNFp6BsBMG2XeKFlPGxv66IQ8DEwh5k=", + "commit": "4d2faeb4fb58c389dc9f76b8d5ae991ef4497e04", + "date": "2023-09-28" +} diff --git a/pkgs/os-specific/linux/kernel/linux-testing-bcachefs.nix b/pkgs/os-specific/linux/kernel/linux-testing-bcachefs.nix index 3602b03b4b6e..e0fb6c7c4e0c 100644 --- a/pkgs/os-specific/linux/kernel/linux-testing-bcachefs.nix +++ b/pkgs/os-specific/linux/kernel/linux-testing-bcachefs.nix @@ -2,12 +2,10 @@ , stdenv , fetchpatch , kernel -, commitDate ? "2023-06-28" # bcachefs-tools stores the expected-revision in: # https://evilpiepirate.org/git/bcachefs-tools.git/tree/.bcachefs_revision # but this does not means that it'll be the latest-compatible revision -, currentCommit ? "84f132d5696138bb038d2dc8f1162d2fab5ac832" -, diffHash ? "sha256-RaBWBU7rXjJFb1euFAFBHWCBQAG7npaCodjp/vMYpyw=" +, version ? lib.importJSON ./bcachefs.json , kernelPatches # must always be defined in bcachefs' all-packages.nix entry because it's also a top-level attribute supplied by callPackage , argsOverride ? {} , ... @@ -15,7 +13,7 @@ # NOTE: bcachefs-tools should be updated simultaneously to preserve compatibility (kernel.override ( args // { - version = "${kernel.version}-bcachefs-unstable-${commitDate}"; + version = "${kernel.version}-bcachefs-unstable-${version.date}"; extraMeta = { branch = "master"; @@ -32,12 +30,12 @@ }; kernelPatches = [ { - name = "bcachefs-${currentCommit}"; + name = "bcachefs-${version.commit}"; patch = fetchpatch { - name = "bcachefs-${currentCommit}.diff"; - url = "https://evilpiepirate.org/git/bcachefs.git/rawdiff/?id=${currentCommit}&id2=v${lib.versions.majorMinor kernel.version}"; - sha256 = diffHash; + name = "bcachefs-${version.commit}.diff"; + url = "https://evilpiepirate.org/git/bcachefs.git/rawdiff/?id=${version.commit}&id2=v${lib.versions.majorMinor kernel.version}"; + sha256 = version.diffHash; }; } ] ++ kernelPatches; })) diff --git a/pkgs/os-specific/linux/util-linux/bcachefs-patch-set.patch b/pkgs/os-specific/linux/util-linux/bcachefs-patch-set.patch new file mode 100644 index 000000000000..068744d4f32d --- /dev/null +++ b/pkgs/os-specific/linux/util-linux/bcachefs-patch-set.patch @@ -0,0 +1,277 @@ +commit 68564ebb50f8afab5a9527c534417e247cca0b27 +Author: Filipe Manana +Date: Thu Aug 17 10:20:13 2023 +0100 + + libmount: Fix regression when mounting with atime + + A regression was introduced in v2.39 that causes mounting with the atime + option to fail: + + $ mkfs.ext4 -F /dev/sdi + $ mount -o atime /dev/sdi /mnt/sdi + mount: /mnt/sdi: not mount point or bad option. + dmesg(1) may have more information after failed mount system call. + + The failure comes from the mount_setattr(2) call returning -EINVAL. This + is because we pass an invalid value for the attr_clr argument. From a + strace capture we have: + + mount_setattr(4, "", AT_EMPTY_PATH, {attr_set=0, attr_clr=MOUNT_ATTR_NOATIME, propagation=0 /* MS_??? */, userns_fd=0}, 32) = -1 EINVAL (Invalid argument) + + We can't pass MOUNT_ATTR_NOATIME to mount_setattr(2) through the attr_clr + argument because all atime options are exclusive, so in order to set atime + one has to pass MOUNT_ATTR__ATIME to attr_clr and leave attr_set as + MOUNT_ATTR_RELATIME (which is defined as a value of 0). + + This can be read from the man page for mount_setattr(2) and also from the + kernel source: + + $ cat fs/namespace.c + static int build_mount_kattr(const struct mount_attr *attr, size_t usize, + struct mount_kattr *kattr, unsigned int flags) + { + (...) + /* + * Since the MOUNT_ATTR_ values are an enum, not a bitmap, + * users wanting to transition to a different atime setting cannot + * simply specify the atime setting in @attr_set, but must also + * specify MOUNT_ATTR__ATIME in the @attr_clr field. + * So ensure that MOUNT_ATTR__ATIME can't be partially set in + * @attr_clr and that @attr_set can't have any atime bits set if + * MOUNT_ATTR__ATIME isn't set in @attr_clr. + */ + if (attr->attr_clr & MOUNT_ATTR__ATIME) { + if ((attr->attr_clr & MOUNT_ATTR__ATIME) != MOUNT_ATTR__ATIME) + return -EINVAL; + + /* + * Clear all previous time settings as they are mutually + * exclusive. + */ + kattr->attr_clr |= MNT_RELATIME | MNT_NOATIME; + switch (attr->attr_set & MOUNT_ATTR__ATIME) { + case MOUNT_ATTR_RELATIME: + kattr->attr_set |= MNT_RELATIME; + break; + case MOUNT_ATTR_NOATIME: + kattr->attr_set |= MNT_NOATIME; + break; + case MOUNT_ATTR_STRICTATIME: + break; + default: + return -EINVAL; + } + (...) + + So fix this by setting attr_clr MOUNT_ATTR__ATIME if we want to clear any + atime related option. + + Signed-off-by: Filipe Manana + +diff --git a/libmount/src/optlist.c b/libmount/src/optlist.c +index 1e962ec6d..0702adae7 100644 +--- a/libmount/src/optlist.c ++++ b/libmount/src/optlist.c +@@ -875,7 +875,18 @@ int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *cl + + if (opt->ent->mask & MNT_INVERT) { + DBG(OPTLIST, ul_debugobj(ls, " clr: %s", opt->ent->name)); +- *clr |= x; ++ /* ++ * All atime settings are mutually exclusive so *clr must ++ * have MOUNT_ATTR__ATIME set. ++ * ++ * See the function fs/namespace.c:build_mount_kattr() ++ * in the linux kernel source. ++ */ ++ if (x == MOUNT_ATTR_RELATIME || x == MOUNT_ATTR_NOATIME || ++ x == MOUNT_ATTR_STRICTATIME) ++ *clr |= MOUNT_ATTR__ATIME; ++ else ++ *clr |= x; + } else { + DBG(OPTLIST, ul_debugobj(ls, " set: %s", opt->ent->name)); + *set |= x; +diff --git a/tests/expected/libmount/context-mount-flags b/tests/expected/libmount/context-mount-flags +index 960641863..eb71323dd 100644 +--- a/tests/expected/libmount/context-mount-flags ++++ b/tests/expected/libmount/context-mount-flags +@@ -3,3 +3,6 @@ ro,nosuid,noexec + successfully mounted + rw,nosuid,noexec + successfully umounted ++successfully mounted ++rw,relatime ++successfully umounted +diff --git a/tests/ts/libmount/context b/tests/ts/libmount/context +index f5b47185e..a5d2e81a3 100755 +--- a/tests/ts/libmount/context ++++ b/tests/ts/libmount/context +@@ -116,8 +116,15 @@ $TS_CMD_FINDMNT --kernel --mountpoint $MOUNTPOINT -o VFS-OPTIONS -n >> $TS_OUTPU + + ts_run $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>> $TS_ERRLOG + is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>> $TS_ERRLOG +-ts_finalize_subtest + ++# Test that the atime option works after the migration to use the new kernel mount APIs. ++ts_run $TESTPROG --mount -o atime $DEVICE $MOUNTPOINT >> $TS_OUTPUT 2>> $TS_ERRLOG ++$TS_CMD_FINDMNT --kernel --mountpoint $MOUNTPOINT -o VFS-OPTIONS -n >> $TS_OUTPUT 2>> $TS_ERRLOG ++is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>> $TS_ERRLOG ++ts_run $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>> $TS_ERRLOG ++is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>> $TS_ERRLOG ++ ++ts_finalize_subtest + + ts_init_subtest "mount-loopdev" + mkdir -p $MOUNTPOINT &> /dev/null + +commit 1ec71634aa4ef5ddca23d65c8a296f3614231e8a +Author: Colin Gillespie +Date: Wed Aug 9 18:28:07 2023 +1000 + + libblkid: (bcachefs) fix not detecting large superblocks + + Probing does not detect bcachefs filesystems with a superblock larger + than 4KiB. Bcachefs superblocks grow in size and can become much larger + than this. + + Increase the superblock maximum size limit to 1MiB. + + Validate the superblock isn't larger than the maximum size defined in + the superblocks layout section. + + (cherry picked from commit 48d573797797650d96456979797c0155d58f61cb) + +diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c +index 40e702d75..236877042 100644 +--- a/libblkid/src/superblocks/bcache.c ++++ b/libblkid/src/superblocks/bcache.c +@@ -102,6 +102,15 @@ union bcachefs_sb_csum { + uint8_t raw[16]; + } __attribute__((packed)); + ++struct bcachefs_sb_layout { ++ uint8_t magic[16]; ++ uint8_t layout_type; ++ uint8_t sb_max_size_bits; ++ uint8_t nr_superblocks; ++ uint8_t pad[5]; ++ uint64_t sb_offset[61]; ++} __attribute__((packed)); ++ + struct bcachefs_super_block { + union bcachefs_sb_csum csum; + uint16_t version; +@@ -123,7 +132,7 @@ struct bcachefs_super_block { + uint64_t flags[8]; + uint64_t features[2]; + uint64_t compat[2]; +- uint8_t layout[512]; ++ struct bcachefs_sb_layout layout; + struct bcachefs_sb_field _start[]; + } __attribute__((packed)); + +@@ -143,7 +152,7 @@ struct bcachefs_super_block { + /* granularity of offset and length fields within superblock */ + #define BCACHEFS_SECTOR_SIZE 512 + /* maximum superblock size */ +-#define BCACHEFS_SB_MAX_SIZE 4096 ++#define BCACHEFS_SB_MAX_SIZE 0x100000 + /* fields offset within super block */ + #define BCACHEFS_SB_FIELDS_OFF offsetof(struct bcachefs_super_block, _start) + /* tag value for members field */ +@@ -302,6 +311,9 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag) + return BLKID_PROBE_NONE; + + sb_size = BCACHEFS_SB_FIELDS_OFF + BYTES(bcs); ++ if (sb_size > BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits) ++ return BLKID_PROBE_NONE; ++ + if (sb_size > BCACHEFS_SB_MAX_SIZE) + return BLKID_PROBE_NONE; + + +commit acbf17ae8f8ee0f941fe98ed12f115f2b349bba8 +Author: Karel Zak +Date: Wed Aug 23 11:53:45 2023 +0200 + + libblkid: (bcachefs) fix compiler warning [-Werror=sign-compare] + + Addresses: https://github.com/util-linux/util-linux/pull/2427 + Signed-off-by: Karel Zak + (cherry picked from commit 17873d38fc97913c0a31d4bd08cfbfe45c4de5be) + +diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c +index 236877042..6ab3fe9d4 100644 +--- a/libblkid/src/superblocks/bcache.c ++++ b/libblkid/src/superblocks/bcache.c +@@ -311,7 +311,7 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag) + return BLKID_PROBE_NONE; + + sb_size = BCACHEFS_SB_FIELDS_OFF + BYTES(bcs); +- if (sb_size > BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits) ++ if (sb_size > ((uint64_t) BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits)) + return BLKID_PROBE_NONE; + + if (sb_size > BCACHEFS_SB_MAX_SIZE) + +commit 6b9fda87c4e5d0c6f945d7565197f157b9fa3d5f +Author: Thomas Weißschuh +Date: Wed Aug 23 11:58:33 2023 +0200 + + libblkid: (bcachefs) fix size validation + + Avoid signed shift out-of-bounds. + + Also mark the constants explitly as unsigned instead of casting. + + Signed-off-by: Thomas Weißschuh + (cherry picked from commit befe455f59de8c7bc66b85ed52aae8cbc95325fa) + +diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c +index 6ab3fe9d4..28ac4b52b 100644 +--- a/libblkid/src/superblocks/bcache.c ++++ b/libblkid/src/superblocks/bcache.c +@@ -142,17 +142,19 @@ struct bcachefs_super_block { + /* magic string len */ + #define BCACHE_SB_MAGIC_LEN (sizeof(BCACHE_SB_MAGIC) - 1) + /* super block offset */ +-#define BCACHE_SB_OFF 0x1000 ++#define BCACHE_SB_OFF 0x1000U + /* supper block offset in kB */ + #define BCACHE_SB_KBOFF (BCACHE_SB_OFF >> 10) + /* magic string offset within super block */ + #define BCACHE_SB_MAGIC_OFF offsetof(struct bcache_super_block, magic) + /* start of checksummed data within superblock */ +-#define BCACHE_SB_CSUMMED_START 8 ++#define BCACHE_SB_CSUMMED_START 8U + /* granularity of offset and length fields within superblock */ +-#define BCACHEFS_SECTOR_SIZE 512 ++#define BCACHEFS_SECTOR_SIZE 512U ++/* maximum superblock size shift */ ++#define BCACHEFS_SB_MAX_SIZE_SHIFT 0x10U + /* maximum superblock size */ +-#define BCACHEFS_SB_MAX_SIZE 0x100000 ++#define BCACHEFS_SB_MAX_SIZE (1U << BCACHEFS_SB_MAX_SIZE_SHIFT) + /* fields offset within super block */ + #define BCACHEFS_SB_FIELDS_OFF offsetof(struct bcachefs_super_block, _start) + /* tag value for members field */ +@@ -311,12 +313,16 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag) + return BLKID_PROBE_NONE; + + sb_size = BCACHEFS_SB_FIELDS_OFF + BYTES(bcs); +- if (sb_size > ((uint64_t) BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits)) +- return BLKID_PROBE_NONE; + + if (sb_size > BCACHEFS_SB_MAX_SIZE) + return BLKID_PROBE_NONE; + ++ if (bcs->layout.sb_max_size_bits > BCACHEFS_SB_MAX_SIZE_SHIFT) ++ return BLKID_PROBE_NONE; ++ ++ if (sb_size > (BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits)) ++ return BLKID_PROBE_NONE; ++ + sb = blkid_probe_get_sb_buffer(pr, mag, sb_size); + if (!sb) + return BLKID_PROBE_NONE; diff --git a/pkgs/os-specific/linux/util-linux/default.nix b/pkgs/os-specific/linux/util-linux/default.nix index 45c0d57cbff4..d710fabb7ace 100644 --- a/pkgs/os-specific/linux/util-linux/default.nix +++ b/pkgs/os-specific/linux/util-linux/default.nix @@ -29,6 +29,7 @@ stdenv.mkDerivation rec { patches = [ ./rtcwake-search-PATH-for-shutdown.patch + ./bcachefs-patch-set.patch ]; # We separate some of the utilities into their own outputs. This diff --git a/pkgs/tools/filesystems/bcachefs-tools/default.nix b/pkgs/tools/filesystems/bcachefs-tools/default.nix index 2c54d4be6147..a121a2c6d93a 100644 --- a/pkgs/tools/filesystems/bcachefs-tools/default.nix +++ b/pkgs/tools/filesystems/bcachefs-tools/default.nix @@ -16,23 +16,16 @@ , fuse3 , cargo , rustc -, coreutils , rustPlatform , makeWrapper , fuseSupport ? false +, version ? lib.importJSON ./version.json }: -let - rev = "cfa816bf3f823a3bedfedd8e214ea929c5c755fe"; -in stdenv.mkDerivation { +stdenv.mkDerivation { pname = "bcachefs-tools"; - version = "unstable-2023-06-28"; + version = "unstable-${version.date}"; - src = fetchFromGitHub { - owner = "koverstreet"; - repo = "bcachefs-tools"; - inherit rev; - hash = "sha256-XgXUwyZV5N8buYTuiu1Y1ZU3uHXjZ/OZ1kbZ9d6Rt5I="; - }; + src = fetchFromGitHub (builtins.removeAttrs version ["date"]); nativeBuildInputs = [ pkg-config @@ -70,11 +63,11 @@ in stdenv.mkDerivation { makeFlags = [ "PREFIX=${placeholder "out"}" - "VERSION=${lib.strings.substring 0 7 rev}" + "VERSION=${lib.strings.substring 0 7 version.rev}" "INITRAMFS_DIR=${placeholder "out"}/etc/initramfs-tools" ]; - preCheck = lib.optionalString fuseSupport '' + preCheck = lib.optionalString (!fuseSupport) '' rm tests/test_fuse.py ''; @@ -83,11 +76,6 @@ in stdenv.mkDerivation { inherit (nixosTests.installer) bcachefsSimple bcachefsEncrypted bcachefsMulti; }; - postFixup = '' - wrapProgram $out/bin/mount.bcachefs \ - --prefix PATH : ${lib.makeBinPath [ coreutils ]} - ''; - enableParallelBuilding = true; meta = with lib; { diff --git a/pkgs/tools/filesystems/bcachefs-tools/version.json b/pkgs/tools/filesystems/bcachefs-tools/version.json new file mode 100644 index 000000000000..061fdcdbac67 --- /dev/null +++ b/pkgs/tools/filesystems/bcachefs-tools/version.json @@ -0,0 +1,7 @@ +{ + "owner": "koverstreet", + "repo": "bcachefs-tools", + "rev": "6b175a022496572416918bd38d083120c23ba5f2", + "sha256": "qC6Bq2zdO8Tj+bZbIUvcVBqvuKccqDEX3HIeOXsEloQ=", + "date": "2023-09-29" +} diff --git a/pkgs/top-level/linux-kernels.nix b/pkgs/top-level/linux-kernels.nix index 7b746286f055..7d9061ac43b8 100644 --- a/pkgs/top-level/linux-kernels.nix +++ b/pkgs/top-level/linux-kernels.nix @@ -218,8 +218,8 @@ in { linux_testing_bcachefs = callPackage ../os-specific/linux/kernel/linux-testing-bcachefs.nix { # Pinned on the last version which Kent's commits can be cleany rebased up. - kernel = linux_6_4; - kernelPatches = linux_6_4.kernelPatches; + kernel = linux_6_5; + kernelPatches = linux_6_5.kernelPatches; }; linux_hardkernel_4_14 = callPackage ../os-specific/linux/kernel/linux-hardkernel-4.14.nix {