Compare commits

...

312 Commits

Author SHA1 Message Date
Thomas Mühlbacher
33483738c6 fix: use cargo workspace
This way bch_bindgen actually gets used by various cargo subcommands,
like clippy.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-31 12:54:52 -04:00
Thomas Mühlbacher
ea5bdadabd chore(nix): structure github CI nix flake checks
Makes it way easier to identify CI failures for people who try to use
github for contributions.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-31 12:54:46 -04:00
Integral
66c943be6c bcachefs-tools: add fs_usage & return -EINVAL when no matching subcommand
Add the missing usage function for "fs" subcommand; when no matching
subcommand exists, print the usage and return -EINVAL.

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-31 12:51:18 -04:00
Kent Overstreet
3d968816a4 Update bcachefs sources to 7fdc3fa3cb5f bcachefs: Log original key being moved in data updates 2025-03-30 18:27:52 -04:00
Kent Overstreet
76b3ec9d66 list_journal: fix transaction filter extent matching
Giving a single pos for the transaction filter now correctly matches
against extents.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-30 18:27:52 -04:00
Kent Overstreet
3e2d5b2b9a Update bcachefs sources to 0a2abe7ce837 bcachefs: Don't use designated initializers for disk_accounting_pos
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-29 21:50:53 -04:00
Kent Overstreet
7c47145f6c cmd_fs_usage: Fix kernel version check
This needed an access() check, like the other uses, instead of exiting
if it can't be read.

Factor out a small common helper for this.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-28 11:38:55 -04:00
Integral
396545c2ea bcachefs-tools: hide FUSE in usage when BCACHEFS_FUSE disabled
When BCACHEFS_FUSE is disabled or not defined, FUSE section shouldn't
be displayed in bcachefs usage (--help).

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-28 11:12:32 -04:00
Integral
3bfe433d22 bcachefs-tools: make targets of subvolume create/delete required
Currently, when no targets are provided for "bcachefs subvolume create" or
"bcachefs subvolume delete", it will exit silently with code 0. Make targets
(arguments) required to solve this problem.

This patch solves issue https://github.com/koverstreet/bcachefs/issues/766.

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-27 13:58:21 -04:00
Kent Overstreet
19d3a1778c fsck: Kill -R, --reconstruct_alloc
We don't want users hitting this accidentally, and if needed for some
strange reason (it shouldn't be), it can still be specified via -o.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-26 10:15:26 -04:00
Integral
e54f288992 bcachefs-tools: fix build failure by fixing of C header filename
C header filename in `c_src/cmd_fusemount.c` hasn't been updated after renaming
`libbcachefs/fs-common.h`. Updating the filename to fix build failure.

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-26 09:41:11 -04:00
Kent Overstreet
7c66e9fac5 migrate_superblock: make sure we remove old superblock
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-26 09:39:59 -04:00
Kent Overstreet
2160e9a7bd format: fix minimum bucket nr check 2025-03-25 16:47:50 -04:00
Kent Overstreet
941dfd7a29 mount: Parse bcachefs options, and pass them to mount helper
This fixes the migrate test - we need to handle the sb=# option.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-25 16:37:26 -04:00
Kent Overstreet
18b4914587 rust binding for parse_mount_opts()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-25 16:37:26 -04:00
Kent Overstreet
8af5c93e48 Update bcachefs sources to 1392e502d48b bcachefs: Add an "ignore unknown" option to bch2_parse_mount_opts()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-25 16:37:24 -04:00
Kent Overstreet
6657ce2de3 Migrate tool fixes
Migrate now works: there is an inconsequential free space inconsistency
after marking the new superblock (in migrate_superblock), which we're
hacking around with a fsck.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-24 17:46:23 -04:00
Kent Overstreet
5504533986 format: kill min_size()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-23 12:41:35 -04:00
Kent Overstreet
a55c655158 format: Redo bucket size calculations
bucket size now takes into account system memory and amount of memory
required to fsck: on very large filesystems it will automatically scale
up bucket size to ensure we can fsck.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-23 11:52:54 -04:00
Kent Overstreet
b8435c5693 bch2_format() now takes a darray of dev_opts
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-23 11:03:42 -04:00
Thomas Mühlbacher
80d0a21ed3 chore(nix): rm unused attr build input
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:09:26 -04:00
Thomas Mühlbacher
a1080f2f6a feat(nix): add a CI check that builds on 32-bit
Picked armv7l-linux but i686-linux would probably also work. Not sure
which one is more important to check for.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:09:21 -04:00
Thomas Mühlbacher
3bf9a19571 feat(nix): add an MSRV build to CI
Having a build that uses the actual version of Rust specified in
Cargo.toml should allow us to catch issues with breaking MSRV compat
more easily.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:09:15 -04:00
Thomas Mühlbacher
00dd889d33 feat(nix): enable cross compilation
Adds packages for every member of systems from any of the systems. Since
rust-overlay is more or less basically like rustup, we get to just have
all of those targets without having to build quite as much of the
toolchain.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:09:07 -04:00
Thomas Mühlbacher
1a8e684ae0 fix(makefile): locate built bin with CARGO_BUILD_TARGET set
When this environment variable is set, e.g. for some cross compile
setups, the target dir is nested a little further.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:08:48 -04:00
Thomas Mühlbacher
3d972489a8 fix(key): replace c_str macro with c"" literal
According to the MSRV in Cargo.toml, we can use this now.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:08:39 -04:00
Thomas Mühlbacher
197437be12 feat(nix): replace fenix with rust-overlay
We're going to use rust-overlay for setting up an MSRV build.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:08:31 -04:00
Thomas Mühlbacher
0a23a5ab1a feat(nix): open up support to more architectures
This means that the flake can now be built for the following
architectures:

- aarch64-linux
- armv6l-linux
- armv7l-linux
- i686-linux
- powerpc64le-linux
- riscv64-linux
- x86_64-linux

It doesn't mean that it's necessarily going to work perfectly on all of
these architecture and binary cache support is not available for a lot
of them either. But at least it let's you build for them if you want to.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:08:19 -04:00
Thomas Mühlbacher
017c3cc66e fix(nix): rm input from crane that no longer exists
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:08:06 -04:00
Thomas Mühlbacher
8b7810403b flake.lock: Update
Flake lock file updates:

• Updated input 'crane':
    'github:ipetkov/crane/529c1a0b1f29f0d78fa3086b8f6a134c71ef3aaf' (2024-07-24)
  → 'github:ipetkov/crane/70947c1908108c0c551ddfd73d4f750ff2ea67cd' (2025-03-19)
• Removed input 'crane/nixpkgs'
• Updated input 'fenix':
    'github:nix-community/fenix/483df76def3e5010d709aa3a0418ba2088503994' (2024-07-30)
  → 'github:nix-community/fenix/7d9ba794daf5e8cc7ee728859bc688d8e26d5f06' (2025-03-20)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/a021b85be57d34b1eed687fcafd5d5ec64b2d853' (2024-07-29)
  → 'github:rust-lang/rust-analyzer/15d87419f1a123d8f888d608129c3ce3ff8f13d4' (2025-03-18)
• Updated input 'flake-compat':
    'github:edolstra/flake-compat/0f9255e01c2351cc7d116c072cb317785dd33b33' (2023-10-04)
  → 'github:edolstra/flake-compat/ff81ac966bb2cae68946d5ed5fc4994f96d0ffec' (2024-12-04)
• Updated input 'flake-parts':
    'github:hercules-ci/flake-parts/9227223f6d922fee3c7b190b2cc238a99527bbb7' (2024-07-03)
  → 'github:hercules-ci/flake-parts/f4330d22f1c5d2ba72d3d22df5597d123fdb60a9' (2025-03-07)
• Updated input 'flake-parts/nixpkgs-lib':
    '5daf051448.tar.gz?narHash=sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI%3D' (2024-07-01)
  → 'github:nix-community/nixpkgs.lib/147dee35aab2193b174e4c0868bd80ead5ce755c' (2025-03-02)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/52ec9ac3b12395ad677e8b62106f0b98c1f8569d' (2024-07-28)
  → 'github:nixos/nixpkgs/a84ebe20c6bc2ecbcfb000a50776219f48d134cc' (2025-03-19)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/768acdb06968e53aa1ee8de207fd955335c754b7' (2024-07-30)
  → 'github:numtide/treefmt-nix/adc195eef5da3606891cedf80c0d9ce2d3190808' (2025-03-19)

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-21 13:07:56 -04:00
Kent Overstreet
ce0c2241a4 v1.25.0
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-19 18:03:23 -04:00
Kent Overstreet
846f3398a2 More device option work
More work to regularize device options, with common command line
parsing - like other options.

This fixes an assortment of little nits: buggyness with the discard
option, device state (and others) can now be specied at device add time,
and is a decent cleanup.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-19 15:47:44 -04:00
Kent Overstreet
e6aecdd3b8 cmd_fsck: just exit if passed -a
-a is used when called from system to mean "automatic invocation, run
check only if you think you need it".

Since we have self healing and online fsck, we never need run fsck
automatically at boot time.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-19 15:09:44 -04:00
Kent Overstreet
62ea232b09 Update bcachefs sources to dbe591cee299 bcachefs: Add missing smp_rmb()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-19 10:18:56 -04:00
Kent Overstreet
64ce740ac6 cmd_recover_super: 'bcachefs recover-super'
New tool for scanning for backup superblocks, to recover when the
primary superblock + sb layout have been overwritten.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-17 14:28:10 -04:00
Kent Overstreet
c0836924b1 Update bcachefs sources to 4d28432bcc5f bcachefs: Validate bch_sb.offset field
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-17 14:23:49 -04:00
Kent Overstreet
f42ee45c6e Format now sets version_incompat_allowed
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-16 16:09:03 -04:00
Kent Overstreet
6cbadc946d Update bcachefs sources to 46af7258b951 bcachefs: BCH_SB_FEATURES_ALL includes BCH_FEATURE_incompat_verison_field
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-03-16 16:09:01 -04:00
Kent Overstreet
86cbeaf1c2 fix bch2_super_write() for bs > 4096
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-02-22 09:29:56 -05:00
Kent Overstreet
dd1a882d17 Update bcachefs sources to 9736cbbc5cc3 bcachefs: bs > ps support
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-02-20 15:52:55 -05:00
Kent Overstreet
3e15e96cb9 Switch to c11 atomics
there's a strange bug in liburcu's usage of c11 atomics turning up with
gcc 15; switch to using c11 atomics directly to work around this.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-02-13 18:48:07 -05:00
koverstreet
d7f02b4ed5
Merge pull request from Conan-Kudo/update-fedora-builddeps
docs: INSTALL: Update list of build dependencies for Fedora
2025-02-13 16:48:39 -05:00
Neal Gompa
1606364799 docs: INSTALL: Update list of build dependencies for Fedora
This is more in line with the dependencies used to build it for
the official Fedora package.

Signed-off-by: Neal Gompa <neal@gompa.dev>
2025-02-13 16:46:57 -05:00
Kent Overstreet
553e605886 Merge remote-tracking branch 'github/master' 2025-02-06 17:32:41 -05:00
koverstreet
55538d928b
Merge pull request from pevik/opensuse-install
docs: Add fuse package on openSUSE
2025-02-06 17:31:48 -05:00
Kent Overstreet
7d30f895c6 cmd_fs_usage: Handle querying old versions
Fix reading accounting from old kernel versions that had it in little
endian.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-02-06 10:26:10 -05:00
Petr Vorel
8cc5bdede9 docs: Add fuse package on openSUSE
While it, shorten zypper command and reformat.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
2025-02-06 09:51:05 +01:00
Kent Overstreet
67c9b378c7 fixup! Update bcachefs sources to 63bbe0ca4167 bcachefs: Scrub
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-02-03 15:31:59 -05:00
Kent Overstreet
55afc8ad37 v1.20.0
Bump version numbers

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-02-03 14:14:04 -05:00
Kent Overstreet
3fcc955d00 Scrub
Implement 'bcachefs data scrub', frontend for
BCH_IOCTL_DATA.BCH_DATA_OP_scrub.

Takes a path to a device, mountpoint, or filesystem uuid. Can be run on
a specific device by passing a device, or if run on a filesystem scrubs
all devices in parallel.

Metadata only scrubbing is supported via -m.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-02-03 14:08:49 -05:00
Kent Overstreet
c4e25c6c3c bcachefs fs top
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-02-03 14:08:49 -05:00
Kent Overstreet
8361ae1a42 Update bcachefs sources to 63bbe0ca4167 bcachefs: Scrub 2025-02-03 14:08:49 -05:00
Kent Overstreet
895fc9a101 cmd_format: fix -l, -v options
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-01-26 17:34:23 -05:00
koverstreet
56b2449ded
Merge pull request from pevik/opensuse-pkg
INSTALL: Add info about openSUSE packages
2025-01-25 00:09:46 -05:00
Petr Vorel
117e5fd7e9
docs: Add info about openSUSE packages
Signed-off-by: Petr Vorel <pvorel@suse.cz>
2025-01-24 22:39:47 +01:00
Kent Overstreet
35a13784a2 Update bcachefs sources to 78c6c8127e21 bcachefs: Fix check_inode_hash_info_matches_root() 2025-01-15 12:20:30 -05:00
Kent Overstreet
16e23eaec1 Fix cmd_fs_usage for disk accounting key sort change
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-01-15 12:20:30 -05:00
Kent Overstreet
9cc5c9a79b update min_heap
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-01-15 12:20:30 -05:00
Kent Overstreet
6f1429b4eb Update bcachefs sources to f4b9a91fce73 bcachefs: Scrub 2024-12-30 17:04:00 -05:00
koverstreet
7210d5c911
Merge pull request from Flowdalic/mount-print-error
mount: print a helpful error message
2024-12-29 16:16:25 -05:00
Kent Overstreet
1055935ffe Update bcachefs sources to 864591728963 bcachefs: Dropped superblock write is no longer a fatal error
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-29 14:57:48 -05:00
Integral
634c812a1e Fix build failure on liburcu v0.15.0
After upgrading liburcu to v0.15.0, bcachefs-tools failed to build. This patch
fixes build errors on liburcu v0.15.0.

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-29 08:44:50 -05:00
Kent Overstreet
601deb6e5d fix c11 atomics
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-10 16:16:05 -05:00
Kent Overstreet
ef25411bdc fixup! bcachefs: cmd_set_option() can now set device options on multi device filesystems 2024-12-09 03:55:16 -05:00
Kent Overstreet
8b31dfb350 Update bcachefs sources to 55a65a994ed5 bcachefs: bcachefs_metadata_version_persistent_inode_cursors
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-08 16:00:44 -05:00
Kent Overstreet
2aeeac7785 bcachefs: cmd_set_option() can now set device options on multi device filesystems
Currently, 'bcachefs set-fs-option' requires all devices to be specified
when setting options on an offline multidevice filesystem - it can't yet
scan for the rest of the filesystem members.

We do need to fix this, but the scan code is written in Rust, so that
either means a lot of ugly FFI code or rewriting cmd_set_option() in
Rust - neither of which are happening today.

So as an interim hack, add a --dev-idx option: this can be specified
(multiple times if desired) for indicating which devices the device
specific options should be applied to.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-06 16:30:19 -05:00
Kent Overstreet
83cc57700f fixup! cmd_format: fix --version
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-04 21:22:03 -05:00
Kent Overstreet
626b1945eb fix build
haven't merged inode_alloc_cursor yet

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-03 23:07:00 -05:00
koverstreet
077677e61c
Merge pull request from ticpu/set-passphrase
Fix set-passphrase on --no_passphrase FS
2024-12-03 22:41:13 -05:00
koverstreet
a17e2ca95c
Merge pull request from michaeladler/fix/man-page-set-file-option
man: setattr has been renamed to set-file-option
2024-12-03 22:38:14 -05:00
Kent Overstreet
ac124c8885 Update bcachefs sources to 4a32728376a8 bcachefs: bcachefs_metadata_version_inode_depth
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-03 21:51:54 -05:00
Kent Overstreet
c560ff06f4 cmd_format: fix --version
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-12-03 21:51:26 -05:00
koverstreet
51ebefdd6e
Merge pull request from nnathan/improvements_to_initcpio
initcpio: small improvements to the mkinitcpio hooks
2024-12-01 19:26:50 -05:00
Naveen Nathan
77d72319a4 initcpio: small improvements to the mkinitcpio hooks 2024-12-02 09:46:38 +11:00
koverstreet
c2af793c8c
Merge pull request from DerVerruckteFuchs/master
add mkinitcpio hook for Arch and sample /etc/mkinitcpio.conf
2024-12-01 17:31:55 -05:00
Kent Overstreet
de51418b60 Update bcachefs sources to bc01863fb6ef bcachefs: bcachefs_metadata_version_disk_accounting_big_endian
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-11-29 21:27:09 -05:00
Kent Overstreet
6829fb2010 fix online fsck options
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-11-28 23:43:06 -05:00
Integral
d4932bf0e3 bcachefs-tools: Fix TODO "Show bcachefs version"
Fix TODO "Show bcachefs version" in fusemount.

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-11-06 16:21:02 -05:00
Michael Adler
9beb9fabb2 man: setattr has been renamed to set-file-option
Closes 

Fixes: 52b9e813 ("Rename option commands")
Signed-off-by: Michael Adler <michael.adler@siemens.com>
2024-11-05 14:00:13 +01:00
Integral
511a714ed3 bcachefs-tools: update VERSION in Makefile to 1.13.0
Update VERSION in Makefile to 1.13.0.

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-27 16:15:00 -04:00
Integral
b7831af74d bcachefs-tools: fix in fuse feature in RUSTFLAGS
Currently, when "BCACHEFS_FUSE=1" is set, fusemount subcommand
still cannot be identified. Change RUSTFLAGS in Makefile to fix
this problem.

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-27 16:15:00 -04:00
koverstreet
64767d6443
Merge pull request from g2p/format-safety
Check for a sufficiently recent libblkid before formatting
2024-10-27 16:13:55 -04:00
Gabriel de Perthuis
8d5f44d3b1 Check for a sufficiently recent libblkid before formatting
This can prevent data loss as libblkid < 2.40.1 can fail
to recognize existing bcachefs filesystems.

Reported on #bcache.

Signed-off-by: Gabriel de Perthuis <g2p.code@gmail.com>
2024-10-27 14:48:05 +00:00
Integral
5350fd2b7b bcachefs-tools: fix build failure when BCACHEFS_FUSE=1
Currently, when BCACHEFS_FUSE=1 is set, bcachefs-tools failed to build.
Replace "bch2_trans_do()" macro with "bch2_trans_commit_do()" in
cmd_fusemount.c to fix build failure.

Signed-off-by: Integral <integral@archlinuxcn.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-26 01:48:17 -04:00
Malte Schröder
cb8dc1b2ba Allow multiple targets for subvolume delete.
Signed-off-by: Malte Schröder <malte.schroeder@tnxip.de>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-25 15:07:49 -04:00
Florian Schmaus
9ed0f3fd72 mount: print a helpful error message
Just returning a failure exit status makes it hard to tell what the
actual issue was. Instead, the mount command now also provides some
textual output.

See https://github.com/koverstreet/bcachefs-tools/issues/308 for an
example where mount does not provide any helpful output, even with
BCACHEFS_LOG=trace enabled.

Signed-off-by: Florian Schmaus <flo@geekplace.eu>
2024-10-25 10:46:26 +02:00
Kent Overstreet
2541755981 cmd_fsck: Add -K flag (don't run kernel fsck)
This was added previously, but not added to the getopt string.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-20 19:23:21 -04:00
Kent Overstreet
553d6f107a Update bcachefs sources to 1dbc147a6eb0 bcachefs: Add version check for bch_btree_ptr_v2.sectors_written validate
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-20 19:07:51 -04:00
Kent Overstreet
4f9293b045 cmd_fsck: Create loopback device for kernel fsck when necessary
fstests generic/648 now passes

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-12 17:20:56 -04:00
Kent Overstreet
282331defa Fix some warnings about elided lifetimes
these popped up on the latest rustc

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-12 17:20:56 -04:00
Kent Overstreet
b1e6d1ced2 cmd_mount: Change error message on -EBUSY to match util-linux
This causes xfstests generic/741 to pass

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-12 17:20:56 -04:00
Alyssa Ross
3666da87f2 Pass -C default-linker-libraries to rustc
By default, rustc passes -nodefaultlibs to the linker.  In some cases,
this can cause compiler builtins (e.g. __cpu_model, used by
__builtin_cpu_supports) not to be linked in:

= note: /nix/store/s2cjhni3s6shh0n35ay1hpj8d85k44qk-x86_64-unknown-linux-musl-binutils-2.43.1/bin/x86_64-unknown-linux-musl-ld: ./libbcachefs.a(tools-util.o): in function `resolve_crc32c':
        /build/source/c_src/tools-util.c:457:(.text+0x1023): undefined reference to `__cpu_model'
        collect2: error: ld returned 1 exit status

I saw this with static musl GCC builds, and others have reported it with
Clang.

Link: https://github.com/koverstreet/bcachefs-tools/issues/300
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-12 17:20:56 -04:00
Alyssa Ross
6153c37e38 Avoid static linking conflicts with libblkid
When static linking, it's not possible to have two functions with the
same name in different libraries:

	= note: /nix/store/s2cjhni3s6shh0n35ay1hpj8d85k44qk-x86_64-unknown-linux-musl-binutils-2.43.1/bin/x86_64-unknown-linux-musl-ld: /nix/store/zwid05lzfy46k32xljb2alh0gq7ys58a-util-linux-minimal-static-x86_64-unknown-linux-musl-2.39.4-lib/lib/libblkid.a(libcommon_la-crc32c.o): in function `crc32c':
	        (.text+0x0): multiple definition of `crc32c'; ./libbcachefs.a(tools-util.o):/build/source/c_src/tools-util.c:484: first defined here
	        collect2: error: ld returned 1 exit status

Work around this by avoiding a known name collision with a function in
libblkid.

Closes: https://github.com/koverstreet/bcachefs-tools/issues/311
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-12 17:20:56 -04:00
Kent Overstreet
4e25d26a81 Update bcachefs sources to 9ab6c94002b9 bcachefs: bch2_journal_meta() takes ref on c->writes 2024-10-12 17:20:56 -04:00
Kent Overstreet
1dba682527 cmd_kill_btree_node: Can now kill multiple nodes simultaneously
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-12 17:20:56 -04:00
Kent Overstreet
571ca8b8ce cmd_list_journal: Add filtering on log msg
This allows us to filter out e.g. all btree_node_write_work transacitons

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-09 21:58:15 -04:00
Kent Overstreet
01413354a5 Update bcachefs sources to 8aa83b2beeb3 bcachefs: Improve check_snapshot_exists() 2024-10-09 21:58:03 -04:00
Kent Overstreet
1d68a6da59 Update bcachefs sources to 3b80552e7057 bcachefs: __wait_for_freeing_inode: Switch to wait_bit_queue_entry
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-09 19:49:17 -04:00
Kent Overstreet
c4456b4714 Update cargo dependencies
This fixes an odd bindgen issue

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-09 19:48:37 -04:00
Kent Overstreet
d27d4cf7f0 Fix 'fuse' feature conditional compilation
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-05 22:49:27 -04:00
Thomas Bertschinger
3829e49167 fuse: graceful shutdown when startup fails
When FUSE startup encounters an error after opening the filesystem--for
example because of a bad mountpoint--it exited uncleanly, which is a
bit unfriendly.

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-10-04 22:48:21 -04:00
Kent Overstreet
9f20109509 Update bcachefs sources to 438696e03da7 bcachefs: rename version -> bversion for big endian builds 2024-09-29 22:18:18 -04:00
Kent Overstreet
7a98f526b5 cmd_list: open with noxcl
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-09-29 22:18:18 -04:00
Kent Overstreet
bc5d903fda Update bcachefs sources to 82792a451950 bcachefs: Switch some bch2_dev_rcu() calls to _noerror
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-09-07 22:25:45 -04:00
Mae Kasza
45468a9a6f
Fix set-passphrase on --no_passphrase FS
This also fixes a bug where the set-passphrase
command failed to derive the key for disks initially
formatted with --encrypted and --no_passphrase, due to
bch_sb_crypt_init not configuring the KDF params if
the passphrase wasn't specified during formatting.

Signed-off-by: Mae Kasza <git@badat.dev>
Tested-by: Jérôme Poulin <jeromepoulin@gmail.com>
2024-09-07 21:46:32 -04:00
Kent Overstreet
cd35891eb9 Update bcachefs sources to ec2ddb95112b bcachefs: bch2_opts_to_text()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-09-07 21:14:35 -04:00
Alyssa Ross
f9ec00d5ca Remove udev from PKGCONFIG_LIBS in Makefile
libudev.pc is the pkg-config file for the udev libraries.  udev.pc is
just there to define the directory that rules etc. should be installed
into.  It therefore doesn't need to be included in the list of libraries
passed to pkg-config --cflags or pkg-config --libs.

At least one implementation of the libudev API, libudev-zero, does not
provide a udev.pc file, because it does not implement the udev rules
language, just the library API.  With this change, it's possible to
build bcachefs-tools against libudev-zero by pointing PKGCONFIG_UDEVDIR
somewhere on the make command line.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-09-04 15:38:46 -04:00
koverstreet
68704c30dc
Merge pull request from workingjubilee/remove-trivial-deps
Remove trivial deps
2024-09-04 11:39:40 -04:00
Jubilee Young
a1122aced2 Remove byteorder dep
This requires something other than literally zero code to replace, but
is another opportunity to deny packagers the fun of experimenting with
replacing crate versions with incompatible patched crate versions.
2024-09-03 00:31:33 -07:00
Jubilee Young
1a5b11db3f bch_bindgen: Remove memoffset dep
A trivial replacement allowed by std stabilizing it in rust 1.77.
Less crate dependencies means less odd decisions by packagers.
2024-09-03 00:14:30 -07:00
Kent Overstreet
1e058db4b6 cmd_dump: Open in noexcl mode
no need to make it harder to dump than it needs to be

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-31 21:34:15 -04:00
Kent Overstreet
b422b19f63 Update bcachefs sources to 22fa8fc32e6a bcachefs: rcu_pending now works in userspace 2024-08-23 19:34:30 -04:00
koverstreet
6f938e0399
Merge pull request from reedriley/master
fix setattr in usage/docs; bump version in various places from v1.9.5 (wrong) to v1.11.1
2024-08-23 17:47:05 -04:00
Reed Riley
481a50f0a9 version bump to v1.11.1 2024-08-22 16:26:18 -05:00
Reed Riley
6c32c8d9c9 change setattr to set-file-option in docs/usage 2024-08-22 16:23:51 -05:00
koverstreet
d30bc11101
Merge pull request from Managor/master
Change lingering set-option texts to set-fs-option
2024-08-21 17:34:06 -04:00
Antti Savolainen
ef47274485 Change lingering set-option texts to set-fs-option 2024-08-21 15:24:00 +03:00
Kent Overstreet
31039815a7 posix_to_bcachefs: fix missing copy_xattrs() error checking
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-20 19:47:56 -04:00
Kent Overstreet
8e0023ed4a Update bcachefs sources to 62439c6f1a6d bcachefs: Simplify bch2_xattr_emit() implementation
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-18 20:44:19 -04:00
Kent Overstreet
e2e1493111 Update bcachefs sources to e7015d0df31c bcachefs: Simplify bch2_xattr_emit() implementation
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-17 16:09:41 -04:00
Kent Overstreet
8b93af8747 kill_btree_node fixup
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-10 17:30:27 -04:00
koverstreet
74a48d6da8
Merge pull request from PowerUser64/spelling-fix
doc: correct some spelling errors
2024-08-10 12:16:55 -04:00
Kent Overstreet
6687752a1d Update bcachefs sources to 070f7d6a382a bcachefs: bch2_sb_nr_devices()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-10 11:52:25 -04:00
PowerUser64
5b4ee5cf7b doc: correct some spelling errors 2024-08-09 21:36:42 -07:00
Kent Overstreet
495a54c03b Revert "build: rm package.version from Cargo.toml"
This reverts commit 48c51020e5.

Deleting the version from Cargo.toml broke the MSRV build with cargo
1.7.0.
2024-08-09 04:08:08 -04:00
Kent Overstreet
3f885423df fsck: modprobe before doing version check
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-09 04:01:23 -04:00
Kent Overstreet
8d75a97e1a cmd_fs_usage: fix null ptr deref
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-09 03:44:27 -04:00
Kent Overstreet
b00ac20e76 mount: When mounting a single device, make sure we mount the device specified
When mounting a multi device filesystem we have to scan for component
devices from the UUID, but we don't want to scan if it's a single device
filesystem; if the same filesystem is exposed via multiple device nodes
(e.g. dm faulty testing), the scan can pick up the wrong node.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-09 03:44:27 -04:00
Kent Overstreet
c616061a93 bch_sb::number_of_devices() now calls proper c helper
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-08 11:51:17 -04:00
Kent Overstreet
95e8cddd3b Update bcachefs sources to dfc7b2c9433e bcachefs: bch2_sb_nr_devices()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-08 11:51:07 -04:00
Kent Overstreet
da1d5571f5 fixup! cmd_set_option: Can now set device options
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-08-06 20:34:20 -04:00
koverstreet
6958dd8df2
Merge pull request from WhatAmISupposedToPutHere/master
Ask for password via systemd-ask-password
2024-08-02 09:33:46 -04:00
koverstreet
e42312b602
Merge pull request from JohnRTitor/nix-fix
nix: add meta.mainProgram to allow directly running from this repo
2024-07-31 18:22:23 -04:00
John Titor
73a271e130
nix: add meta.mainProgram to allow directly running from this repo 2024-07-31 22:37:13 +05:30
koverstreet
c60ce81890
Merge pull request from koverstreet/update_flake_lock_action
flake.lock: Update
2024-07-30 20:46:21 -04:00
github-actions[bot]
1eaac529af flake.lock: Update
Flake lock file updates:

• Updated input 'crane':
    'github:ipetkov/crane/8a68b987c476a33e90f203f0927614a75c3f47ea?narHash=sha256-a0G1NvyXGzdwgu6e1HQpmK5R5yLsfxeBe07nNDyYd%2Bg%3D' (2024-07-18)
  → 'github:ipetkov/crane/529c1a0b1f29f0d78fa3086b8f6a134c71ef3aaf?narHash=sha256-k3oiD2z2AAwBFLa4%2BxfU%2B7G5fisRXfkvrMTCJrjZzXo%3D' (2024-07-24)
• Updated input 'fenix':
    'github:nix-community/fenix/d3121c162a1fa4fabcb9af9642d50e8b05ddfe83?narHash=sha256-AJjRiL2diAitpARbE9bUTlgtqHC8QS1ImXNaXMRhKoU%3D' (2024-07-20)
  → 'github:nix-community/fenix/483df76def3e5010d709aa3a0418ba2088503994?narHash=sha256-DfGaJtgrzcwPQYLTvjL1KaVIjpvi85b2MpM6yEGvJzM%3D' (2024-07-30)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/b333f85a9dc06a45d9eb126c6371414c49b46784?narHash=sha256-23zmEelXzAvnfMlLsJ6a6P7yNiI9WOUrS9xh9dXVc/U%3D' (2024-07-19)
  → 'github:rust-lang/rust-analyzer/a021b85be57d34b1eed687fcafd5d5ec64b2d853?narHash=sha256-KxjkPVn9rQqYam6DhiN/V2NcMXtYW25maxkJoiVMpmE%3D' (2024-07-29)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/1d9c2c9b3e71b9ee663d11c5d298727dace8d374?narHash=sha256-8MUgifkJ7lkZs3u99UDZMB4kbOxvMEXQZ31FO3SopZ0%3D' (2024-07-19)
  → 'github:nixos/nixpkgs/52ec9ac3b12395ad677e8b62106f0b98c1f8569d?narHash=sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k%3D' (2024-07-28)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/888bfb10a9b091d9ed2f5f8064de8d488f7b7c97?narHash=sha256-wNXLQ/ATs1S4Opg1PmuNoJ%2BWamqj93rgZYV3Di7kxkg%3D' (2024-07-20)
  → 'github:numtide/treefmt-nix/768acdb06968e53aa1ee8de207fd955335c754b7?narHash=sha256-uru7JzOa33YlSRwf9sfXpJG%2BUAV%2BbnBEYMjrzKrQZFw%3D' (2024-07-30)
2024-07-30 21:57:23 +00:00
koverstreet
1e5452a027
Merge pull request from tmuehlbacher/fix-c-exit-code
Fix C exit code
2024-07-30 17:56:43 -04:00
Thomas Mühlbacher
fb6a56bb81 fix(nix): silence trace from treefmt-nix
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-30 23:35:39 +02:00
Thomas Mühlbacher
b4db95b16e fix: don't try to convert C command returns to u8
Fixes Rust panics if some C command (like fsck) returns a value bigger
than 255. The process exit code will be mangled but what can we do, it's
less confusing than a panic (that unfortunately doesn't print the return
value).

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-30 23:33:09 +02:00
Sasha Finkelstein
54da29d413 mount: Ask for password via systemd-ask-password
This would allow to supply the password via the plymouth password input.
If systemd-ask-password does not exist or fails to start, falls back to
the old-style password request.

Signed-off-by: Sasha Finkelstein <fnkl.kernel@gmail.com>
2024-07-26 20:39:17 +02:00
Kent Overstreet
57cd58db1e mount: Fix UAF in option string handling
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-22 11:22:34 -04:00
koverstreet
dfc39d36c4
Merge pull request from koverstreet/update_flake_lock_action
flake.lock: Update
2024-07-20 20:11:19 -04:00
github-actions[bot]
52dd7f6391 flake.lock: Update
Flake lock file updates:

• Updated input 'crane':
    'github:ipetkov/crane/0095fd8ea00ae0a9e6014f39c375e40c2fbd3386?narHash=sha256-UKrfy/46YF2TRnxTtKCYzqf2f5ZPRRWwKCCJb7O5X8U%3D' (2024-06-15)
  → 'github:ipetkov/crane/8a68b987c476a33e90f203f0927614a75c3f47ea?narHash=sha256-a0G1NvyXGzdwgu6e1HQpmK5R5yLsfxeBe07nNDyYd%2Bg%3D' (2024-07-18)
• Updated input 'fenix':
    'github:nix-community/fenix/ab655c627777ab5f9964652fe23bbb1dfbd687a8?narHash=sha256-ixopuTeTouxqTxfMuzs6IaRttbT8JqRW5C9Q/57WxQw%3D' (2024-06-08)
  → 'github:nix-community/fenix/d3121c162a1fa4fabcb9af9642d50e8b05ddfe83?narHash=sha256-AJjRiL2diAitpARbE9bUTlgtqHC8QS1ImXNaXMRhKoU%3D' (2024-07-20)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/48bbdd6a74f3176987d5c809894ac33957000d19?narHash=sha256-%2BlRAmz92CNUxorqWusgJbL9VE1eKCnQQojglRemzwkw%3D' (2024-06-05)
  → 'github:rust-lang/rust-analyzer/b333f85a9dc06a45d9eb126c6371414c49b46784?narHash=sha256-23zmEelXzAvnfMlLsJ6a6P7yNiI9WOUrS9xh9dXVc/U%3D' (2024-07-19)
• Updated input 'flake-parts':
    'github:hercules-ci/flake-parts/2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8?narHash=sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw%3D' (2024-06-01)
  → 'github:hercules-ci/flake-parts/9227223f6d922fee3c7b190b2cc238a99527bbb7?narHash=sha256-pQMhCCHyQGRzdfAkdJ4cIWiw%2BJNuWsTX7f0ZYSyz0VY%3D' (2024-07-03)
• Updated input 'flake-parts/nixpkgs-lib':
    'eb9ceca17d.tar.gz?narHash=sha256-lIbdfCsf8LMFloheeE6N31%2BBMIeixqyQWbSr2vk79EQ%3D' (2024-06-01)
  → '5daf051448.tar.gz?narHash=sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI%3D' (2024-07-01)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/e9ee548d90ff586a6471b4ae80ae9cfcbceb3420?narHash=sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY%3D' (2024-06-13)
  → 'github:nixos/nixpkgs/1d9c2c9b3e71b9ee663d11c5d298727dace8d374?narHash=sha256-8MUgifkJ7lkZs3u99UDZMB4kbOxvMEXQZ31FO3SopZ0%3D' (2024-07-19)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/68eb1dc333ce82d0ab0c0357363ea17c31ea1f81?narHash=sha256-ULzoKzEaBOiLRtjeY3YoGFJMwWSKRYOic6VNw2UyTls%3D' (2024-06-16)
  → 'github:numtide/treefmt-nix/888bfb10a9b091d9ed2f5f8064de8d488f7b7c97?narHash=sha256-wNXLQ/ATs1S4Opg1PmuNoJ%2BWamqj93rgZYV3Di7kxkg%3D' (2024-07-20)
2024-07-21 00:00:57 +00:00
koverstreet
da81a430b1
Merge pull request from tmuehlbacher/disable-treefmt-check
ci: disable treefmt-check
2024-07-20 20:00:19 -04:00
Thomas Mühlbacher
b105a566ec ci: disable treefmt-check
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-21 01:54:10 +02:00
koverstreet
201b1e8216
Merge pull request from tmuehlbacher/variety-changes
Variety changes
2024-07-20 19:37:06 -04:00
Thomas Mühlbacher
cdcc241167 refactor: fix clippy lint
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-21 01:17:27 +02:00
Thomas Mühlbacher
7c68f2758d style: nix fmt
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-21 01:17:27 +02:00
Thomas Mühlbacher
e218119b01 fix(logging): re-enable warn and error by default
Same as it was in most previous releases. Without this, you may not see
any output for certain errors.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-21 01:16:28 +02:00
Thomas Mühlbacher
09cde4869d feat(logging): switch to custom file:line format
This mostly tries to be similar to the default `env_logger` format but
instead of using the more vague target in the log message, we instead
put the file name and line number in the log.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-21 01:16:28 +02:00
Thomas Mühlbacher
48c51020e5 build: rm package.version from Cargo.toml
This sets the version, that can be read at build time using the
environment variable `CARGO_PKG_VERSION`, to the default
value (`0.0.0`).

Setting `package.version` in the Cargo manifest is mandatory for
publishing to crates.io. We're not publishing the crate currently, and
there isn't an obvious case for doing so in the future that comes to
mind.

Our sources are not using the version from cargo currently. `clap` and
some other dependencies may use them by default but still we don't use
that version in any outputs. Therefore, we should be fine without it.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-21 01:16:28 +02:00
Thomas Mühlbacher
ceb5e80d0e chore: rm leftover gitignore entries
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-07-21 01:16:28 +02:00
Kent Overstreet
52b9e813bd Rename option commands
set-option	-> set-fs-option
setattr 	-> set-file-option

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-20 16:45:08 -04:00
Kent Overstreet
59ccde4a2f mount: Fall back to read-only on -EROFS
this is the mount helper's job, and since we're the mount helper...

fixes: xfstests generic/050

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-20 11:33:46 -04:00
Kent Overstreet
60ff4f2f3c bump version to 1.9.5
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-18 20:48:14 -04:00
Kent Overstreet
9058835b97 mount: Close devices before doing mount
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-18 20:48:14 -04:00
Kent Overstreet
573d635b2c Update bcachefs sources to 1592eaa60418 bcachefs: Btree path tracepoints 2024-07-18 18:52:15 -04:00
Alexander Fougner
088e17a54a ci: bump upload-artifact action
Signed-off-by: Alexander Fougner <fougner89@gmail.com>
2024-07-17 11:24:07 +02:00
Alexander Fougner
f8d6a67db0 ci: fix build for older debian deps
also drop ubuntu 20.04 from build matrix, include 24.04 instead which
is soon to go stable.

Signed-off-by: Alexander Fougner <fougner89@gmail.com>
2024-07-17 11:24:05 +02:00
Kent Overstreet
9020d202a4 kill old python tests
these were never used, kill a dependency

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-15 23:34:58 -04:00
Kent Overstreet
07913d1185 logging: kill quiet option
no logging by default, enabled with -v

logging by default broke fstests

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-15 23:20:54 -04:00
Kent Overstreet
e084e9f65b update debian/ from upstream
'make deb' works

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-15 21:23:38 -04:00
Kent Overstreet
8594891772 cmd_set_option: Can now set device options
This allows data_allowed (and others) to be set on an offline
filesystem.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-15 20:17:37 -04:00
Kent Overstreet
32fbdff2a9 Update bcachefs sources to 4a7a003763f5 bcachefs: Opt_durability can now be set via bch2_opt_set_sb() 2024-07-15 20:17:37 -04:00
Kent Overstreet
2d60567685 fix silly clippy warning
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-14 22:16:13 -04:00
Lauri Tirkkonen
7ebd67e63a mount: replace rpassword with rustix::termios
because rpassword unconditionally open()s /dev/tty, it fails with ENXIO
on the console without workarounds like busybox's cttyhack. in contrast,
bcachefs unlock works fine on console, so change the passphrase prompt
logic in mount to be closer to what it is in unlock.

Signed-off-by: Lauri Tirkkonen <lauri@hacktheplanet.fi>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-14 21:49:58 -04:00
Thomas Bertschinger
9e12dd06b9 include debuginfo in bcachefs binary by default
The debuginfo is used by the "bcachefs debug" and "bcachefs list_bkeys"
commands.

Rust 1.77 [1] changed Cargo's release profile to strip debuginfo by default,
but we always want it included.

[1] https://github.com/rust-lang/cargo/pull/13257

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-14 16:20:17 -04:00
Kent Overstreet
061a9ff2a3 Update bcachefs sources to 4d1d53862afb bcachefs: show none if label is not set 2024-07-14 15:20:16 -04:00
Kent Overstreet
a1764e00cd Update bcachefs sources to 47d1e7a86242 bcachefs: drop packed, aligned from bkey_inode_buf
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-12 14:42:54 -04:00
Kent Overstreet
4be409afea provide atomic64_try_cmpxchg() for 32bit
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-12 14:24:38 -04:00
Kent Overstreet
0f9b409aee add i686-linux to nix flake
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-12 14:14:55 -04:00
Tavian Barnes
53d7722563 raid/cpu: Use memcpy() instead of type punning
The vendor may not be suitably aligned for uint32_t *.

Signed-off-by: Tavian Barnes <tavianator@tavianator.com>
2024-07-12 14:02:14 -04:00
Kent Overstreet
8b06995115 Update bcachefs sources to 2be6fc9b111c bcachefs: bch2_gc_btree() should not use btree_root_lock
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-07-05 09:16:45 -04:00
koverstreet
d061c7ea11
Merge pull request from tmuehlbacher/improve-logging-exiting
Improve logging and exiting
2024-06-29 14:16:14 -04:00
Kent Overstreet
755788e2d6 Be explicit about which fsck implementation we're running
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-29 11:55:03 -04:00
Kent Overstreet
34b5654d9e Update bcachefs sources to 9404a01d3dc5 bcachefs: Make read_only a mount option again, but hidden
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-28 18:26:04 -04:00
Thomas Mühlbacher
5cce07e986 feat: use ExitCode over std::process:exit()
Should provide us with better outputs on process failure, also makes
unwinding better and is generally recommended over `exit()`.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-29 00:11:07 +02:00
Thomas Mühlbacher
176d76bceb feat: add --quiet cli argument
To silence log outputs on the CLI.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-28 21:29:47 +02:00
Thomas Mühlbacher
df09682869 feat: use env_logger
Instead of the custom logger impl, which limits the features we can
easily provide for users.

This introduces the `BCACHEFS_LOG` environment variable for setting the
log verbosity. Setting `BCACHEFS_LOG=trace`, e.g. in a test environment,
will yield all log messages.

Also I think it's reasonable to print INFO level logs by default.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-28 21:29:20 +02:00
koverstreet
b0eb3c2930
Merge pull request from Artturin/use-ar-var
Use the AR variable in Makefile
2024-06-28 11:21:19 -04:00
Thomas Mühlbacher
7a17d429d5 feat(key): make UnlockPolicy::Fail more useful
We already can check if an fs is encrypted with `bcachefs unlock -c`.
With this option we can now instead check if we have a key but not
actually mount by not specifying a mount point. e.g.

```sh
if bcachefs mount -k fail "$blkdev"`; then
    echo "device is unlocked!"
fi
```

Not sure what the original intent for this was. For scenarios where
encryption is simply not supported on principle?

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-26 19:14:45 +02:00
Thomas Mühlbacher
ee5f3719d3 refactor(key): split up unlocking functions
This is more similar to the existing C code, which is already in nice
small chunks.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-26 19:14:45 +02:00
Thomas Mühlbacher
795585e289 refactor: simplify branches for parsing dev
Less repetition and no nested if/else.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-26 19:14:45 +02:00
Thomas Mühlbacher
9bd3ada1d1 feat(mount): make unlock policy optional/explict
This changes the semantics of some arguments related to unlocking and
slightly changes the unlocking logic. Also update help formatting/text.

Instead of defaulting to `UnlockPolicy::Ask`, the argument becomes
optional. That means if it is specified, the user really wants that
specific policy. Similar to how `passphrase_file` also works.

This also extends `UnlockPolicy` to override `isatty` detection.

Fixes: 
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-26 19:14:45 +02:00
Thomas Mühlbacher
a411e7237f refactor(mount): rename opt => cli
The term option is already used for mount options and the `Option` type.
In other modules it's just called `cli`, so let's do that here as well.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-26 19:14:45 +02:00
Thomas Mühlbacher
cf180e8f34 refactor: rm function param only used for log msg
We lose that bit of info but it's weird to require a parameter simply
because we want to use it for a log message.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-26 19:14:45 +02:00
Artturin
91e67ab2bd Use the AR variable in Makefile
For cross-compiling
2024-06-24 21:00:08 +03:00
David Disseldorp
411df4e53f key: use c_long type for keyctl_search() helper fn
The keyctl_search() C function returns a long, which is already
reflected in the KeyHandle._id type. The search_keyring() helper
function currently returns a Result<i64>, which breaks 32-bit builds for
e.g. armv7l:
  error[E0308]: mismatched types
     --> src/key.rs:121:16
      |
  121 |             Ok(key_id)
      |             -- ^^^^^^ expected `i64`, found `i32`
      |             |
      |             arguments to this enum variant are incorrect
...
  error[E0308]: mismatched types
     --> src/key.rs:135:24
      |
  135 |                 _id:   id,
      |                        ^^ expected `i32`, found `i64`

Fix this by changing search_keyring() to return a Result<c_long>.

Fixes: f72ded6a ("fix(key): search for key in all relevant keyrings")
Signed-off-by: David Disseldorp <ddiss@suse.de>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-20 08:52:12 -04:00
Kent Overstreet
277ba6d4ac v1.9.1
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-19 14:48:31 -04:00
Kent Overstreet
02aa11829a Merge commit '41df701a089fbf19fe16d65fbb6df46854b1f3df' of https://github.com/tmuehlbacher/bcachefs-tools 2024-06-19 12:09:32 -04:00
Kent Overstreet
adb63be479 update Cargo.lock version
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-19 09:23:49 -04:00
Kent Overstreet
dd275b1c5f Update version to 1.9.0
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-19 09:05:50 -04:00
Thomas Mühlbacher
41df701a08 fix(logger): log to stderr
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-18 20:56:25 +02:00
Thomas Mühlbacher
f72ded6a4f fix(key): search for key in all relevant keyrings
Previously, using `bcachefs unlock -k session` would still cause mount
to ask for a passphrase.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-18 20:56:17 +02:00
Thomas Mühlbacher
e4271d7a3e fix(key): remove any newlines from passphrase
To match the behavior of the C code and because there may be newlines
under some conditions.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-18 20:56:15 +02:00
Thomas Mühlbacher
87ab1fd7ed chore(editorconfig): extend for sh scripts
To match with what's already in the repo.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-18 20:56:06 +02:00
koverstreet
c909480560
Merge pull request from koverstreet/update_flake_lock_action
flake.lock: Update
2024-06-17 14:21:10 -04:00
github-actions[bot]
33ce7dd90c flake.lock: Update
Flake lock file updates:

• Updated input 'crane':
    'github:ipetkov/crane/17d9e9dedd58dde2c562a4296934c6d6a0844534?narHash=sha256-hGLeRxSEeFz9WvmQ4s4AuMJ5InLSZvoczDdXkWSFi1A%3D' (2024-06-09)
  → 'github:ipetkov/crane/0095fd8ea00ae0a9e6014f39c375e40c2fbd3386?narHash=sha256-UKrfy/46YF2TRnxTtKCYzqf2f5ZPRRWwKCCJb7O5X8U%3D' (2024-06-15)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/051f920625ab5aabe37c920346e3e69d7d34400e?narHash=sha256-4q0s6m0GUcN7q%2BY2DqD27iLvbcd1G50T2lv08kKxkSI%3D' (2024-06-07)
  → 'github:nixos/nixpkgs/e9ee548d90ff586a6471b4ae80ae9cfcbceb3420?narHash=sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY%3D' (2024-06-13)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/4fc1c45a5f50169f9f29f6a98a438fb910b834ed?narHash=sha256-npYqVg%2BWk4oxnWrnVG7416fpfrlRhp/lQ6wQ4DHI8YE%3D' (2024-06-08)
  → 'github:numtide/treefmt-nix/68eb1dc333ce82d0ab0c0357363ea17c31ea1f81?narHash=sha256-ULzoKzEaBOiLRtjeY3YoGFJMwWSKRYOic6VNw2UyTls%3D' (2024-06-16)
2024-06-17 18:20:02 +00:00
koverstreet
a87faa2e30
Merge pull request from tmuehlbacher/fix-nix-install
fix(nix): install paths from pkg-config properly
2024-06-17 14:19:23 -04:00
Kent Overstreet
d915c62f17 Update bcachefs sources to 792ca5ba3c9a bcachefs: kill key cache arg to bch2_assert_pos_locked() 2024-06-17 14:08:42 -04:00
Kent Overstreet
fc06a0ea5e Update bcachefs sources to c56e1ec97dfd bcachefs: Fix bch2_sb_downgrade_update()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-17 12:38:43 -04:00
Thomas Mühlbacher
b46d3a2710 fix(nix): install paths from pkg-config properly
Because we were using `DESTDIR` instead of `PREFIX` for some reason, no
one noticed that this didn't work.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-17 18:31:40 +02:00
Ariel Miculas
ab83e348fb Preserve directory {a,m,c} times by calling copy_times() after the recursion
Otherwise the directory {a,m,c} times will be modified by the recursive
copy of the directory tree.

Signed-off-by: Ariel Miculas <ariel.miculas@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-16 14:09:18 -04:00
Ariel Miculas
3a4a096cd2 Fix incomplete file copy due to copy_data misuse
The copy_data function takes a start and an end parameter as the range
of bytes to copy, but it was called with a start and a length parameter.
This resulted in incomplete file copies. Fix it by passing the end of
the range instead of the length.

Signed-off-by: Ariel Miculas <ariel.miculas@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-16 14:09:13 -04:00
Ariel Miculas
ed675b8d64 Fix performance regression of update_inode
This kernel commit: 65bd442397274347e721a89c2c4882a392bae982 removes
BTREE_ITER_cached from bch2_btree_insert_trans, which causes the
update_inode function to take a long time (~20s). Add this flag back in
the update_inode function.

Signed-off-by: Ariel Miculas <ariel.miculas@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-16 14:08:59 -04:00
Ariel Miculas
d750b2b98b bcachefs: allow initializing a bcachefs filesystem from a source directory
Add a new source command line argument which specifies the directory
tree that will be copied onto the newly formatted bcachefs filesystem.

This commit also fixes an issue in copy_link where uninitialized data is
copied into the symlink because of a round_up of the buffer size.

Signed-off-by: Ariel Miculas <ariel.miculas@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-16 14:08:52 -04:00
Kent Overstreet
f3ab07db73 fix missing include
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-16 14:08:47 -04:00
koverstreet
8bc27da705
Merge pull request from koverstreet/update_flake_lock_action
flake.lock: Update
2024-06-10 18:52:25 -04:00
github-actions[bot]
a2a0d53945 flake.lock: Update
Flake lock file updates:

• Updated input 'crane':
    'github:ipetkov/crane/480dff0be03dac0e51a8dfc26e882b0d123a450e?narHash=sha256-dIubLa56W9sNNz0e8jGxrX3CAkPXsq7snuFA/Ie6dn8%3D' (2024-05-29)
  → 'github:ipetkov/crane/17d9e9dedd58dde2c562a4296934c6d6a0844534?narHash=sha256-hGLeRxSEeFz9WvmQ4s4AuMJ5InLSZvoczDdXkWSFi1A%3D' (2024-06-09)
• Updated input 'fenix':
    'github:nix-community/fenix/14c3b99d4b7cb91343807eac77f005ed9218f742?narHash=sha256-BKFOT/eg0mCf99oTKa63yW%2Bd5Y3K6c5Gb%2BNetxacaHg%3D' (2024-05-31)
  → 'github:nix-community/fenix/ab655c627777ab5f9964652fe23bbb1dfbd687a8?narHash=sha256-ixopuTeTouxqTxfMuzs6IaRttbT8JqRW5C9Q/57WxQw%3D' (2024-06-08)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/b32f181f477576bb203879f7539608f3327b6178?narHash=sha256-mUZtVS2S%2BleFcMpBgbqkMnZm4II1qBM21pW8UnivVSo%3D' (2024-05-27)
  → 'github:rust-lang/rust-analyzer/48bbdd6a74f3176987d5c809894ac33957000d19?narHash=sha256-%2BlRAmz92CNUxorqWusgJbL9VE1eKCnQQojglRemzwkw%3D' (2024-06-05)
• Updated input 'flake-parts':
    'github:hercules-ci/flake-parts/8dc45382d5206bd292f9c2768b8058a8fd8311d9?narHash=sha256-/GJvTdTpuDjNn84j82cU6bXztE0MSkdnTWClUCRub78%3D' (2024-05-16)
  → 'github:hercules-ci/flake-parts/2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8?narHash=sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw%3D' (2024-06-01)
• Updated input 'flake-parts/nixpkgs-lib':
    '50eb7ecf4c.tar.gz?narHash=sha256-QBx10%2Bk6JWz6u7VsohfSw8g8hjdBZEf8CFzXH1/1Z94%3D' (2024-05-02)
  → 'eb9ceca17d.tar.gz?narHash=sha256-lIbdfCsf8LMFloheeE6N31%2BBMIeixqyQWbSr2vk79EQ%3D' (2024-06-01)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/ad57eef4ef0659193044870c731987a6df5cf56b?narHash=sha256-SzDKxseEcHR5KzPXLwsemyTR/kaM9whxeiJohbL04rs%3D' (2024-05-29)
  → 'github:nixos/nixpkgs/051f920625ab5aabe37c920346e3e69d7d34400e?narHash=sha256-4q0s6m0GUcN7q%2BY2DqD27iLvbcd1G50T2lv08kKxkSI%3D' (2024-06-07)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/52b66cade760e93276146eb057122b8011ab9057?narHash=sha256-V68CsekhPCF6Oz84t2FHY5jin4smKrmsS208Xw057zs%3D' (2024-05-30)
  → 'github:numtide/treefmt-nix/4fc1c45a5f50169f9f29f6a98a438fb910b834ed?narHash=sha256-npYqVg%2BWk4oxnWrnVG7416fpfrlRhp/lQ6wQ4DHI8YE%3D' (2024-06-08)
2024-06-10 22:31:10 +00:00
koverstreet
786e507c2e
Merge pull request from tmuehlbacher/flake-stuff
Make nix package builds have a unique version; dev shell addition
2024-06-10 18:30:30 -04:00
koverstreet
e743caf71c
Merge pull request from tmuehlbacher/subvol-fix
fix(subvol): canonicalize requires path to exist
2024-06-10 18:30:00 -04:00
Thomas Mühlbacher
c20f323fdb fix(subvol): canonicalize requires path to exist
Which is probably not the case when you want to create a subvolume in
that path.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-10 23:07:27 +02:00
Thomas Mühlbacher
2a15fc0445 build(nix): use actual commit rev in version
This way we get an actually unique version for every version that can be
traced back to the source.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-10 00:04:13 +02:00
Thomas Mühlbacher
990437ad13 build(nix): add bear to dev shell
A useful addition to make sure is available, since we also make clangd
available through clang-tools. bear can generate the
`compile_commands.json` for clangd. For example with `make clean && bear
-- make -j$(nproc)`.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-10 00:04:13 +02:00
koverstreet
c2354f0326
Merge pull request from tmuehlbacher/fix-subvolume-commands-with-relative-paths
fix(subvol): make cmds work with relative paths
2024-06-09 17:43:41 -04:00
Thomas Mühlbacher
b42b5b4065 fix(subvol): make cmds work with relative paths
`Path::parent()` returns `Some("")` for relative paths with a single
component. The simplest fix is to just canonicalize the paths first.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-09 22:13:11 +02:00
Kent Overstreet
e1fa076a86 Fix target option parsing for format, migrate
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-07 16:12:55 -04:00
Kent Overstreet
0d570e822b Update bcachefs sources to 4f69e2d39ad3 bcachefs: bch2_btree_insert() - add btree iter flags 2024-06-05 10:53:01 -04:00
Kent Overstreet
0916d38664 cmd_fs_usage: Use now BCH_IOCTL_QUERY_ACCOUNTING
We can now report on compression type/ratio, btree usage, and pending
rebalance work.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-03 20:08:06 -04:00
Kent Overstreet
da5435b0cc cmd_fs_usage: split out devs_usage_to_text()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-03 20:08:06 -04:00
Kent Overstreet
7d79fba1af Update bcachefs sources to f81dc88f0c80 bcachefs: bch2_btree_insert() - add btree iter flags
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-03 20:08:06 -04:00
koverstreet
d456f9e97a
Merge pull request from tmuehlbacher/fix-subvolume-commands
Fix subvolume commands
2024-06-03 17:01:22 -04:00
Thomas Mühlbacher
30e16b5e15 fix: avoid addr_of if we already use a reference
It's kind of stupid to use this macro if we have to deref the parameter
first. I was too enthusiastic about using this macro instead of `as`
because it's nicer to read (imo).

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-03 17:05:52 +02:00
Thomas Mühlbacher
fac7cce224 fix: unbreak subvolume commands
This was a stupid mistake by me, "fixing" more than what clippy told me
to. `p` is already a reference and we should not use the addr of it.

Fixes: 96a3462 ("refactor: casting-related `clippy::pedantic` fixes")
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-06-03 17:05:52 +02:00
Kent Overstreet
587f7f5a47 cmd_list_journal: open with noexcl, so we can work on mounted filesystems
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-06-02 21:06:47 -04:00
koverstreet
cafd2226a2
Merge pull request from tux3/patch-1
docs: udev.pc now in systemd-dev on Debian
2024-06-01 12:33:10 -04:00
Tux3
697c79fa7c
docs: udev.pc now in systemd-dev on Debian 2024-06-01 11:52:24 +02:00
koverstreet
4676269d2d
Merge pull request from koverstreet/update_flake_lock_action
flake.lock: Update
2024-05-31 11:37:03 -04:00
github-actions[bot]
617ba1380b flake.lock: Update
Flake lock file updates:

• Updated input 'crane':
    'github:ipetkov/crane/19ca94ec2d288de334ae932107816b4a97736cd8?narHash=sha256-8K1R9Yg4r08rYk86Yq%2Blu3E9L3uRUb4xMqYHgl0VGS0%3D' (2024-05-26)
  → 'github:ipetkov/crane/480dff0be03dac0e51a8dfc26e882b0d123a450e?narHash=sha256-dIubLa56W9sNNz0e8jGxrX3CAkPXsq7snuFA/Ie6dn8%3D' (2024-05-29)
• Updated input 'fenix':
    'github:nix-community/fenix/9af557bccdfa8fb6a425661c33dbae46afef0afa?narHash=sha256-zxFADJsXhODHH9rrF7gXjN%2BBYVkMoNY2NpLyjGQDOJA%3D' (2024-05-27)
  → 'github:nix-community/fenix/14c3b99d4b7cb91343807eac77f005ed9218f742?narHash=sha256-BKFOT/eg0mCf99oTKa63yW%2Bd5Y3K6c5Gb%2BNetxacaHg%3D' (2024-05-31)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/71a816a90facb6546a0a06010da17598e11812f7?narHash=sha256-xJ5vzVr5Et6wxHRQLOYicsa0gN2bwm4mj6AFHc8ugJc%3D' (2024-05-26)
  → 'github:rust-lang/rust-analyzer/b32f181f477576bb203879f7539608f3327b6178?narHash=sha256-mUZtVS2S%2BleFcMpBgbqkMnZm4II1qBM21pW8UnivVSo%3D' (2024-05-27)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/3eaeaeb6b1e08a016380c279f8846e0bd8808916?narHash=sha256-pU9ViBVE3XYb70xZx%2BjK6SEVphvt7xMTbm6yDIF4xPs%3D' (2024-05-21)
  → 'github:nixos/nixpkgs/ad57eef4ef0659193044870c731987a6df5cf56b?narHash=sha256-SzDKxseEcHR5KzPXLwsemyTR/kaM9whxeiJohbL04rs%3D' (2024-05-29)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/2fba33a182602b9d49f0b2440513e5ee091d838b?narHash=sha256-wJqHMg/K6X3JGAE9YLM0LsuKrKb4XiBeVaoeMNlReZg%3D' (2024-05-17)
  → 'github:numtide/treefmt-nix/52b66cade760e93276146eb057122b8011ab9057?narHash=sha256-V68CsekhPCF6Oz84t2FHY5jin4smKrmsS208Xw057zs%3D' (2024-05-30)
2024-05-31 15:34:51 +00:00
koverstreet
e739da5da8
Merge pull request from tmuehlbacher/fix-result-eval
fix: evaluate KeyHandle Result
2024-05-31 11:34:36 -04:00
koverstreet
af05a54922
Merge pull request from tmuehlbacher/fix-pedantic-clippy-lints
Fix pedantic clippy lints
2024-05-31 11:34:06 -04:00
Thomas Mühlbacher
8cd17b40df build(nix): make package version more accurate
Would still be better to have commit rev included if
applicable/available but still better than before.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-31 14:49:39 +02:00
Thomas Mühlbacher
96a346254d refactor: casting-related clippy::pedantic fixes
Prefer using `ptr::addr_of!()` and `pointer::cast()` instead of raw `as`
where clippy complains and other type casting lints.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-31 12:48:42 +02:00
Thomas Mühlbacher
15e3c90584 refactor: make c_str! simpler, add test
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-31 12:48:42 +02:00
Thomas Mühlbacher
0ca3233518 refactor: change some fn type sigs and simplify
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-31 12:48:42 +02:00
Thomas Mühlbacher
20f7954cdb refactor: treat harmless clippy::pedantic lints
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-31 12:48:42 +02:00
Thomas Mühlbacher
9ec185437d fix: evaluate KeyHandle Result
This one is sort of bad to have missed, ouch.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-31 03:56:53 +02:00
koverstreet
96843fc95d
Merge pull request from tmuehlbacher/msrv-and-tweaks
Msrv and tweaks
2024-05-30 20:41:29 -04:00
Thomas Mühlbacher
781ea5d40f fix: minor tweaks for key.rs
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-31 02:30:59 +02:00
Thomas Mühlbacher
31066e17e8 fix: keep compat with MSRV
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-31 02:30:59 +02:00
koverstreet
d42a097280
Merge pull request from tmuehlbacher/rewrite-rust-key-handling
Rewrite rust key handling
2024-05-30 19:56:27 -04:00
Thomas Mühlbacher
22495e0d31 feat: rewrite key.rs
- Introduce `KeyHandle` and `Passphrase` types

- Refactor the functions into associated functions

- Add `zeroizing` crate to handle passphrase memory safely

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-30 22:26:06 +02:00
Thomas Mühlbacher
25bce91b4b refactor: rename function again
`bch2_sb_is_encrypted_and_locked()` simply does not check if the fs is
locked. The name is misleading.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-30 22:26:06 +02:00
Thomas Mühlbacher
21b1111b59 refactor: reduce UnlockPolicy boilerplate
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-30 22:26:06 +02:00
koverstreet
de6e8ac230
Merge pull request from JohnRTitor/cleanup
treewide: fix typos in docs and comments
2024-05-29 23:56:27 -04:00
Kent Overstreet
3016a7dbbd cmd_fsck: Fix check for running online fsck
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-29 18:01:59 -04:00
Kent Overstreet
c3c7dacab2 mount: minor cleanup
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-29 17:00:50 -04:00
Andrea Gelmini
18f9526c45
treewide, docs: fix typos
Signed-off-by: Andrea Gelmini <andrea.gelmini@gelma.net>
[remove changes to libbcachefs/, linux/, include/, and raid/]
Co-authored-by: Masum Reza <masumrezarock100@gmail.com>
Signed-off-by: Masum Reza <masumrezarock100@gmail.com>
2024-05-29 09:22:09 +05:30
Kent Overstreet
0c39011ae0 Update bcachefs sources to 8528bde1b66b bcachefs: Fix uninitialized var warning 2024-05-28 18:22:45 -04:00
koverstreet
cd94eda1d8
Merge pull request from JohnRTitor/workflows
workflows: add monthly flake lock update workflow
2024-05-28 16:18:34 -04:00
John Titor
a0bbe712c0
workflows: add monthly flake lock update workflow
Signed-off-by: Masum Reza <masumrezarock100@gmail.com>
2024-05-29 01:12:56 +05:30
koverstreet
c36b96d4dc
Merge pull request from tmuehlbacher/add-more-flake-checks
Add more flake checks
2024-05-28 15:25:29 -04:00
Thomas Mühlbacher
d43fbfd642 docs: rm outdated msrv in install instructions 2024-05-28 19:32:53 +02:00
Thomas Mühlbacher
7f15685517 build(nix): minor tweaks
- rm unused function argument

- `LIBCLANG_PATH` is superfluous here, this is already handled by
  `rustPlatform.bindgenHook` for us.

- rustc is not directly needed in the `$PATH` for the build but it's
  good to have in the dev shell.
2024-05-28 19:32:53 +02:00
Thomas Mühlbacher
b362f12add build(nix): add cargo test check
this is pretty much a no-op currently, but hopefully we can make some
use of it in the future.
2024-05-28 19:32:53 +02:00
Thomas Mühlbacher
422ae1f1a7 build(nix): add cargo clippy check
note that this only checks the top-level package, `bch_bindgen` is
excluded because it has too many clippy lints.
2024-05-28 19:32:53 +02:00
Thomas Mühlbacher
bf2c0c8852 build(nix): use crane to build packages
this enables faster incremental rebuilds in nix. it also allows us to
add clippy and cargo test checks more easily. aside from that, i have
tried to carry over things that i think are sensible from the previous
`mkDerivation` call.

the `checkPhase` may as well rather be done in a `installCheckPhase` and
we can set `enableParallelBuilding` to speed up the compilation of
`libbcachefs.a`.
2024-05-28 19:32:15 +02:00
Thomas Mühlbacher
ce01c61ba5 build(nix): enable rustfmt check+formatter
with this, the gh actions ci will fail if submitted code does not adhere
to rustfmt rules.

additionally, running `nix fmt` will also format rust code.

because we want rules only supported by nightly rustfmt, and nixpkgs
doesn't have a nightly toolchain, we need to pull in another flake
input: fenix.
2024-05-27 19:30:26 -04:00
Thomas Mühlbacher
0e414b462f style: fix one straggler not caught by rustfmt
not sure why this wasn't picked up, maybe different versions of nightly
rustfmt?
2024-05-27 19:30:26 -04:00
Kent Overstreet
7efaf45d78 Update bcachefs sources to bc0fa834a738 bcachefs: Better fsck error message for key version 2024-05-27 19:17:49 -04:00
Kent Overstreet
067e072465 Update bcachefs sources to ea473c4a1a21 bcachefs: btree_gc can now handle unknown btrees 2024-05-27 19:04:42 -04:00
Kent Overstreet
9bb2977a1a Update bcachefs sources to 45845c32a41a fs: bcachefs: add missing MODULE_DESCRIPTION() 2024-05-27 17:59:22 -04:00
Christopher Fore
5a3011c48e doc: update subvolume destroy command to subvolume delete
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-26 21:36:01 -04:00
Kent Overstreet
aa985e6a44 Format with rustfmt
Note that we're using struct/enum align options, which require nightly.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-26 20:38:08 -04:00
Thomas Mühlbacher
5b216318b8 check_for_key before ask_for_passphrase
let's always first check if there is already a key in the keyring
available before we try to get the key from some more involved means.

Fixes: 
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-26 13:32:56 -04:00
Thomas Mühlbacher
6ba303e8bf fix unfortunate typo
causes mounting encrypted devices to become stuck in a busy loop.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-26 12:52:37 -04:00
Kent Overstreet
80167bf0a8 cmd_dump: Dump full btree nodes
We're still having issues with corrupted dumps when we try to dump only
the live part of btree nodes.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-26 12:51:26 -04:00
Kent Overstreet
1e35104d31 Revert dump blocksize change
It appears qemu-img chokes on qcow2 images with too many l1 entries

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-25 12:51:31 -04:00
Thomas Bertschinger
7bf821f3f9 check errno to determine fsck ioctl error
The error code is in errno, not the return value.

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-25 00:02:27 -04:00
koverstreet
ff44b8b96d
Merge pull request from intelfx/work/fix-naming
fusemount: unbreak build
2024-05-24 18:09:54 -04:00
Kent Overstreet
9cd7440649 cmd_dump: Dump btree nodes correctly
We were using sectors_written from the parent node - whoops

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-24 18:07:20 -04:00
Kent Overstreet
3f531df2b3 Update bcachefs sources to 254510a1c269 bcachefs: btree_ptr_sectors_written() now takes bkey_s_c 2024-05-24 18:07:20 -04:00
Ivan Shapovalov
72ad5766bd fusemount: unbreak build
Commit 477670f4 ("Update bcachefs sources to 07f9a27f1969 bcachefs: add
no_invalid_checks flag") changed capitalization of BTREE_ITER_* flags.
Update cmd_fusemount.c accordingly.

Fixes: 477670f4 ("Update bcachefs sources to 07f9a27f1969 bcachefs: add no_invalid_checks flag")
2024-05-24 22:56:50 +02:00
koverstreet
cd198e2b8e
Merge pull request from tmuehlbacher/make-nix-ci-useful
Make nix ci useful
2024-05-24 12:01:21 -04:00
Thomas Mühlbacher
88aa61eb95 ci: run nix build in workflow
so since up until the last merged changes, this entire gh action pretty
much equated to a no-op, afaict. and even now, the only thing i added in
PR  is a formatter check only for *.nix files.

i plan to add more checks soon that will be run by `nix flake check`.
but as of right now, adding this is the quickest way to make sure at
least something useful is done by this workflow.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-23 21:04:41 +02:00
Thomas Mühlbacher
45c8cc32a3 ci: fix NixOS misnomer
this workflow has nothing to do with NixOS, it's just running Nix on
Ubuntu.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-23 21:03:00 +02:00
koverstreet
0f5c8e0407
Merge pull request from tmuehlbacher/gh-action-fix
github action fix
2024-05-22 17:42:59 -04:00
Thomas Mühlbacher
368cdb8796 ci: fix ci by updating gh actions
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 23:20:16 +02:00
Thomas Mühlbacher
f40361c34f chore(editorconfig): add *.y{,a}ml
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 23:20:16 +02:00
koverstreet
764031a4aa
Merge pull request from tmuehlbacher/flake-overhaul
Flake overhaul
2024-05-22 16:58:18 -04:00
koverstreet
7d795ddb25
Merge pull request from tmuehlbacher/cargo-clippy
Fix clippy lints
2024-05-22 16:44:35 -04:00
Thomas Mühlbacher
56a9580aeb build(nix): add some packages to the dev shell
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
2e316499df build(nix): add treefmt-nix
currently still bare but can be extended with a number of different
formatters (rustfmt, clang-format, ...). For full list see
https://flake.parts/options/treefmt-nix

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
cc16402e4f build(nix): replace flake-utils with flake-parts
it also provides a way for abstracting `system` and provides optional
modules, like treefmt-nix.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
0fcdd67bf0 build(nix): rm nixpkgs overlay
it shouldn't really be our job to define an overlay. it doesn't do
anything for us, afaict, and is trivial to implement for downstream
users of the flake if they so desire.

also the overlay doesn't even overlay anything, there is no package
called `bcachefs` in nixpkgs.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
5e9d1953a2 build(nix): simplify devShell
much more DRY.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
eccefb381d style(nix): group together inputs attr
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
b91647aab8 style(nix): run nix fmt
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
e94c985640 build(nix): switch to new RFC style nixfmt
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
04a31f10e0 build(flake.lock): update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/fa804edfb7869c9fb230e174182a8a1a7e512c40' (2023-11-02)
  → 'github:nixos/nixpkgs/3eaeaeb6b1e08a016380c279f8846e0bd8808916' (2024-05-21)
• Updated input 'utils':
    'github:numtide/flake-utils/ff7b65b44d01cf9ba6a71320833626af21126384' (2023-09-12)
  → 'github:numtide/flake-utils/b1d9ab70662946ef0850d488da1c9019f3a9752a' (2024-03-11)

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
683710c068 chore(editorconfig): flesh out definitions
so it actually works.

Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:35:05 +02:00
Thomas Mühlbacher
3882d1b1e4 refactor: manually fix remaining clippy lints
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:33:40 +02:00
Thomas Mühlbacher
3488d4f15f refactor: cargo clippy --fix
Signed-off-by: Thomas Mühlbacher <tmuehlbacher@posteo.net>
2024-05-22 22:33:40 +02:00
Thomas Bertschinger
3ac510f6a4 add "bkey-type" option to list command
Only bkeys of the specified type will be printed.

Also, this reworks the error type in bch_bindgen to be able to
represent other kinds of error than just "invalid btree id".

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-09 17:29:08 -04:00
Kent Overstreet
477670f481 Update bcachefs sources to 07f9a27f1969 bcachefs: add no_invalid_checks flag 2024-05-09 16:26:14 -04:00
Kent Overstreet
5531accc97 cmd_dump: Fix missing sectors-to-bytes conversion
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-08 19:04:53 -04:00
Tony Asleson
128b569155 mount: Make udev_bcachefs_info more idiomatic
Signed-off-by: Tony Asleson <tasleson@redhat.com>
2024-05-07 12:20:49 -05:00
Tony Asleson
3d63b901c6 Handle mount with FS with 1 device
If the user passes a single device node during the mount and
we have no information for it in the udev db, we read up the
super block.  When we do this, if the FS only has 1 block device
we will simply go ahead and do the mount instead of walking
all the block devices and reading up super blocks looking for
devices with a matching FS UUID.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2024-05-07 12:20:49 -05:00
Tony Asleson
761ef99f91 Add env. variable BCACHEFS_BLOCK_SCAN
Introduce an env. variable for users that have a broken blkid which
renders the udev db as incomplete.  Only checks for the existence
of the variable, not its value.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2024-05-07 12:20:49 -05:00
Tony Asleson
1fb1898b24 mount: Leverage udev db
If the udev database contains information about bcachefs, utilize it.
Otherwise, resort to traversing block devices and checking for
bcachefs super blocks.

V2: Reduce number of places we call read_super_slient in interators

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2024-05-07 12:20:49 -05:00
Kent Overstreet
52904aa886 BCACHEFS_KERNEL_ONLY
Add an environment variable that indicates we prefer to run bcachefs
code in the kernel, not userspace - this is for the test environment
where it's easier to debug kernel code.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-05-04 15:28:24 -04:00
Thomas Bertschinger
2b8a0f0caf remove redundant "cmd_" prefix from functions in "commands"
It is more idiomatic to use `commands::mount` than
`commands::cmd_mount`.

No functionality changes intended by this patch.

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-04-30 21:16:09 -04:00
koverstreet
578f32a96e
Merge pull request from evanrichter/fix_device_add_args
Fix device add args
2024-04-29 12:57:27 -04:00
Evan Richter
a739671c0b add short arg parsers to device add command
Without the single char (with ':' if optarg expected) only the long
argument string would successfully parse.

For example, now "-lasdf" parses the same as "--label asdf"
2024-04-29 10:16:13 -06:00
Evan Richter
b832e3b2f7 remove --tier from device add getopt parser 2024-04-29 09:59:16 -06:00
Kent Overstreet
efbe47e2b4 Update bcachefs sources to c19cbaf6e7b0 bcachefs: Run upgrade/downgrade even in -o nochanges mode 2024-04-28 21:29:50 -04:00
Kent Overstreet
b9e48edba7 Update bcachefs sources to 035773e55b52 bcachefs: fix integer conversion bug 2024-04-25 16:25:29 -04:00
Kent Overstreet
ec2d118738 fix splice_fd_to_stdinout() when stdin is closed
We need to check when stdin has been closed - otherwise we'll spin
because select() will return immediately.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-04-25 00:43:47 -04:00
Kent Overstreet
b3677f3040 Merge branch 'man-bcachefs-subvolume-snapshot' of https://github.com/FedericoSchonborn/bcachefs-tools 2024-04-19 21:42:12 -04:00
Federico Damián Schonborn
b8b36900f8
bcachefs.8: subvolume delete -> subvolume snapshot
Signed-off-by: Federico Damián Schonborn <federicoschonborn@disroot.org>
2024-04-19 22:36:17 -03:00
Kent Overstreet
0e0aa31912 Update bcachefs sources to 0389c09b2fb7 bcachefs: Fix bio alloc in check_extent_checksum()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2024-04-17 17:34:56 -04:00
Christophe B Billheimer
ad41c2fb76 add mkinitcpio hook for Arch and sample /etc/mkinitcpio.conf 2018-07-28 22:54:36 -04:00
348 changed files with 33918 additions and 21059 deletions

View File

@ -1 +1 @@
10ca1f99f8c99a3d992b686cdc29d427807070e5
7fdc3fa3cb5fb561f5945b4de418d48d1a726a8d

View File

@ -1,6 +1,34 @@
indent_style = tab
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 8
indent_style = tab
insert_final_newline = true
max_line_length = 80
tab_width = 8
trim_trailing_whitespace = true
[.git/**]
max_line_length = 72
[*.nix]
indent_style = space
indent_size = 2
[*.y{,a}ml]
indent_size = 2
indent_style = space
[Cargo.toml]
indent_style = space
indent_size = 4
[*.rs]
indent_style = space
indent_size = 4
[*.sh]
indent_size = 4
indent_style = space

View File

@ -8,7 +8,7 @@ jobs:
name: bcachefs-tools-deb
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-22.04]
os: [ubuntu-22.04, ubuntu-24.04]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@ -21,6 +21,7 @@ jobs:
sudo apt-get update && sudo apt-get -y --no-install-recommends install \
valgrind \
equivs devscripts
grep -q 22.04 /etc/os-release && sed -i -e 's/ systemd-dev,/ systemd,/g' debian/control
mk-build-deps
sudo apt install ./bcachefs-tools-build-deps_*.deb
- name: Setup Rust
@ -32,7 +33,7 @@ jobs:
make -j`nproc` deb
mkdir dist && mv ../*.deb ./dist/
- name: Upload deb
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: bcachefs-tools-deb_${{ matrix.os }}
path: dist
@ -57,7 +58,7 @@ jobs:
make -j`nproc` rpm
mv ${HOME}/rpmbuild ./
- name: Upload rpm
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: bcachefs-tools-rpm
path: rpmbuild

21
.github/workflows/nix-flake-update.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: '0 0 1 * *' # Run monthly
push:
paths:
- 'flake.nix'
jobs:
lockfile:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v27
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@v21

31
.github/workflows/nix-flake.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Nix Flake actions
on:
pull_request:
push:
jobs:
nix-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
- id: set-matrix
name: Generate Nix Matrix
run: |
set -Eeu
matrix="$(nix eval --json '.#githubActions.matrix')"
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
nix-build:
name: ${{ matrix.name }} (${{ matrix.system }})
needs: nix-matrix
runs-on: ${{ matrix.os }}
strategy:
matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}}
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
- run: nix build -L '.#${{ matrix.attr }}'

View File

@ -1,21 +0,0 @@
name: "NixOS-Tests"
on:
pull_request:
push:
jobs:
nixos-flake-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v23
with:
extra_nix_config: |
experimental-features = nix-command flakes
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- uses: cachix/cachix-action@v12
with:
name: bcachefs-tools
# If you chose API tokens for write access OR if you have a private cache
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix flake show
- run: nix flake check --print-build-logs

3
.gitignore vendored
View File

@ -10,12 +10,11 @@ TAGS
cscope*
bcachefs-tools
compile_commands.json
tests/test_helper
tests/__pycache__/
# dot-files that we don't want to ignore
!.gitignore
!.github/dependabot.yml
!.github/workflows/
!.editorconfig
bcachefs-principles-of-operation.*

433
Cargo.lock generated
View File

@ -4,56 +4,57 @@ version = 3
[[package]]
name = "aho-corasick"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.11"
version = "0.6.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.6"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
@ -61,33 +62,30 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.79"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]]
name = "bcachefs-tools"
version = "0.3.1"
version = "1.25.0"
dependencies = [
"anyhow",
"bch_bindgen",
"byteorder",
"clap",
"clap_complete",
"colored",
"either",
"env_logger",
"errno 0.2.8",
"libc",
"log",
"rpassword",
"owo-colors",
"rustix",
"strum",
"strum_macros",
"udev",
"uuid",
"zeroize",
]
[[package]]
@ -98,8 +96,6 @@ dependencies = [
"bindgen",
"bitfield",
"bitflags 1.3.2",
"byteorder",
"memoffset",
"paste",
"pkg-config",
"uuid",
@ -107,11 +103,11 @@ dependencies = [
[[package]]
name = "bindgen"
version = "0.69.4"
version = "0.69.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
dependencies = [
"bitflags 2.4.2",
"bitflags 2.6.0",
"cexpr",
"clang-sys",
"itertools",
@ -142,23 +138,17 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.2"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "cc"
version = "1.0.83"
version = "1.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1"
dependencies = [
"libc",
"shlex",
]
[[package]]
@ -178,9 +168,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.7.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
@ -189,9 +179,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.4.18"
version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [
"clap_builder",
"clap_derive",
@ -199,9 +189,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.4.18"
version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [
"anstream",
"anstyle",
@ -212,18 +202,18 @@ dependencies = [
[[package]]
name = "clap_complete"
version = "4.4.10"
version = "4.5.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb745187d7f4d76267b37485a65e0149edd0e91a4cfcdd3f27524ad86cee9f3"
checksum = "9646e2e245bf62f45d39a0f3f36f1171ad1ea0d6967fd114bca72cb02a8fcdfb"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
version = "4.4.7"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
@ -233,31 +223,30 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.6.0"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "colorchoice"
version = "1.0.0"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "colored"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
dependencies = [
"lazy_static",
"windows-sys 0.48.0",
]
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
[[package]]
name = "either"
version = "1.9.0"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "env_logger"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
"log",
]
[[package]]
name = "errno"
@ -272,9 +261,9 @@ dependencies = [
[[package]]
name = "errno"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
@ -298,9 +287,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "heck"
version = "0.4.1"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "home"
@ -311,6 +300,12 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.12.1"
@ -322,9 +317,9 @@ dependencies = [
[[package]]
name = "lazy_static"
version = "1.4.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lazycell"
@ -334,18 +329,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.153"
version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "libloading"
version = "0.8.1"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-sys 0.48.0",
"windows-targets",
]
[[package]]
@ -360,30 +355,21 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
version = "0.4.13"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "log"
version = "0.4.20"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.7.1"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "memoffset"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
@ -403,27 +389,33 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.19.0"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "owo-colors"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56"
[[package]]
name = "paste"
version = "1.0.14"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pkg-config"
version = "0.3.29"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "prettyplease"
version = "0.2.16"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"
checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
dependencies = [
"proc-macro2",
"syn",
@ -431,27 +423,27 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.78"
version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.10.3"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
dependencies = [
"aho-corasick",
"memchr",
@ -461,9 +453,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.5"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
@ -472,30 +464,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.2"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rpassword"
version = "7.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f"
dependencies = [
"libc",
"rtoolbox",
"windows-sys 0.48.0",
]
[[package]]
name = "rtoolbox"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e"
dependencies = [
"libc",
"windows-sys 0.48.0",
]
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustc-hash"
@ -505,17 +476,23 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.31"
version = "0.38.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
dependencies = [
"bitflags 2.4.2",
"errno 0.3.8",
"bitflags 2.6.0",
"errno 0.3.9",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "rustversion"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "shlex"
version = "1.3.0"
@ -524,15 +501,37 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "strsim"
version = "0.10.0"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "strum"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "2.0.48"
version = "2.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
dependencies = [
"proc-macro2",
"quote",
@ -541,12 +540,12 @@ dependencies = [
[[package]]
name = "terminal_size"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
dependencies = [
"rustix",
"windows-sys 0.48.0",
"windows-sys 0.59.0",
]
[[package]]
@ -562,21 +561,21 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.12"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "utf8parse"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.7.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
[[package]]
name = "which"
@ -612,134 +611,104 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@ -1,17 +1,23 @@
[workspace]
resolver = "2"
default-members = [".", "bch_bindgen"]
[package]
name = "bcachefs-tools"
version = "0.3.1"
version = "1.25.0"
authors = ["Yuxuan Shui <yshuiv7@gmail.com>", "Kayla Firestack <dev@kaylafire.me>", "Kent Overstreet <kent.overstreet@linux.dev>" ]
edition = "2021"
rust-version = "1.70"
rust-version = "1.77.0"
[[bin]]
name = "bcachefs"
path = "src/bcachefs.rs"
[features]
fuse = []
[dependencies]
log = { version = "0.4", features = ["std"] }
colored = "2"
clap = { version = "4.0.32", features = ["derive", "wrap_help"] }
clap_complete = "4.3.2"
anyhow = "1.0"
@ -20,6 +26,16 @@ udev = "0.7.0"
uuid = "1.2.2"
errno = "0.2"
either = "1.5"
rpassword = "7"
bch_bindgen = { path = "bch_bindgen" }
byteorder = "1.3"
strum = { version = "0.26", features = ["derive"] }
strum_macros = "0.26"
zeroize = { version = "1", features = ["std", "zeroize_derive"] }
rustix = { version = "0.38.34", features = ["termios"] }
owo-colors = "4"
[dependencies.env_logger]
version = "0.10"
default-features = false
[profile.release]
strip = "none"

View File

@ -17,8 +17,9 @@ Build dependencies:
* zlib1g
In addition a recent Rust toolchain is required (rustc, cargo), either by using
[rustup](https://rustup.rs/) or make sure to use a distribution where rustc (>=1.65)
is available.
[rustup](https://rustup.rs/) or make sure to use a distribution where a recent
enough rustc is available. Please check `rust-version` in `Cargo.toml` to see
the minimum supported Rust version (MSRV).
``` shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path
@ -33,12 +34,24 @@ apt install -y pkg-config libaio-dev libblkid-dev libkeyutils-dev \
python3 python3-docutils libclang-dev debhelper dh-python
```
Fedora: install the "Development tools" group along with:
Starting from Debian Trixie and Ubuntu 23.10, you will additionally need:
```shell
dnf install -y libaio-devel libsodium-devel \
apt install -y systemd-dev
```
Fedora: install build dependencies either with `dnf builddep bcachefs-tools` or with:
```shell
dnf install -y @c-development libaio-devel libsodium-devel \
libblkid-devel libzstd-devel zlib-devel userspace-rcu-devel \
lz4-devel libuuid-devel valgrind-devel keyutils-libs-devel \
findutils udev systemd-devel llvm-devel
findutils systemd-devel clang-devel llvm-devel rust cargo
```
openSUSE: install build dependencies with:
```shell
zypper in -y libaio-devel libsodium-devel libblkid-devel liburcu-devel \
libzstd-devel zlib-devel liblz4-devel libuuid-devel valgrind-devel \
keyutils-devel findutils udev systemd-devel llvm-devel
```
Arch: install bcachefs-tools-git from the AUR.
@ -74,6 +87,11 @@ Arch:
pacman -S fuse3
```
openSUSE:
```shell
zypper in -y fuse3-devel
```
Then, make using the `BCACHEFS_FUSE` environment variable (make clean first if
previously built without fuse support):

View File

@ -1,4 +1,4 @@
VERSION=1.7.0
VERSION=1.25.0
PREFIX?=/usr/local
LIBEXECDIR?=$(PREFIX)/libexec
@ -22,6 +22,13 @@ else
CARGO_CLEAN_ARGS = --quiet
endif
# when cross compiling, cargo places the built binary in a different location
ifdef CARGO_BUILD_TARGET
BUILT_BIN = target/$(CARGO_BUILD_TARGET)/release/bcachefs
else
BUILT_BIN = target/release/bcachefs
endif
# Prevent recursive expansions of $(CFLAGS) to avoid repeatedly performing
# compile tests
CFLAGS:=$(CFLAGS)
@ -73,12 +80,13 @@ CFLAGS+=$(call cc-disable-warning, zero-length-array)
CFLAGS+=$(call cc-disable-warning, shift-overflow)
CFLAGS+=$(call cc-disable-warning, enum-conversion)
CFLAGS+=$(call cc-disable-warning, gnu-variable-sized-type-not-at-end)
export RUSTFLAGS=-C default-linker-libraries
PKGCONFIG_LIBS="blkid uuid liburcu libsodium zlib liblz4 libzstd libudev libkeyutils udev"
PKGCONFIG_LIBS="blkid uuid liburcu libsodium zlib liblz4 libzstd libudev libkeyutils"
ifdef BCACHEFS_FUSE
PKGCONFIG_LIBS+="fuse3 >= 3.7"
CFLAGS+=-DBCACHEFS_FUSE
export RUSTFLAGS=--cfg fuse
RUSTFLAGS+=--cfg feature="fuse"
endif
PKGCONFIG_CFLAGS:=$(shell $(PKG_CONFIG) --cflags $(PKGCONFIG_LIBS))
@ -152,9 +160,6 @@ all: bcachefs $(optional_build)
debug: CFLAGS+=-Werror -DCONFIG_BCACHEFS_DEBUG=y -DCONFIG_VALGRIND=y
debug: bcachefs
.PHONY: tests
tests: tests/test_helper
.PHONY: TAGS tags
TAGS:
ctags -e -R .
@ -178,13 +183,9 @@ RUST_SRCS:=$(shell find src bch_bindgen/src -type f -iname '*.rs')
bcachefs: $(BCACHEFS_DEPS) $(RUST_SRCS)
$(Q)$(CARGO_BUILD)
libbcachefs.a: $(filter-out ./tests/%.o, $(OBJS))
libbcachefs.a: $(OBJS)
@echo " [AR] $@"
$(Q)ar -rc $@ $+
tests/test_helper: $(filter ./tests/%.o, $(OBJS))
@echo " [LD] $@"
$(Q)$(CC) $(LDFLAGS) $+ $(LOADLIBES) $(LDLIBS) -o $@
$(Q)$(AR) -rc $@ $+
# If the version string differs from the last build, update the last version
ifneq ($(VERSION),$(shell cat .version 2>/dev/null))
@ -201,7 +202,7 @@ cmd_version.o : .version
install: INITRAMFS_HOOK=$(INITRAMFS_DIR)/hooks/bcachefs
install: INITRAMFS_SCRIPT=$(INITRAMFS_DIR)/scripts/local-premount/bcachefs
install: bcachefs $(optional_install)
$(INSTALL) -m0755 -D target/release/bcachefs -t $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0755 -D $(BUILT_BIN) -t $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0644 -D bcachefs.8 -t $(DESTDIR)$(PREFIX)/share/man/man8/
$(INSTALL) -m0755 -D initramfs/script $(DESTDIR)$(INITRAMFS_SCRIPT)
$(INSTALL) -m0755 -D initramfs/hook $(DESTDIR)$(INITRAMFS_HOOK)
@ -225,7 +226,7 @@ install_systemd: $(systemd_services) $(systemd_libexecfiles)
.PHONY: clean
clean:
@echo "Cleaning all"
$(Q)$(RM) libbcachefs.a c_src/libbcachefs.a tests/test_helper .version *.tar.xz $(OBJS) $(DEPS) $(DOCGENERATED)
$(Q)$(RM) libbcachefs.a c_src/libbcachefs.a .version *.tar.xz $(OBJS) $(DEPS) $(DOCGENERATED)
$(Q)$(CARGO_CLEAN)
$(Q)$(RM) -f $(built_scripts)
@ -254,6 +255,7 @@ update-bcachefs-sources:
test -d libbcachefs || mkdir libbcachefs
cp $(LINUX_DIR)/fs/bcachefs/*.[ch] libbcachefs/
git add libbcachefs/*.[ch]
git rm -f libbcachefs/mean_and_variance_test.c
cp $(LINUX_DIR)/include/linux/closure.h include/linux/
git add include/linux/closure.h
cp $(LINUX_DIR)/lib/closure.c linux/
@ -293,7 +295,7 @@ tarball: $(SRCTARXZ)
$(SRCTARXZ) : .gitcensus
$(Q)tar --transform "s,^,$(SRCDIR)/," -Jcf $(SRCDIR).tar.xz \
`cat .gitcensus`
`cat .gitcensus`
@echo Wrote: $@
.PHONY: .gitcensus

View File

@ -13,7 +13,7 @@ cc-cross-prefix = $(firstword $(foreach c, $(1), \
$(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
# output directory for tests below
TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
TMPOUT = .tmp_$$$$
# try-run
# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
@ -53,13 +53,11 @@ cc-option = $(call __cc-option, $(CC),\
# cc-option-yn
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
cc-option-yn = $(call try-run,\
$(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
cc-option-yn = $(if $(call cc-option,$1),y,n)
# cc-disable-warning
# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
cc-disable-warning = $(call try-run,\
$(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
cc-disable-warning = $(if $(call cc-option,-W$(strip $1)),-Wno-$(strip $1))
# gcc-min-version
# Usage: cflags-$(call gcc-min-version, 70100) += -foo
@ -72,3 +70,20 @@ clang-min-version = $(call test-ge, $(CONFIG_CLANG_VERSION), $1)
# ld-option
# Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y)
ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3))
# __rustc-option
# Usage: MY_RUSTFLAGS += $(call __rustc-option,$(RUSTC),$(MY_RUSTFLAGS),-Cinstrument-coverage,-Zinstrument-coverage)
# TODO: remove RUSTC_BOOTSTRAP=1 when we raise the minimum GNU Make version to 4.4
__rustc-option = $(call try-run,\
echo '#![allow(missing_docs)]#![feature(no_core)]#![no_core]' | RUSTC_BOOTSTRAP=1\
$(1) --sysroot=/dev/null $(filter-out --sysroot=/dev/null,$(2)) $(3)\
--crate-type=rlib --out-dir=$(TMPOUT) --emit=obj=- - >/dev/null,$(3),$(4))
# rustc-option
# Usage: rustflags-y += $(call rustc-option,-Cinstrument-coverage,-Zinstrument-coverage)
rustc-option = $(call __rustc-option, $(RUSTC),\
$(KBUILD_RUSTFLAGS),$(1),$(2))
# rustc-option-yn
# Usage: flag := $(call rustc-option-yn,-Cinstrument-coverage)
rustc-option-yn = $(if $(call rustc-option,$1),y,n)

View File

@ -0,0 +1,15 @@
#!/usr/bin/ash
run_hook() {
local rootdev
if rootdev="$(resolve_device "$root")" && bcachefs unlock -c "$rootdev" >/dev/null 2>&1
then
echo "Unlocking $rootdev:"
while true
do
bcachefs unlock "$rootdev" && break
done
fi
}
# vim: set ft=sh ts=4 sw=4 et:

View File

@ -0,0 +1,16 @@
#!/bin/bash
build() {
add_module bcachefs
add_binary bcachefs
add_runscript
}
help() {
cat <<HELPEOF
This hook is for getting the bcachefs unlock prompt at boot
HELPEOF
}
# vim set ft=sh ts=4 sw=4 et:

66
arch/etc/mkinitcpio.conf Normal file
View File

@ -0,0 +1,66 @@
# vim:set ft=sh
# MODULES
# The following modules are loaded before any boot hooks are
# run. Advanced users may wish to specify all system modules
# in this array. For instance:
# MODULES=(piix ide_disk reiserfs)
MODULES=(bcachefs)
# BINARIES
# This setting includes any additional binaries a given user may
# wish into the CPIO image. This is run last, so it may be used to
# override the actual binaries included by a given hook
# BINARIES are dependency parsed, so you may safely ignore libraries
BINARIES=(bcachefs)
# FILES
# This setting is similar to BINARIES above, however, files are added
# as-is and are not parsed in any way. This is useful for config files.
FILES=()
# HOOKS
# This is the most important setting in this file. The HOOKS control the
# modules and scripts added to the image, and what happens at boot time.
# Order is important, and it is recommended that you do not change the
# order in which HOOKS are added. Run 'mkinitcpio -H <hook name>' for
# help on a given hook.
# 'base' is _required_ unless you know precisely what you are doing.
# 'udev' is _required_ in order to automatically load modules
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
# Examples:
## This setup specifies all modules in the MODULES setting above.
## No raid, lvm2, or encrypted root is needed.
# HOOKS="base"
#
## This setup will autodetect all modules for your system and should
## work as a sane default
# HOOKS="base udev autodetect block filesystems"
#
## This setup will generate a 'full' image which supports most systems.
## No autodetection is done.
# HOOKS="base udev block filesystems"
#
## This setup assembles a pata mdadm array with an encrypted root FS.
## Note: See 'mkinitcpio -H mdadm' for more information on raid devices.
# HOOKS="base udev block mdadm encrypt filesystems"
#
## This setup loads an lvm2 volume group on a usb device.
# HOOKS="base udev block lvm2 filesystems"
#
## NOTE: If you have /usr on a separate partition, you MUST include the
# usr, fsck and shutdown hooks.
HOOKS=(base udev autodetect modconf block filesystems bcachefs keyboard fsck)
# COMPRESSION
# Use this to compress the initramfs image. By default, gzip compression
# is used. Use 'cat' to create an uncompressed image.
#COMPRESSION="gzip"
#COMPRESSION="bzip2"
#COMPRESSION="lzma"
#COMPRESSION="xz"
#COMPRESSION="lzop"
#COMPRESSION="lz4"
# COMPRESSION_OPTIONS
# Additional options for the compressor
#COMPRESSION_OPTIONS=""

View File

@ -20,7 +20,7 @@ which are documented in detail below:
Format one or a list of devices with bcachefs data structures.
.It Ic show-super
Dump superblock information to stdout.
.It Ic set-option
.It Ic set-fs-option
Set a filesystem option
.El
.Ss Mount commands
@ -91,7 +91,7 @@ Add default superblock, after bcachefs migrate
.El
.Ss Commands for operating on files in a bcachefs filesystem
.Bl -tag -width 18n -compact
.It Ic setattr
.It Ic set-file-option
Set various per file attributes
.El
.Ss Commands for debugging
@ -248,7 +248,7 @@ List of sections to print
.It Fl l , Fl -layout
Print superblock layout
.El
.It Nm Ic set-option Oo Ar options Oc Ar device
.It Nm Ic set-fs-option Oo Ar options Oc Ar device
.Bl -tag -width Ds
.It Fl -errors Ns = Ns ( Cm continue | ro | panic )
Action to take on filesystem error
@ -497,7 +497,7 @@ Resize journal on a device
Create a new subvolume
.It Ic subvolume delete Oo Ar options Oc Ar path
Delete an existing subvolume
.It Ic subvolume delete Oo Ar options Oc Ar source dest
.It Ic subvolume snapshot Oo Ar options Oc Ar source dest
Create a snapshot of
.Ar source
at
@ -574,7 +574,7 @@ Offset of existing superblock
.El
.Sh Commands for operating on files in a bcachefs filesystem
.Bl -tag -width Ds
.It Nm Ic setattr Oo Ar options Oc Ar devices\ ...
.It Nm Ic set-file-option Oo Ar options Oc Ar devices\ ...
.Bl -tag -width Ds
.It Fl -data_replicas Ns = Ns Ar number
Number of data replicas

View File

@ -3,6 +3,7 @@ name = "bch_bindgen"
version = "0.1.0"
authors = [ "Kayla Firestack <dev@kaylafire.me>", "Yuxuan Shui <yshuiv7@gmail.com>", "Kent Overstreet <kent.overstreet@linux.dev>" ]
edition = "2021"
rust-version = "1.77"
[lib]
crate-type = ["lib"]
@ -12,8 +13,6 @@ crate-type = ["lib"]
anyhow = "1.0"
uuid = "1.2.2"
bitfield = "0.14.0"
memoffset = "0.8.0"
byteorder = "1.3"
bitflags = "1.3.2"
paste = "1.0.11"

View File

@ -29,8 +29,7 @@ fn main() {
.to_string(),
)
.clang_args(
urcu
.include_paths
urcu.include_paths
.iter()
.map(|p| format!("-I{}", p.display())),
)
@ -64,7 +63,6 @@ fn main() {
.allowlist_function("printbuf.*")
.blocklist_type("rhash_lock_head")
.blocklist_type("srcu_struct")
.blocklist_type("bch_ioctl_data.*")
.allowlist_var("BCH_.*")
.allowlist_var("KEY_SPEC_.*")
.allowlist_var("Fix753_.*")

View File

@ -1,3 +0,0 @@
# Default settings, i.e. idiomatic rust
edition = "2021"
newline_style = "Unix"

View File

@ -3,6 +3,8 @@
#![allow(non_snake_case)]
#![allow(unused)]
use crate::c;
include!(concat!(env!("OUT_DIR"), "/bcachefs.rs"));
use bitfield::bitfield;
@ -16,7 +18,7 @@ bitfield! {
pub struct bch_crypt_flags(u64);
pub TYPE, _: 4, 0;
}
use memoffset::offset_of;
use std::mem::offset_of;
impl bch_sb_field_crypt {
pub fn scrypt_flags(&self) -> Option<bch_scrypt_flags> {
use std::convert::TryInto;
@ -59,12 +61,15 @@ impl bch_sb {
uuid::Uuid::from_bytes(self.user_uuid.b)
}
pub fn number_of_devices(&self) -> u32 {
unsafe { c::bch2_sb_nr_devices(self) }
}
/// Get the nonce used to encrypt the superblock
pub fn nonce(&self) -> nonce {
use byteorder::{LittleEndian, ReadBytesExt};
let mut internal_uuid = &self.uuid.b[..];
let dword1 = internal_uuid.read_u32::<LittleEndian>().unwrap();
let dword2 = internal_uuid.read_u32::<LittleEndian>().unwrap();
let [a, b, c, d, e, f, g, h, _rest @ ..] = self.uuid.b;
let dword1 = u32::from_le_bytes([a, b, c, d]);
let dword2 = u32::from_le_bytes([e, f, g, h]);
nonce {
d: [0, 0, dword1, dword2],
}

View File

@ -1,17 +1,17 @@
#![allow(non_camel_case_types)]
use crate::btree::BtreeIter;
use crate::c;
use crate::fs::Fs;
use crate::btree::BtreeIter;
use crate::printbuf_to_formatter;
use std::fmt;
use std::marker::PhantomData;
use std::mem::transmute;
pub struct BkeySC<'a> {
pub k: &'a c::bkey,
pub v: &'a c::bch_val,
pub(crate) iter: PhantomData<&'a mut BtreeIter<'a>>
pub k: &'a c::bkey,
pub v: &'a c::bch_val,
pub(crate) iter: PhantomData<&'a mut BtreeIter<'a>>,
}
pub enum BkeyValC<'a> {
@ -49,59 +49,66 @@ pub enum BkeyValC<'a> {
snapshot_tree(&'a c::bch_snapshot_tree),
logged_op_truncate(&'a c::bch_logged_op_truncate),
logged_op_finsert(&'a c::bch_logged_op_finsert),
accounting(&'a c::bch_accounting),
inode_alloc_cursor(&'a c::bch_inode_alloc_cursor),
}
impl<'a, 'b> BkeySC<'a> {
unsafe fn to_raw(&self) -> c::bkey_s_c {
c::bkey_s_c { k: self.k, v: self.v }
c::bkey_s_c {
k: self.k,
v: self.v,
}
}
pub fn to_text(&'a self, fs: &'b Fs) -> BkeySCToText<'a, 'b> {
BkeySCToText { k: self, fs }
}
pub fn v(&'a self) -> BkeyValC {
pub fn v(&'a self) -> BkeyValC<'a> {
unsafe {
let ty: c::bch_bkey_type = transmute(self.k.type_ as u32);
use c::bch_bkey_type::*;
use BkeyValC::*;
match ty {
KEY_TYPE_deleted => deleted,
KEY_TYPE_whiteout => whiteout,
KEY_TYPE_error => error,
KEY_TYPE_cookie => cookie(transmute(self.v)),
KEY_TYPE_hash_whiteout => hash_whiteout(transmute(self.v)),
KEY_TYPE_btree_ptr => btree_ptr(transmute(self.v)),
KEY_TYPE_extent => extent(transmute(self.v)),
KEY_TYPE_reservation => reservation(transmute(self.v)),
KEY_TYPE_inode => inode(transmute(self.v)),
KEY_TYPE_inode_generation => inode_generation(transmute(self.v)),
KEY_TYPE_dirent => dirent(transmute(self.v)),
KEY_TYPE_xattr => xattr(transmute(self.v)),
KEY_TYPE_alloc => alloc(transmute(self.v)),
KEY_TYPE_quota => quota(transmute(self.v)),
KEY_TYPE_stripe => stripe(transmute(self.v)),
KEY_TYPE_reflink_p => reflink_p(transmute(self.v)),
KEY_TYPE_reflink_v => reflink_v(transmute(self.v)),
KEY_TYPE_inline_data => inline_data(transmute(self.v)),
KEY_TYPE_btree_ptr_v2 => btree_ptr_v2(transmute(self.v)),
KEY_TYPE_indirect_inline_data => indirect_inline_data(transmute(self.v)),
KEY_TYPE_alloc_v2 => alloc_v2(transmute(self.v)),
KEY_TYPE_subvolume => subvolume(transmute(self.v)),
KEY_TYPE_snapshot => snapshot(transmute(self.v)),
KEY_TYPE_inode_v2 => inode_v2(transmute(self.v)),
KEY_TYPE_alloc_v3 => inode_v3(transmute(self.v)),
KEY_TYPE_set => set,
KEY_TYPE_lru => lru(transmute(self.v)),
KEY_TYPE_alloc_v4 => alloc_v4(transmute(self.v)),
KEY_TYPE_backpointer => backpointer(transmute(self.v)),
KEY_TYPE_inode_v3 => inode_v3(transmute(self.v)),
KEY_TYPE_bucket_gens => bucket_gens(transmute(self.v)),
KEY_TYPE_snapshot_tree => snapshot_tree(transmute(self.v)),
KEY_TYPE_logged_op_truncate => logged_op_truncate(transmute(self.v)),
KEY_TYPE_logged_op_finsert => logged_op_finsert(transmute(self.v)),
KEY_TYPE_MAX => unreachable!(),
KEY_TYPE_deleted => deleted,
KEY_TYPE_whiteout => whiteout,
KEY_TYPE_error => error,
KEY_TYPE_cookie => cookie(transmute(self.v)),
KEY_TYPE_hash_whiteout => hash_whiteout(transmute(self.v)),
KEY_TYPE_btree_ptr => btree_ptr(transmute(self.v)),
KEY_TYPE_extent => extent(transmute(self.v)),
KEY_TYPE_reservation => reservation(transmute(self.v)),
KEY_TYPE_inode => inode(transmute(self.v)),
KEY_TYPE_inode_generation => inode_generation(transmute(self.v)),
KEY_TYPE_dirent => dirent(transmute(self.v)),
KEY_TYPE_xattr => xattr(transmute(self.v)),
KEY_TYPE_alloc => alloc(transmute(self.v)),
KEY_TYPE_quota => quota(transmute(self.v)),
KEY_TYPE_stripe => stripe(transmute(self.v)),
KEY_TYPE_reflink_p => reflink_p(transmute(self.v)),
KEY_TYPE_reflink_v => reflink_v(transmute(self.v)),
KEY_TYPE_inline_data => inline_data(transmute(self.v)),
KEY_TYPE_btree_ptr_v2 => btree_ptr_v2(transmute(self.v)),
KEY_TYPE_indirect_inline_data => indirect_inline_data(transmute(self.v)),
KEY_TYPE_alloc_v2 => alloc_v2(transmute(self.v)),
KEY_TYPE_subvolume => subvolume(transmute(self.v)),
KEY_TYPE_snapshot => snapshot(transmute(self.v)),
KEY_TYPE_inode_v2 => inode_v2(transmute(self.v)),
KEY_TYPE_alloc_v3 => inode_v3(transmute(self.v)),
KEY_TYPE_set => set,
KEY_TYPE_lru => lru(transmute(self.v)),
KEY_TYPE_alloc_v4 => alloc_v4(transmute(self.v)),
KEY_TYPE_backpointer => backpointer(transmute(self.v)),
KEY_TYPE_inode_v3 => inode_v3(transmute(self.v)),
KEY_TYPE_bucket_gens => bucket_gens(transmute(self.v)),
KEY_TYPE_snapshot_tree => snapshot_tree(transmute(self.v)),
KEY_TYPE_logged_op_truncate => logged_op_truncate(transmute(self.v)),
KEY_TYPE_logged_op_finsert => logged_op_finsert(transmute(self.v)),
KEY_TYPE_accounting => accounting(transmute(self.v)),
KEY_TYPE_inode_alloc_cursor => inode_alloc_cursor(transmute(self.v)),
KEY_TYPE_MAX => unreachable!(),
}
}
}
@ -109,7 +116,11 @@ impl<'a, 'b> BkeySC<'a> {
impl<'a> From<&'a c::bkey_i> for BkeySC<'a> {
fn from(k: &'a c::bkey_i) -> Self {
BkeySC { k: &k.k, v: &k.v, iter: PhantomData }
BkeySC {
k: &k.k,
v: &k.v,
iter: PhantomData,
}
}
}
@ -121,7 +132,9 @@ pub struct BkeySCToText<'a, 'b> {
impl<'a, 'b> fmt::Display for BkeySCToText<'a, 'b> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {
printbuf_to_formatter(f, |buf| c::bch2_bkey_val_to_text(buf, self.fs.raw, self.k.to_raw()))
printbuf_to_formatter(f, |buf| {
c::bch2_bkey_val_to_text(buf, self.fs.raw, self.k.to_raw())
})
}
}
}

View File

@ -1,23 +1,26 @@
use crate::SPOS_MAX;
use crate::c;
use crate::bkey::BkeySC;
use crate::fs::Fs;
use crate::c;
use crate::errcode::{bch_errcode, errptr_to_result_c};
use crate::fs::Fs;
use crate::printbuf_to_formatter;
use crate::SPOS_MAX;
use bitflags::bitflags;
use std::fmt;
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use bitflags::bitflags;
pub struct BtreeTrans<'f> {
raw: *mut c::btree_trans,
fs: PhantomData<&'f Fs>
raw: *mut c::btree_trans,
fs: PhantomData<&'f Fs>,
}
impl<'f> BtreeTrans<'f> {
pub fn new(fs: &'f Fs) -> BtreeTrans {
pub fn new(fs: &'f Fs) -> BtreeTrans<'f> {
unsafe {
BtreeTrans { raw: &mut *c::__bch2_trans_get(fs.raw, 0), fs: PhantomData }
BtreeTrans {
raw: &mut *c::__bch2_trans_get(fs.raw, 0),
fs: PhantomData,
}
}
}
}
@ -25,36 +28,41 @@ impl<'f> BtreeTrans<'f> {
impl<'f> Drop for BtreeTrans<'f> {
fn drop(&mut self) {
unsafe { c::bch2_trans_put(&mut *self.raw) }
}
}
}
bitflags! {
pub struct BtreeIterFlags: u16 {
const SLOTS = c::BTREE_ITER_SLOTS as u16;
const INTENT = c::BTREE_ITER_INTENT as u16;
const PREFETCH = c::BTREE_ITER_PREFETCH as u16;
const IS_EXTENTS = c::BTREE_ITER_IS_EXTENTS as u16;
const NOT_EXTENTS = c::BTREE_ITER_NOT_EXTENTS as u16;
const CACHED = c::BTREE_ITER_CACHED as u16;
const KEY_CACHED = c::BTREE_ITER_WITH_KEY_CACHE as u16;
const WITH_UPDATES = c::BTREE_ITER_WITH_UPDATES as u16;
const WITH_JOURNAL = c::BTREE_ITER_WITH_JOURNAL as u16;
const __ALL_SNAPSHOTS = c::__BTREE_ITER_ALL_SNAPSHOTS as u16;
const ALL_SNAPSHOTS = c::BTREE_ITER_ALL_SNAPSHOTS as u16;
const FILTER_SNAPSHOTS = c::BTREE_ITER_FILTER_SNAPSHOTS as u16;
const NOPRESERVE = c::BTREE_ITER_NOPRESERVE as u16;
const CACHED_NOFILL = c::BTREE_ITER_CACHED_NOFILL as u16;
const KEY_CACHE_FILL = c::BTREE_ITER_KEY_CACHE_FILL as u16;
const SLOTS = c::btree_iter_update_trigger_flags::BTREE_ITER_slots as u16;
const INTENT = c::btree_iter_update_trigger_flags::BTREE_ITER_intent as u16;
const PREFETCH = c::btree_iter_update_trigger_flags::BTREE_ITER_prefetch as u16;
const IS_EXTENTS = c::btree_iter_update_trigger_flags::BTREE_ITER_is_extents as u16;
const NOT_EXTENTS = c::btree_iter_update_trigger_flags::BTREE_ITER_not_extents as u16;
const CACHED = c::btree_iter_update_trigger_flags::BTREE_ITER_cached as u16;
const KEY_CACHED = c::btree_iter_update_trigger_flags::BTREE_ITER_with_key_cache as u16;
const WITH_UPDATES = c::btree_iter_update_trigger_flags::BTREE_ITER_with_updates as u16;
const WITH_JOURNAL = c::btree_iter_update_trigger_flags::BTREE_ITER_with_journal as u16;
const SNAPSHOT_FIELD = c::btree_iter_update_trigger_flags::BTREE_ITER_snapshot_field as u16;
const ALL_SNAPSHOTS = c::btree_iter_update_trigger_flags::BTREE_ITER_all_snapshots as u16;
const FILTER_SNAPSHOTS = c::btree_iter_update_trigger_flags::BTREE_ITER_filter_snapshots as u16;
const NOPRESERVE = c::btree_iter_update_trigger_flags::BTREE_ITER_nopreserve as u16;
const CACHED_NOFILL = c::btree_iter_update_trigger_flags::BTREE_ITER_cached_nofill as u16;
const KEY_CACHE_FILL = c::btree_iter_update_trigger_flags::BTREE_ITER_key_cache_fill as u16;
}
}
pub struct BtreeIter<'t> {
raw: c::btree_iter,
trans: PhantomData<&'t BtreeTrans<'t>>,
raw: c::btree_iter,
trans: PhantomData<&'t BtreeTrans<'t>>,
}
impl<'t> BtreeIter<'t> {
pub fn new(trans: &'t BtreeTrans<'t>, btree: c::btree_id, pos: c::bpos, flags: BtreeIterFlags) -> BtreeIter<'t> {
pub fn new(
trans: &'t BtreeTrans<'t>,
btree: c::btree_id,
pos: c::bpos,
flags: BtreeIterFlags,
) -> BtreeIter<'t> {
unsafe {
let mut iter: MaybeUninit<c::btree_iter> = MaybeUninit::uninit();
@ -63,30 +71,52 @@ impl<'t> BtreeIter<'t> {
iter.as_mut_ptr(),
btree,
pos,
flags.bits as u32);
flags.bits as u32,
);
BtreeIter { raw: iter.assume_init(), trans: PhantomData }
BtreeIter {
raw: iter.assume_init(),
trans: PhantomData,
}
}
}
pub fn peek_upto<'i>(&'i mut self, end: c::bpos) -> Result<Option<BkeySC>, bch_errcode> {
pub fn peek_max<'i>(&'i mut self, end: c::bpos) -> Result<Option<BkeySC<'i>>, bch_errcode> {
unsafe {
let k = c::bch2_btree_iter_peek_upto(&mut self.raw, end);
errptr_to_result_c(k.k)
.map(|_| if !k.k.is_null() { Some(BkeySC { k: &*k.k, v: &*k.v, iter: PhantomData }) } else { None } )
let k = c::bch2_btree_iter_peek_max(&mut self.raw, end);
errptr_to_result_c(k.k).map(|_| {
if !k.k.is_null() {
Some(BkeySC {
k: &*k.k,
v: &*k.v,
iter: PhantomData,
})
} else {
None
}
})
}
}
pub fn peek(&mut self) -> Result<Option<BkeySC>, bch_errcode> {
self.peek_upto(SPOS_MAX)
self.peek_max(SPOS_MAX)
}
pub fn peek_and_restart(&mut self) -> Result<Option<BkeySC>, bch_errcode> {
unsafe {
let k = c::bch2_btree_iter_peek_and_restart_outlined(&mut self.raw);
errptr_to_result_c(k.k)
.map(|_| if !k.k.is_null() { Some(BkeySC{ k: &*k.k, v: &*k.v, iter: PhantomData }) } else { None } )
errptr_to_result_c(k.k).map(|_| {
if !k.k.is_null() {
Some(BkeySC {
k: &*k.k,
v: &*k.v,
iter: PhantomData,
})
} else {
None
}
})
}
}
@ -100,21 +130,23 @@ impl<'t> BtreeIter<'t> {
impl<'t> Drop for BtreeIter<'t> {
fn drop(&mut self) {
unsafe { c::bch2_trans_iter_exit(self.raw.trans, &mut self.raw) }
}
}
}
pub struct BtreeNodeIter<'t> {
raw: c::btree_iter,
trans: PhantomData<&'t BtreeTrans<'t>>,
raw: c::btree_iter,
trans: PhantomData<&'t BtreeTrans<'t>>,
}
impl<'t> BtreeNodeIter<'t> {
pub fn new(trans: &'t BtreeTrans<'t>,
btree: c::btree_id,
pos: c::bpos,
pub fn new(
trans: &'t BtreeTrans<'t>,
btree: c::btree_id,
pos: c::bpos,
locks_want: u32,
depth: u32,
flags: BtreeIterFlags) -> BtreeNodeIter {
depth: u32,
flags: BtreeIterFlags,
) -> BtreeNodeIter<'t> {
unsafe {
let mut iter: MaybeUninit<c::btree_iter> = MaybeUninit::uninit();
c::bch2_trans_node_iter_init(
@ -124,9 +156,13 @@ impl<'t> BtreeNodeIter<'t> {
pos,
locks_want,
depth,
flags.bits as u32);
flags.bits as u32,
);
BtreeNodeIter { raw: iter.assume_init(), trans: PhantomData }
BtreeNodeIter {
raw: iter.assume_init(),
trans: PhantomData,
}
}
}
@ -161,7 +197,7 @@ impl<'t> BtreeNodeIter<'t> {
impl<'t> Drop for BtreeNodeIter<'t> {
fn drop(&mut self) {
unsafe { c::bch2_trans_iter_exit(self.raw.trans, &mut self.raw) }
}
}
}
impl<'b, 'f> c::btree {
@ -175,23 +211,27 @@ impl<'b, 'f> c::btree {
}
pub struct BtreeNodeToText<'b, 'f> {
b: &'b c::btree,
fs: &'f Fs,
b: &'b c::btree,
fs: &'f Fs,
}
impl<'b, 'f> fmt::Display for BtreeNodeToText<'b, 'f> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
printbuf_to_formatter(f, |buf| unsafe { c::bch2_btree_node_to_text(buf, self.fs.raw, self.b) })
printbuf_to_formatter(f, |buf| unsafe {
c::bch2_btree_node_to_text(buf, self.fs.raw, self.b)
})
}
}
pub struct BtreeNodeOndiskToText<'b, 'f> {
b: &'b c::btree,
fs: &'f Fs,
b: &'b c::btree,
fs: &'f Fs,
}
impl<'b, 'f> fmt::Display for BtreeNodeOndiskToText<'b, 'f> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
printbuf_to_formatter(f, |buf| unsafe { c::bch2_btree_node_ondisk_to_text(buf, self.fs.raw, self.b) })
printbuf_to_formatter(f, |buf| unsafe {
c::bch2_btree_node_ondisk_to_text(buf, self.fs.raw, self.b)
})
}
}

View File

@ -1,8 +1,8 @@
use crate::c;
use crate::errcode::{bch_errcode, errptr_to_result};
use std::ffi::CString;
use std::os::unix::ffi::OsStrExt;
use std::path::PathBuf;
use crate::c;
use crate::errcode::{bch_errcode, errptr_to_result};
pub struct Fs {
pub raw: *mut c::bch_fs,
@ -10,18 +10,19 @@ pub struct Fs {
impl Fs {
pub fn open(devs: &Vec<PathBuf>, opts: c::bch_opts) -> Result<Fs, bch_errcode> {
let devs: Vec<_> = devs.iter()
let devs: Vec<_> = devs
.iter()
.map(|i| CString::new(i.as_os_str().as_bytes()).unwrap().into_raw())
.collect();
let ret = unsafe { c::bch2_fs_open(devs[..].as_ptr(), devs.len() as u32, opts) };
errptr_to_result(ret).map(|fs| Fs { raw: fs})
errptr_to_result(ret).map(|fs| Fs { raw: fs })
}
}
impl Drop for Fs {
fn drop(&mut self) {
unsafe { c::bch2_fs_stop(self.raw) }
}
}
}

View File

@ -1,11 +1,11 @@
pub mod bcachefs;
pub mod btree;
pub mod bkey;
pub mod btree;
pub mod errcode;
pub mod keyutils;
pub mod sb_io;
pub mod fs;
pub mod keyutils;
pub mod opts;
pub mod sb_io;
pub use paste::paste;
pub mod c {
@ -15,15 +15,19 @@ pub mod c {
use c::bpos as Bpos;
pub const fn spos(inode: u64, offset: u64, snapshot: u32) -> Bpos {
Bpos { inode, offset, snapshot }
Bpos {
inode,
offset,
snapshot,
}
}
pub const fn pos(inode: u64, offset: u64) -> Bpos {
spos(inode, offset, 0)
}
pub const POS_MIN: Bpos = spos(0, 0, 0);
pub const POS_MAX: Bpos = spos(u64::MAX, u64::MAX, 0);
pub const POS_MIN: Bpos = spos(0, 0, 0);
pub const POS_MAX: Bpos = spos(u64::MAX, u64::MAX, 0);
pub const SPOS_MAX: Bpos = spos(u64::MAX, u64::MAX, u32::MAX);
use std::cmp::Ordering;
@ -44,14 +48,15 @@ impl PartialOrd for Bpos {
impl Ord for Bpos {
fn cmp(&self, other: &Self) -> Ordering {
let l_inode = self.inode;
let r_inode = other.inode;
let l_offset = self.offset;
let r_offset = other.offset;
let l_snapshot = self.snapshot;
let r_snapshot = other.snapshot;
let l_inode = self.inode;
let r_inode = other.inode;
let l_offset = self.offset;
let r_offset = other.offset;
let l_snapshot = self.snapshot;
let r_snapshot = other.snapshot;
l_inode.cmp(&r_inode)
l_inode
.cmp(&r_inode)
.then(l_offset.cmp(&r_offset))
.then(l_snapshot.cmp(&r_snapshot))
}
@ -68,9 +73,9 @@ impl fmt::Display for c::btree_id {
}
}
use std::str::FromStr;
use std::ffi::CString;
use std::{path::Path,os::unix::ffi::OsStrExt};
use std::str::FromStr;
use std::{os::unix::ffi::OsStrExt, path::Path};
pub fn path_to_cstr<P: AsRef<Path>>(p: P) -> CString {
CString::new(p.as_ref().as_os_str().as_bytes()).unwrap()
@ -79,29 +84,60 @@ pub fn path_to_cstr<P: AsRef<Path>>(p: P) -> CString {
use std::error::Error;
#[derive(Debug)]
pub struct InvalidBtreeId;
pub enum BchToolsErr {
InvalidBtreeId,
InvalidBkeyType,
InvalidBpos,
}
impl fmt::Display for InvalidBtreeId {
impl fmt::Display for BchToolsErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "invalid btree id")
match self {
BchToolsErr::InvalidBtreeId => write!(f, "invalid btree id"),
BchToolsErr::InvalidBkeyType => write!(f, "invalid bkey type"),
BchToolsErr::InvalidBpos => write!(f, "invalid bpos"),
}
}
}
impl Error for InvalidBtreeId {
}
impl Error for BchToolsErr {}
impl FromStr for c::btree_id {
type Err = InvalidBtreeId;
type Err = BchToolsErr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = CString::new(s).unwrap();
let p = s.as_ptr();
let v = unsafe {c::match_string(c::__bch2_btree_ids[..].as_ptr(), (-(1 as isize)) as usize, p)};
let v = unsafe {
c::match_string(
c::__bch2_btree_ids[..].as_ptr(),
(-(1 as isize)) as usize,
p,
)
};
if v >= 0 {
Ok(unsafe { std::mem::transmute(v) })
} else {
Err(InvalidBtreeId)
Err(BchToolsErr::InvalidBtreeId)
}
}
}
impl FromStr for c::bch_bkey_type {
type Err = BchToolsErr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = CString::new(s).unwrap();
let p = s.as_ptr();
let v = unsafe {
c::match_string(c::bch2_bkey_types[..].as_ptr(), (-(1 as isize)) as usize, p)
};
if v >= 0 {
Ok(unsafe { std::mem::transmute(v) })
} else {
Err(BchToolsErr::InvalidBkeyType)
}
}
}
@ -118,7 +154,7 @@ impl c::printbuf {
impl Drop for c::printbuf {
fn drop(&mut self) {
unsafe { c::bch2_printbuf_exit(self) }
}
}
}
impl fmt::Display for Bpos {
@ -126,7 +162,7 @@ impl fmt::Display for Bpos {
let mut buf = c::printbuf::new();
unsafe { c::bch2_bpos_to_text(&mut buf, *self) };
let s = unsafe { CStr::from_ptr(buf.buf) };
let s = s.to_str().unwrap();
write!(f, "{}", s)
@ -134,7 +170,7 @@ impl fmt::Display for Bpos {
}
impl FromStr for c::bpos {
type Err = InvalidBtreeId;
type Err = BchToolsErr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "POS_MIN" {
@ -150,20 +186,26 @@ impl FromStr for c::bpos {
}
let mut fields = s.split(':');
let ino_str = fields.next().ok_or(InvalidBtreeId)?;
let off_str = fields.next().ok_or(InvalidBtreeId)?;
let ino_str = fields.next().ok_or(BchToolsErr::InvalidBpos)?;
let off_str = fields.next().ok_or(BchToolsErr::InvalidBpos)?;
let snp_str = fields.next();
let ino: u64 = ino_str.parse().map_err(|_| InvalidBtreeId)?;
let off: u64 = off_str.parse().map_err(|_| InvalidBtreeId)?;
let snp: u32 = snp_str.map(|s| s.parse().ok()).flatten().unwrap_or(0);
let ino: u64 = ino_str.parse().map_err(|_| BchToolsErr::InvalidBpos)?;
let off: u64 = off_str.parse().map_err(|_| BchToolsErr::InvalidBpos)?;
let snp: u32 = snp_str.map(|s| s.parse().ok()).flatten().unwrap_or(0);
Ok(c::bpos { inode: ino, offset: off, snapshot: snp })
Ok(c::bpos {
inode: ino,
offset: off,
snapshot: snp,
})
}
}
pub fn printbuf_to_formatter<F>(f: &mut fmt::Formatter<'_>, func: F) -> fmt::Result
where F: Fn(*mut c::printbuf) {
where
F: Fn(*mut c::printbuf),
{
let mut buf = c::printbuf::new();
func(&mut buf);

View File

@ -1,3 +1,7 @@
use crate::c;
use crate::fs::Fs;
use std::ffi::{CString, c_char};
#[macro_export]
macro_rules! opt_set {
($opts:ident, $n:ident, $v:expr) => {
@ -33,3 +37,29 @@ macro_rules! opt_get {
}
};
}
pub fn parse_mount_opts(fs: Option<&mut Fs>, optstr: Option<&str>, ignore_unknown: bool)
-> Result<c::bch_opts, c::bch_errcode> {
let mut opts: c::bch_opts = Default::default();
if let Some(optstr) = optstr {
let optstr = CString::new(optstr).unwrap();
let optstr_ptr = optstr.as_ptr();
let ret = unsafe {
c::bch2_parse_mount_opts(fs.map_or(std::ptr::null_mut(), |f| f.raw),
&mut opts as *mut c::bch_opts,
std::ptr::null_mut(),
optstr_ptr as *mut c_char,
ignore_unknown)
};
drop(optstr);
if ret != 0 {
let err: c::bch_errcode = unsafe { std::mem::transmute(-ret) };
return Err(err);
}
}
Ok(opts)
}

View File

@ -1,8 +1,10 @@
use anyhow::anyhow;
use crate::path_to_cstr;
use crate::bcachefs;
use crate::bcachefs::*;
use crate::errcode::bch_errcode;
use crate::path_to_cstr;
use anyhow::anyhow;
pub use crate::bcachefs::bch2_free_super;
pub fn read_super_opts(
path: &std::path::Path,
@ -11,7 +13,8 @@ pub fn read_super_opts(
let path = path_to_cstr(path);
let mut sb = std::mem::MaybeUninit::zeroed();
let ret = unsafe { crate::bcachefs::bch2_read_super(path.as_ptr(), &mut opts, sb.as_mut_ptr()) };
let ret =
unsafe { crate::bcachefs::bch2_read_super(path.as_ptr(), &mut opts, sb.as_mut_ptr()) };
if ret != 0 {
let err: bch_errcode = unsafe { ::std::mem::transmute(ret) };
@ -33,7 +36,9 @@ pub fn read_super_silent(
let path = path_to_cstr(path);
let mut sb = std::mem::MaybeUninit::zeroed();
let ret = unsafe { crate::bcachefs::bch2_read_super_silent(path.as_ptr(), &mut opts, sb.as_mut_ptr()) };
let ret = unsafe {
crate::bcachefs::bch2_read_super_silent(path.as_ptr(), &mut opts, sb.as_mut_ptr())
};
if ret != 0 {
let err: bch_errcode = unsafe { ::std::mem::transmute(ret) };

View File

@ -1,56 +0,0 @@
{ lib, stdenv, pkg-config, attr, libuuid, libsodium, keyutils, liburcu, zlib
, libaio, udev, zstd, lz4, nix-gitignore, rustPlatform, rustc, cargo, fuse3
, fuseSupport ? false, }:
let
src = nix-gitignore.gitignoreSource [ ] ./.;
commit = lib.strings.substring 0 7 (builtins.readFile ./.bcachefs_revision);
version = "git-${commit}";
in stdenv.mkDerivation {
inherit src version;
pname = "bcachefs-tools";
nativeBuildInputs = [
pkg-config
cargo
rustc
rustPlatform.cargoSetupHook
rustPlatform.bindgenHook
];
buildInputs = [
libaio
keyutils # libkeyutils
lz4 # liblz4
libsodium
liburcu
libuuid
zstd # libzstd
zlib # zlib1g
attr
udev
] ++ lib.optional fuseSupport fuse3;
${if fuseSupport then "BCACHEFS_FUSE" else null} = "1";
cargoRoot = ".";
# when git-based crates are updated, run:
# nix run github:Mic92/nix-update -- --version=skip --flake default
# to update the hashes
cargoDeps = rustPlatform.importCargoLock {
lockFile = "${src}/Cargo.lock";
};
makeFlags = [ "DESTDIR=${placeholder "out"}" "PREFIX=" "VERSION=${commit}" ];
dontStrip = true;
checkPhase = "./target/release/bcachefs version";
doCheck = true;
meta = {
mainProgram = "bcachefs";
license = lib.licenses.gpl2Only;
};
}

View File

@ -33,7 +33,8 @@ void bcachefs_usage(void)
"Superblock commands:\n"
" format Format a new filesystem\n"
" show-super Dump superblock information to stdout\n"
" set-option Set a filesystem option\n"
" recover-super Attempt to recover overwritten superblock from backups\n"
" set-fs-option Set a filesystem option\n"
" reset-counters Reset all counters on an unmounted device\n"
"\n"
"Mount:\n"
@ -52,6 +53,7 @@ void bcachefs_usage(void)
#endif
"Commands for managing a running filesystem:\n"
" fs usage Show disk usage\n"
" fs top Show runtime performance information\n"
"\n"
"Commands for managing devices within a running filesystem:\n"
" device add Add a new device to an existing filesystem\n"
@ -70,6 +72,7 @@ void bcachefs_usage(void)
"\n"
"Commands for managing filesystem data:\n"
" data rereplicate Rereplicate degraded data\n"
" data scrub Verify checksums and correct errors, if possible\n"
" data job Kick off low level data jobs\n"
"\n"
"Encryption:\n"
@ -82,7 +85,7 @@ void bcachefs_usage(void)
" migrate-superblock Add default superblock, after bcachefs migrate\n"
"\n"
"Commands for operating on files in a bcachefs filesystem:\n"
" setattr Set various per file attributes\n"
" set-file-option Set various attributes on files or directories\n"
"\n"
"Debug:\n"
"These commands work on offline, unmounted filesystems\n"
@ -90,9 +93,11 @@ void bcachefs_usage(void)
" list List filesystem metadata in textual form\n"
" list_journal List contents of journal\n"
"\n"
#ifdef BCACHEFS_FUSE
"FUSE:\n"
" fusemount Mount a filesystem via FUSE\n"
"\n"
#endif
"Miscellaneous:\n"
" completions Generate shell completions\n"
" version Display the version of the invoked bcachefs tool\n");
@ -113,14 +118,15 @@ int fs_cmds(int argc, char *argv[])
{
char *cmd = pop_cmd(&argc, argv);
if (argc < 1) {
bcachefs_usage();
exit(EXIT_FAILURE);
}
if (argc < 1)
return fs_usage();
if (!strcmp(cmd, "usage"))
return cmd_fs_usage(argc, argv);
if (!strcmp(cmd, "top"))
return cmd_fs_top(argc, argv);
return 0;
fs_usage();
return -EINVAL;
}
int device_cmds(int argc, char *argv[])
@ -146,7 +152,8 @@ int device_cmds(int argc, char *argv[])
if (!strcmp(cmd, "resize-journal"))
return cmd_device_resize_journal(argc, argv);
return 0;
device_usage();
return -EINVAL;
}
int data_cmds(int argc, char *argv[])
@ -157,8 +164,11 @@ int data_cmds(int argc, char *argv[])
return data_usage();
if (!strcmp(cmd, "rereplicate"))
return cmd_data_rereplicate(argc, argv);
if (!strcmp(cmd, "scrub"))
return cmd_data_scrub(argc, argv);
if (!strcmp(cmd, "job"))
return cmd_data_job(argc, argv);
return 0;
data_usage();
return -EINVAL;
}

View File

@ -85,8 +85,8 @@ static void do_setattr(char *path, struct bch_opt_strs opts)
static void setattr_usage(void)
{
puts("bcachefs setattr - set attributes on files in a bcachefs filesystem\n"
"Usage: bcachefs setattr [OPTIONS]... <files>\n"
puts("bcachefs set-file-option - set attributes on files in a bcachefs filesystem\n"
"Usage: bcachefs set-file-option [OPTIONS]... <files>\n"
"\n"
"Options:");

View File

@ -1,5 +1,5 @@
#include <getopt.h>
#include <stdio.h>
#include <sys/ioctl.h>
@ -64,6 +64,207 @@ int cmd_data_rereplicate(int argc, char *argv[])
});
}
static void data_scrub_usage(void)
{
puts("bcachefs data scrub\n"
"Usage: bcachefs data scrub [filesystem|device]\n"
"\n"
"Check data for errors, fix from another replica if possible\n"
"\n"
"Options:\n"
" -m, --metadata check metadata only\n"
" -h, --help display this help and exit\n"
"Report bugs to <linux-bcachefs@vger.kernel.org>");
exit(EXIT_SUCCESS);
}
int cmd_data_scrub(int argc, char *argv[])
{
static const struct option longopts[] = {
{ "metadata", no_argument, NULL, 'm' },
{ "help", no_argument, NULL, 'h' },
{ NULL }
};
struct bch_ioctl_data cmd = {
.op = BCH_DATA_OP_scrub,
.scrub.data_types = ~0,
};
int opt;
while ((opt = getopt_long(argc, argv, "hm", longopts, NULL)) != -1)
switch (opt) {
case 'm':
cmd.scrub.data_types = BIT(BCH_DATA_btree);
break;
case 'h':
data_scrub_usage();
break;
}
args_shift(optind);
char *path = arg_pop();
if (!path)
die("Please supply a filesystem");
if (argc)
die("too many arguments");
printf("Starting scrub on");
struct bchfs_handle fs = bcache_fs_open(path);
dev_names dev_names = bchu_fs_get_devices(fs);
struct scrub_device {
const char *name;
int progress_fd;
u64 done, corrected, uncorrected, total;
enum bch_ioctl_data_event_ret ret;
};
DARRAY(struct scrub_device) scrub_devs = {};
if (fs.dev_idx >= 0) {
cmd.scrub.dev = fs.dev_idx;
struct scrub_device d = {
.name = dev_idx_to_name(&dev_names, fs.dev_idx)->dev,
.progress_fd = xioctl(fs.ioctl_fd, BCH_IOCTL_DATA, &cmd),
};
darray_push(&scrub_devs, d);
} else {
/* Scrubbing every device */
darray_for_each(dev_names, dev) {
cmd.scrub.dev = dev->idx;
struct scrub_device d = {
.name = dev->dev,
.progress_fd = xioctl(fs.ioctl_fd, BCH_IOCTL_DATA, &cmd),
};
darray_push(&scrub_devs, d);
}
}
printf(" %zu devices: ", scrub_devs.nr);
darray_for_each(scrub_devs, dev)
printf(" %s", dev->name);
printf("\n");
struct timespec now, last;
bool first = true;
struct printbuf buf = PRINTBUF;
printbuf_tabstop_push(&buf, 16);
printbuf_tabstop_push(&buf, 12);
printbuf_tabstop_push(&buf, 12);
printbuf_tabstop_push(&buf, 12);
printbuf_tabstop_push(&buf, 12);
printbuf_tabstop_push(&buf, 6);
prt_printf(&buf, "device\t");
prt_printf(&buf, "checked\r");
prt_printf(&buf, "corrected\r");
prt_printf(&buf, "uncorrected\r");
prt_printf(&buf, "total\r");
puts(buf.buf);
while (1) {
bool done = true;
printbuf_reset_keep_tabstops(&buf);
clock_gettime(CLOCK_MONOTONIC, &now);
u64 ns_since_last = 0;
if (!first)
ns_since_last = (now.tv_sec - last.tv_sec) * NSEC_PER_SEC +
now.tv_nsec - last.tv_nsec;
darray_for_each(scrub_devs, dev) {
struct bch_ioctl_data_event e;
if (dev->progress_fd >= 0 &&
read(dev->progress_fd, &e, sizeof(e)) != sizeof(e)) {
close(dev->progress_fd);
dev->progress_fd = -1;
}
u64 rate = 0;
if (dev->progress_fd >= 0) {
if (ns_since_last)
rate = ((e.p.sectors_done - dev->done) << 9)
* NSEC_PER_SEC
/ ns_since_last;
dev->done = e.p.sectors_done;
dev->corrected = e.p.sectors_error_corrected;
dev->uncorrected= e.p.sectors_error_uncorrected;
dev->total = e.p.sectors_total;
}
if (dev->progress_fd >= 0 && e.ret) {
close(dev->progress_fd);
dev->progress_fd = -1;
dev->ret = e.ret;
}
if (dev->progress_fd >= 0)
done = false;
prt_printf(&buf, "%s\t", dev->name ?: "(offline)");
prt_human_readable_u64(&buf, dev->done << 9);
prt_tab_rjust(&buf);
prt_human_readable_u64(&buf, dev->corrected << 9);
prt_tab_rjust(&buf);
prt_human_readable_u64(&buf, dev->uncorrected << 9);
prt_tab_rjust(&buf);
prt_human_readable_u64(&buf, dev->total << 9);
prt_tab_rjust(&buf);
prt_printf(&buf, "%llu%%",
dev->total
? dev->done * 100 / dev->total
: 0);
prt_tab_rjust(&buf);
prt_str(&buf, " ");
if (dev->progress_fd >= 0) {
prt_human_readable_u64(&buf, rate);
prt_str(&buf, "/sec");
} else if (dev->ret == BCH_IOCTL_DATA_EVENT_RET_device_offline) {
prt_str(&buf, "offline");
} else {
prt_str(&buf, "complete");
}
if (dev != &darray_last(scrub_devs))
prt_newline(&buf);
}
fputs(buf.buf, stdout);
fflush(stdout);
if (done)
break;
last = now;
first = false;
sleep(1);
for (unsigned i = 0; i < scrub_devs.nr; i++) {
if (i)
printf("\033[1A");
printf("\33[2K\r");
}
}
fputs("\n", stdout);
printbuf_exit(&buf);
return 0;
}
static void data_job_usage(void)
{
puts("bcachefs data job\n"

View File

@ -47,11 +47,11 @@ static void device_add_usage(void)
puts("bcachefs device add - add a device to an existing filesystem\n"
"Usage: bcachefs device add [OPTION]... filesystem device\n"
"\n"
"Options:\n"
" -S, --fs_size=size Size of filesystem on device\n"
" -B, --bucket=size Bucket size\n"
" -D, --discard Enable discards\n"
" -l, --label=label Disk label\n"
"Options:\n");
bch2_opts_usage(OPT_FORMAT|OPT_DEVICE);
puts(" -l, --label=label Disk label\n"
" -f, --force Use device even if it appears to already be formatted\n"
" -h, --help Display this help and exit\n"
"\n"
@ -61,9 +61,6 @@ static void device_add_usage(void)
int cmd_device_add(int argc, char *argv[])
{
static const struct option longopts[] = {
{ "fs_size", required_argument, NULL, 'S' },
{ "bucket", required_argument, NULL, 'B' },
{ "discard", no_argument, NULL, 'D' },
{ "label", required_argument, NULL, 'l' },
{ "force", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
@ -72,22 +69,31 @@ int cmd_device_add(int argc, char *argv[])
struct format_opts format_opts = format_opts_default();
struct dev_opts dev_opts = dev_opts_default();
bool force = false;
int opt;
while ((opt = getopt_long(argc, argv, "t:fh",
longopts, NULL)) != -1)
switch (opt) {
case 'S':
if (bch2_strtoull_h(optarg, &dev_opts.size))
die("invalid filesystem size");
break;
case 'B':
if (bch2_strtoull_h(optarg, &dev_opts.bucket_size))
die("bad bucket_size %s", optarg);
break;
case 'D':
dev_opts.discard = true;
while (true) {
const struct bch_option *opt =
bch2_cmdline_opt_parse(argc, argv, OPT_FORMAT|OPT_DEVICE);
if (opt) {
unsigned id = opt - bch2_opt_table;
u64 v;
struct printbuf err = PRINTBUF;
int ret = bch2_opt_parse(NULL, opt, optarg, &v, &err);
if (ret)
die("invalid %s: %s", opt->attr.name, err.buf);
if (opt->flags & OPT_DEVICE)
bch2_opt_set_by_id(&dev_opts.opts, id, v);
else
die("got bch_opt of wrong type %s", opt->attr.name);
continue;
}
int optid = getopt_long(argc, argv, "S:B:Dl:fh", longopts, NULL);
if (optid == -1)
break;
switch (optid) {
case 'l':
dev_opts.label = strdup(optarg);
break;
@ -97,7 +103,11 @@ int cmd_device_add(int argc, char *argv[])
case 'h':
device_add_usage();
exit(EXIT_SUCCESS);
case '?':
exit(EXIT_FAILURE);
break;
}
}
args_shift(optind);
char *fs_path = arg_pop();
@ -127,10 +137,11 @@ int cmd_device_add(int argc, char *argv[])
opt_set(fs_opts, btree_node_size,
read_file_u64(fs.sysfs_fd, "options/btree_node_size"));
struct bch_sb *sb = bch2_format(fs_opt_strs,
fs_opts,
format_opts,
&dev_opts, 1);
dev_opts_list devs = {};
darray_push(&devs, dev_opts);
struct bch_sb *sb = bch2_format(fs_opt_strs, fs_opts, format_opts, devs);
darray_exit(&devs);
free(sb);
bchu_disk_add(fs, dev_opts.path);
return 0;

View File

@ -30,6 +30,15 @@ static void dump_usage(void)
"Report bugs to <linux-bcachefs@vger.kernel.org>");
}
static void dump_node(struct bch_fs *c, struct bch_dev *ca, struct bkey_s_c k, ranges *data)
{
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
bkey_for_each_ptr(ptrs, ptr)
if (ptr->dev == ca->dev_idx)
range_add(data, ptr->offset << 9, c->opts.btree_node_size);
}
static void dump_one_device(struct bch_fs *c, struct bch_dev *ca, int fd,
bool entire_journal)
{
@ -60,42 +69,25 @@ static void dump_one_device(struct bch_fs *c, struct bch_dev *ca, int fd,
/* Btree: */
for (i = 0; i < BTREE_ID_NR; i++) {
struct bkey_ptrs_c ptrs;
struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter;
struct btree *b;
__for_each_btree_node(trans, iter, i, POS_MIN, 0, 1, 0, b, ret) {
ret = __for_each_btree_node(trans, iter, i, POS_MIN, 0, 1, 0, b, ({
struct btree_node_iter iter;
struct bkey u;
struct bkey_s_c k;
for_each_btree_node_key_unpack(b, k, &iter, &u) {
ptrs = bch2_bkey_ptrs_c(k);
bkey_for_each_ptr(ptrs, ptr)
if (ptr->dev == ca->dev_idx)
range_add(&data,
ptr->offset << 9,
btree_ptr_sectors_written(&b->key));
}
}
for_each_btree_node_key_unpack(b, k, &iter, &u)
dump_node(c, ca, k, &data);
0;
}));
if (ret)
die("error %s walking btree nodes", bch2_err_str(ret));
b = bch2_btree_id_root(c, i)->b;
if (!btree_node_fake(b)) {
ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key));
struct btree *b = bch2_btree_id_root(c, i)->b;
if (!btree_node_fake(b))
dump_node(c, ca, bkey_i_to_s_c(&b->key), &data);
bkey_for_each_ptr(ptrs, ptr)
if (ptr->dev == ca->dev_idx)
range_add(&data,
ptr->offset << 9,
btree_ptr_sectors_written(&b->key));
}
bch2_trans_iter_exit(trans, &iter);
bch2_trans_put(trans);
}
@ -120,6 +112,7 @@ int cmd_dump(int argc, char *argv[])
int fd, opt;
opt_set(opts, direct_io, false);
opt_set(opts, noexcl, true);
opt_set(opts, read_only, true);
opt_set(opts, nochanges, true);
opt_set(opts, norecovery, true);
@ -159,7 +152,7 @@ int cmd_dump(int argc, char *argv[])
if (IS_ERR(c))
die("error opening devices: %s", bch2_err_str(PTR_ERR(c)));
down_read(&c->gc_lock);
down_read(&c->state_lock);
for_each_online_member(c, ca)
nr_devices++;
@ -182,7 +175,7 @@ int cmd_dump(int argc, char *argv[])
close(fd);
}
up_read(&c->gc_lock);
up_read(&c->state_lock);
bch2_fs_stop(c);
return 0;

View File

@ -21,6 +21,7 @@
#include <uuid/uuid.h>
#include "cmds.h"
#include "posix_to_bcachefs.h"
#include "libbcachefs.h"
#include "crypto.h"
#include "libbcachefs/errcode.h"
@ -38,40 +39,38 @@ x('L', fs_label, required_argument) \
x('U', uuid, required_argument) \
x(0, fs_size, required_argument) \
x(0, superblock_size, required_argument) \
x(0, bucket_size, required_argument) \
x('l', label, required_argument) \
x(0, discard, no_argument) \
x(0, data_allowed, required_argument) \
x(0, durability, required_argument) \
x(0, version, required_argument) \
x(0, no_initialize, no_argument) \
x(0, source, required_argument) \
x('f', force, no_argument) \
x('q', quiet, no_argument) \
x('v', verbose, no_argument) \
x('h', help, no_argument)
static void usage(void)
static void format_usage(void)
{
puts("bcachefs format - create a new bcachefs filesystem on one or more devices\n"
"Usage: bcachefs format [OPTION]... <devices>\n"
"\n"
"Options:");
bch2_opts_usage(OPT_FORMAT);
bch2_opts_usage(OPT_FORMAT|OPT_FS);
puts(
" --replicas=# Sets both data and metadata replicas\n"
puts(" --replicas=# Sets both data and metadata replicas\n"
" --encrypted Enable whole filesystem encryption (chacha20/poly1305)\n"
" --no_passphrase Don't encrypt master encryption key\n"
" -L, --fs_label=label\n"
" -U, --uuid=uuid\n"
" --superblock_size=size\n"
" --source=path Initialize the bcachefs filesystem from this root directory\n"
"\n"
"Device specific options:");
bch2_opts_usage(OPT_DEVICE);
bch2_opts_usage(OPT_FORMAT|OPT_DEVICE);
puts(" -l, --label=label Disk label\n"
puts(" --fs_size=size Size of filesystem on device\n"
" -l, --label=label Disk label\n"
"\n"
" -f, --force\n"
" -q, --quiet Only print errors\n"
@ -113,26 +112,69 @@ u64 read_flag_list_or_die(char *opt, const char * const list[],
return v;
}
void build_fs(struct bch_fs *c, const char *src_path)
{
struct copy_fs_state s = {};
int src_fd = xopen(src_path, O_RDONLY|O_NOATIME);
struct stat stat = xfstat(src_fd);
if (!S_ISDIR(stat.st_mode))
die("%s is not a directory", src_path);
copy_fs(c, src_fd, src_path, &s, 0);
}
int cmd_format(int argc, char *argv[])
{
DARRAY(struct dev_opts) devices = { 0 };
DARRAY(char *) device_paths = { 0 };
dev_opts_list devices = {};
darray_str device_paths = {};
struct format_opts opts = format_opts_default();
struct dev_opts dev_opts = dev_opts_default();
bool force = false, no_passphrase = false, quiet = false, initialize = true, verbose = false;
bool unconsumed_dev_option = false;
unsigned v;
int opt;
struct bch_opt_strs fs_opt_strs =
bch2_cmdline_opts_get(&argc, argv, OPT_FORMAT);
struct bch_opts fs_opts = bch2_parse_opts(fs_opt_strs);
struct bch_opt_strs fs_opt_strs = {};
struct bch_opts fs_opts = bch2_opts_empty();
while ((opt = getopt_long(argc, argv,
"-L:U:g:fqhv",
format_opts,
NULL)) != -1)
switch (opt) {
if (getenv("BCACHEFS_KERNEL_ONLY"))
initialize = false;
while (true) {
const struct bch_option *opt =
bch2_cmdline_opt_parse(argc, argv, OPT_FORMAT|OPT_FS|OPT_DEVICE);
if (opt) {
unsigned id = opt - bch2_opt_table;
u64 v;
struct printbuf err = PRINTBUF;
int ret = bch2_opt_parse(NULL, opt, optarg, &v, &err);
if (ret == -BCH_ERR_option_needs_open_fs) {
fs_opt_strs.by_id[id] = strdup(optarg);
continue;
}
if (ret)
die("invalid option: %s", err.buf);
if (opt->flags & OPT_DEVICE) {
bch2_opt_set_by_id(&dev_opts.opts, id, v);
unconsumed_dev_option = true;
} else if (opt->flags & OPT_FS) {
bch2_opt_set_by_id(&fs_opts, id, v);
} else {
die("got bch_opt of wrong type %s", opt->attr.name);
}
continue;
}
int optid = getopt_long(argc, argv,
"-L:l:U:g:fqhv",
format_opts,
NULL);
if (optid == -1)
break;
switch (optid) {
case O_replicas:
if (kstrtouint(optarg, 10, &v) ||
!v ||
@ -142,6 +184,9 @@ int cmd_format(int argc, char *argv[])
opt_set(fs_opts, metadata_replicas, v);
opt_set(fs_opts, data_replicas, v);
break;
case O_source:
opts.source = optarg;
break;
case O_encrypted:
opts.encrypted = true;
break;
@ -162,7 +207,7 @@ int cmd_format(int argc, char *argv[])
force = true;
break;
case O_fs_size:
if (bch2_strtoull_h(optarg, &dev_opts.size))
if (bch2_strtoull_h(optarg, &dev_opts.fs_size))
die("invalid filesystem size");
unconsumed_dev_option = true;
break;
@ -172,35 +217,13 @@ int cmd_format(int argc, char *argv[])
opts.superblock_size >>= 9;
break;
case O_bucket_size:
if (bch2_strtoull_h(optarg, &dev_opts.bucket_size))
die("bad bucket_size %s", optarg);
unconsumed_dev_option = true;
break;
case O_label:
case 'l':
dev_opts.label = optarg;
unconsumed_dev_option = true;
break;
case O_discard:
dev_opts.discard = true;
unconsumed_dev_option = true;
break;
case O_data_allowed:
dev_opts.data_allowed =
read_flag_list_or_die(optarg,
__bch2_data_types, "data type");
unconsumed_dev_option = true;
break;
case O_durability:
if (kstrtouint(optarg, 10, &dev_opts.durability) ||
dev_opts.durability > BCH_REPLICAS_MAX)
die("invalid durability");
unconsumed_dev_option = true;
break;
case O_version:
if (kstrtouint(optarg, 10, &opts.version))
die("invalid version");
opts.version = version_parse(optarg);
break;
case O_no_initialize:
initialize = false;
@ -209,7 +232,7 @@ int cmd_format(int argc, char *argv[])
darray_push(&device_paths, optarg);
dev_opts.path = optarg;
darray_push(&devices, dev_opts);
dev_opts.size = 0;
dev_opts.fs_size = 0;
unconsumed_dev_option = false;
break;
case O_quiet:
@ -218,15 +241,19 @@ int cmd_format(int argc, char *argv[])
break;
case 'v':
verbose = true;
break;
case O_help:
case 'h':
usage();
format_usage();
exit(EXIT_SUCCESS);
break;
case '?':
exit(EXIT_FAILURE);
break;
default:
die("getopt ret %i %c", optid, optid);
}
}
if (unconsumed_dev_option)
die("Options for devices apply to subsequent devices; got a device option with no device");
@ -248,11 +275,7 @@ int cmd_format(int argc, char *argv[])
die("Error opening %s: %s", dev_opts.path, strerror(-ret));
}
struct bch_sb *sb =
bch2_format(fs_opt_strs,
fs_opts,
opts,
devices.data, devices.nr);
struct bch_sb *sb = bch2_format(fs_opt_strs, fs_opts, opts, devices);
bch2_opt_strs_free(&fs_opt_strs);
if (!quiet) {
@ -274,6 +297,12 @@ int cmd_format(int argc, char *argv[])
darray_exit(&devices);
/* don't skip initialization when we have to build an image from a source */
if (opts.source && !initialize) {
printf("Warning: Forcing the initialization because the source flag was supplied\n");
initialize = 1;
}
if (initialize) {
struct bch_opts mount_opts = bch2_opts_empty();
@ -291,6 +320,11 @@ int cmd_format(int argc, char *argv[])
die("error opening %s: %s", device_paths.data[0],
bch2_err_str(PTR_ERR(c)));
if (opts.source) {
build_fs(c, opts.source);
}
bch2_fs_stop(c);
}
@ -401,3 +435,204 @@ int cmd_show_super(int argc, char *argv[])
printbuf_exit(&buf);
return 0;
}
#include "libbcachefs/super-io.h"
#include "libbcachefs/sb-members.h"
typedef DARRAY(struct bch_sb *) probed_sb_list;
static void probe_one_super(int dev_fd, unsigned sb_size, u64 offset,
probed_sb_list *sbs, bool verbose)
{
darray_char sb_buf = {};
darray_resize(&sb_buf, sb_size);
xpread(dev_fd, sb_buf.data, sb_buf.size, offset);
struct printbuf err = PRINTBUF;
int ret = bch2_sb_validate((void *) sb_buf.data, offset >> 9, 0, &err);
printbuf_exit(&err);
if (!ret) {
if (verbose) {
struct printbuf buf = PRINTBUF;
prt_human_readable_u64(&buf, offset);
printf("found superblock at %s\n", buf.buf);
printbuf_exit(&buf);
}
darray_push(sbs, (void *) sb_buf.data);
sb_buf.data = NULL;
}
darray_exit(&sb_buf);
}
static void probe_sb_range(int dev_fd, u64 start_offset, u64 end_offset,
probed_sb_list *sbs, bool verbose)
{
start_offset &= ~((u64) 511);
end_offset &= ~((u64) 511);
size_t buflen = end_offset - start_offset;
void *buf = malloc(buflen);
xpread(dev_fd, buf, buflen, start_offset);
for (u64 offset = 0; offset < buflen; offset += 512) {
struct bch_sb *sb = buf + offset;
if (!uuid_equal(&sb->magic, &BCACHE_MAGIC) &&
!uuid_equal(&sb->magic, &BCHFS_MAGIC))
continue;
size_t bytes = vstruct_bytes(sb);
if (offset + bytes > buflen) {
fprintf(stderr, "found sb %llu size %zu that overran buffer\n",
start_offset + offset, bytes);
continue;
}
struct printbuf err = PRINTBUF;
int ret = bch2_sb_validate(sb, (start_offset + offset) >> 9, 0, &err);
if (ret)
fprintf(stderr, "found sb %llu that failed to validate: %s\n",
start_offset + offset, err.buf);
printbuf_exit(&err);
if (ret)
continue;
if (verbose) {
struct printbuf buf = PRINTBUF;
prt_human_readable_u64(&buf, start_offset + offset);
printf("found superblock at %s\n", buf.buf);
printbuf_exit(&buf);
}
void *sb_copy = malloc(bytes);
memcpy(sb_copy, sb, bytes);
darray_push(sbs, sb_copy);
}
free(buf);
}
static u64 bch2_sb_last_mount_time(struct bch_sb *sb)
{
u64 ret = 0;
for (unsigned i = 0; i < sb->nr_devices; i++)
ret = max(ret, le64_to_cpu(bch2_sb_member_get(sb, i).last_mount));
return ret;
}
static int bch2_sb_time_cmp(struct bch_sb *l, struct bch_sb *r)
{
return cmp_int(bch2_sb_last_mount_time(l),
bch2_sb_last_mount_time(r));
}
static void recover_super_usage(void)
{
puts("bcachefs recover-super \n"
"Usage: bcachefs recover-super [OPTION].. device\n"
"\n"
"Attempt to recover a filesystem on a device that has had the main superblock\n"
"and superblock layout overwritten.\n"
"All options will be guessed if not provided\n"
"\n"
"Options:\n"
" -d, --dev_size size of filessytem on device, in bytes \n"
" -o, --offset offset to probe, in bytes\n"
" -y, --yes Recover without prompting\n"
" -v, --verbose Increase logging level\n"
" -h, --help display this help and exit\n"
"Report bugs to <linux-bcachefs@vger.kernel.org>");
exit(EXIT_SUCCESS);
}
int cmd_recover_super(int argc, char *argv[])
{
static const struct option longopts[] = {
{ "dev_size", 1, NULL, 'd' },
{ "offset", 1, NULL, 'o' },
{ "yes", 0, NULL, 'y' },
{ "verbose", 0, NULL, 'v' },
{ "help", 0, NULL, 'h' },
{ NULL }
};
u64 dev_size = 0, offset = 0;
bool yes = false, verbose = false;
int opt;
while ((opt = getopt_long(argc, argv, "d:o:yvh", longopts, NULL)) != -1)
switch (opt) {
case 'd':
if (bch2_strtoull_h(optarg, &dev_size))
die("invalid offset");
break;
case 'o':
if (bch2_strtoull_h(optarg, &offset))
die("invalid offset");
if (offset & 511)
die("offset must be a multiple of 512");
break;
case 'y':
yes = true;
break;
case 'v':
verbose = true;
break;
case 'h':
recover_super_usage();
break;
}
args_shift(optind);
char *dev_path = arg_pop();
if (!dev_path)
die("please supply a device");
if (argc)
die("too many arguments");
int dev_fd = xopen(dev_path, O_RDWR);
if (!dev_size)
dev_size = get_size(dev_fd);
probed_sb_list sbs = {};
if (offset) {
probe_one_super(dev_fd, SUPERBLOCK_SIZE_DEFAULT, offset, &sbs, verbose);
} else {
unsigned scan_len = 16 << 20; /* 16MB, start and end of device */
probe_sb_range(dev_fd, 4096, scan_len, &sbs, verbose);
probe_sb_range(dev_fd, dev_size - scan_len, dev_size, &sbs, verbose);
}
if (!sbs.nr) {
printf("Found no bcachefs superblocks\n");
exit(EXIT_FAILURE);
}
struct bch_sb *best = NULL;
darray_for_each(sbs, sb)
if (!best || bch2_sb_time_cmp(best, *sb) < 0)
best = *sb;
struct printbuf buf = PRINTBUF;
bch2_sb_to_text(&buf, best, true, BIT_ULL(BCH_SB_FIELD_members_v2));
printf("Found superblock:\n%s", buf.buf);
printf("Recover?");
if (yes || ask_yn())
bch2_super_write(dev_fd, best);
printbuf_exit(&buf);
darray_for_each(sbs, sb)
kfree(*sb);
darray_exit(&sbs);
return 0;
}

View File

@ -9,6 +9,7 @@
#include "libbcachefs/bcachefs_ioctl.h"
#include "libbcachefs/buckets.h"
#include "libbcachefs/disk_accounting.h"
#include "libbcachefs/opts.h"
#include "libbcachefs/super-io.h"
@ -121,19 +122,50 @@ static int dev_by_label_cmp(const void *_l, const void *_r)
cmp_int(l->idx, r->idx);
}
static struct dev_name *dev_idx_to_name(dev_names *dev_names, unsigned idx)
static void devs_usage_to_text(struct printbuf *out,
struct bchfs_handle fs,
dev_names dev_names)
{
darray_for_each(*dev_names, dev)
if (dev->idx == idx)
return dev;
return NULL;
sort(dev_names.data, dev_names.nr,
sizeof(dev_names.data[0]), dev_by_label_cmp, NULL);
printbuf_tabstops_reset(out);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 20);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 14);
darray_for_each(dev_names, dev)
dev_usage_to_text(out, fs, dev);
darray_for_each(dev_names, dev) {
free(dev->dev);
free(dev->label);
}
}
static void persistent_reserved_to_text(struct printbuf *out,
unsigned nr_replicas, s64 sectors)
{
if (!sectors)
return;
prt_str(out, "reserved:");
prt_tab(out);
prt_printf(out, "%u/%u ", 1, nr_replicas);
prt_tab(out);
prt_str(out, "[] ");
prt_units_u64(out, sectors << 9);
prt_tab_rjust(out);
prt_newline(out);
}
static void replicas_usage_to_text(struct printbuf *out,
const struct bch_replicas_usage *r,
const struct bch_replicas_entry_v1 *r,
s64 sectors,
dev_names *dev_names)
{
if (!r->sectors)
if (!sectors)
return;
char devs[4096], *d = devs;
@ -141,11 +173,11 @@ static void replicas_usage_to_text(struct printbuf *out,
unsigned durability = 0;
for (unsigned i = 0; i < r->r.nr_devs; i++) {
unsigned dev_idx = r->r.devs[i];
for (unsigned i = 0; i < r->nr_devs; i++) {
unsigned dev_idx = r->devs[i];
struct dev_name *dev = dev_idx_to_name(dev_names, dev_idx);
durability += dev->durability;
durability += dev ? dev->durability : 0;
if (i)
*d++ = ' ';
@ -157,11 +189,11 @@ static void replicas_usage_to_text(struct printbuf *out,
*d++ = ']';
*d++ = '\0';
bch2_prt_data_type(out, r->r.data_type);
bch2_prt_data_type(out, r->data_type);
prt_char(out, ':');
prt_tab(out);
prt_printf(out, "%u/%u ", r->r.nr_required, r->r.nr_devs);
prt_printf(out, "%u/%u ", r->nr_required, r->nr_devs);
prt_tab(out);
prt_printf(out, "%u ", durability);
@ -170,7 +202,7 @@ static void replicas_usage_to_text(struct printbuf *out,
prt_printf(out, "%s ", devs);
prt_tab(out);
prt_units_u64(out, r->sectors << 9);
prt_units_u64(out, sectors << 9);
prt_tab_rjust(out);
prt_newline(out);
}
@ -181,14 +213,190 @@ static void replicas_usage_to_text(struct printbuf *out,
_r = replicas_usage_next(_r), \
BUG_ON((void *) _r > (void *) (_u)->replicas + (_u)->replica_entries_bytes))
static void fs_usage_to_text(struct printbuf *out, const char *path)
typedef DARRAY(struct bkey_i_accounting *) darray_accounting_p;
static int accounting_p_cmp(const void *_l, const void *_r)
{
unsigned i;
const struct bkey_i_accounting * const *l = _l;
const struct bkey_i_accounting * const *r = _r;
struct bchfs_handle fs = bcache_fs_open(path);
struct bpos lp = (*l)->k.p, rp = (*r)->k.p;
dev_names dev_names = bchu_fs_get_devices(fs);
return bpos_cmp(lp, rp);
}
static void accounting_sort(darray_accounting_p *sorted,
struct bch_ioctl_query_accounting *in)
{
for (struct bkey_i_accounting *a = in->accounting;
a < (struct bkey_i_accounting *) ((u64 *) in->accounting + in->accounting_u64s);
a = bkey_i_to_accounting(bkey_next(&a->k_i)))
if (darray_push(sorted, a))
die("memory allocation failure");
sort(sorted->data, sorted->nr, sizeof(sorted->data[0]), accounting_p_cmp, NULL);
}
static void accounting_swab_if_old(struct bch_ioctl_query_accounting *in)
{
unsigned kernel_version = bcachefs_kernel_version();
if (kernel_version &&
kernel_version < bcachefs_metadata_version_disk_accounting_big_endian)
for (struct bkey_i_accounting *a = in->accounting;
a < (struct bkey_i_accounting *) ((u64 *) in->accounting + in->accounting_u64s);
a = bkey_i_to_accounting(bkey_next(&a->k_i)))
bch2_bpos_swab(&a->k.p);
}
static int fs_usage_v1_to_text(struct printbuf *out,
struct bchfs_handle fs,
dev_names dev_names)
{
struct bch_ioctl_query_accounting *a =
bchu_fs_accounting(fs,
BIT(BCH_DISK_ACCOUNTING_persistent_reserved)|
BIT(BCH_DISK_ACCOUNTING_replicas)|
BIT(BCH_DISK_ACCOUNTING_compression)|
BIT(BCH_DISK_ACCOUNTING_btree)|
BIT(BCH_DISK_ACCOUNTING_rebalance_work));
if (!a)
return -1;
accounting_swab_if_old(a);
darray_accounting_p a_sorted = {};
accounting_sort(&a_sorted, a);
prt_str(out, "Filesystem: ");
pr_uuid(out, fs.uuid.b);
prt_newline(out);
printbuf_tabstops_reset(out);
printbuf_tabstop_push(out, 20);
printbuf_tabstop_push(out, 16);
prt_str(out, "Size:");
prt_tab(out);
prt_units_u64(out, a->capacity << 9);
prt_tab_rjust(out);
prt_newline(out);
prt_str(out, "Used:");
prt_tab(out);
prt_units_u64(out, a->used << 9);
prt_tab_rjust(out);
prt_newline(out);
prt_str(out, "Online reserved:");
prt_tab(out);
prt_units_u64(out, a->online_reserved << 9);
prt_tab_rjust(out);
prt_newline(out);
prt_newline(out);
printbuf_tabstops_reset(out);
printbuf_tabstop_push(out, 16);
prt_str(out, "Data type");
prt_tab(out);
printbuf_tabstop_push(out, 16);
prt_str(out, "Required/total");
prt_tab(out);
printbuf_tabstop_push(out, 14);
prt_str(out, "Durability");
prt_tab(out);
printbuf_tabstop_push(out, 14);
prt_str(out, "Devices");
prt_newline(out);
printbuf_tabstop_push(out, 14);
unsigned prev_type = 0;
darray_for_each(a_sorted, i) {
struct bkey_i_accounting *a = *i;
struct disk_accounting_pos acc_k;
bpos_to_disk_accounting_pos(&acc_k, a->k.p);
bool new_type = acc_k.type != prev_type;
prev_type = acc_k.type;
switch (acc_k.type) {
case BCH_DISK_ACCOUNTING_persistent_reserved:
persistent_reserved_to_text(out,
acc_k.persistent_reserved.nr_replicas,
a->v.d[0]);
break;
case BCH_DISK_ACCOUNTING_replicas:
replicas_usage_to_text(out, &acc_k.replicas, a->v.d[0], &dev_names);
break;
case BCH_DISK_ACCOUNTING_compression:
if (new_type) {
prt_printf(out, "\nCompression:\n");
printbuf_tabstops_reset(out);
printbuf_tabstop_push(out, 12);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 24);
prt_printf(out, "type\tcompressed\runcompressed\raverage extent size\r\n");
}
u64 nr_extents = a->v.d[0];
u64 sectors_uncompressed = a->v.d[1];
u64 sectors_compressed = a->v.d[2];
bch2_prt_compression_type(out, acc_k.compression.type);
prt_tab(out);
prt_human_readable_u64(out, sectors_compressed << 9);
prt_tab_rjust(out);
prt_human_readable_u64(out, sectors_uncompressed << 9);
prt_tab_rjust(out);
prt_human_readable_u64(out, nr_extents
? div_u64(sectors_uncompressed << 9, nr_extents)
: 0);
prt_tab_rjust(out);
prt_newline(out);
break;
case BCH_DISK_ACCOUNTING_btree:
if (new_type) {
prt_printf(out, "\nBtree usage:\n");
printbuf_tabstops_reset(out);
printbuf_tabstop_push(out, 12);
printbuf_tabstop_push(out, 16);
}
prt_printf(out, "%s:\t", bch2_btree_id_str(acc_k.btree.id));
prt_units_u64(out, a->v.d[0] << 9);
prt_tab_rjust(out);
prt_newline(out);
break;
case BCH_DISK_ACCOUNTING_rebalance_work:
if (new_type)
prt_printf(out, "\nPending rebalance work:\n");
prt_units_u64(out, a->v.d[0] << 9);
prt_newline(out);
break;
}
}
darray_exit(&a_sorted);
free(a);
return 0;
}
static void fs_usage_v0_to_text(struct printbuf *out,
struct bchfs_handle fs,
dev_names dev_names)
{
struct bch_ioctl_fs_usage *u = bchu_fs_usage(fs);
prt_str(out, "Filesystem: ");
@ -239,63 +447,63 @@ static void fs_usage_to_text(struct printbuf *out, const char *path)
printbuf_tabstop_push(out, 14);
for (i = 0; i < BCH_REPLICAS_MAX; i++) {
if (!u->persistent_reserved[i])
continue;
prt_str(out, "reserved:");
prt_tab(out);
prt_printf(out, "%u/%u ", 1, i);
prt_tab(out);
prt_str(out, "[] ");
prt_units_u64(out, u->persistent_reserved[i] << 9);
prt_tab_rjust(out);
prt_newline(out);
}
for (unsigned i = 0; i < BCH_REPLICAS_MAX; i++)
persistent_reserved_to_text(out, i, u->persistent_reserved[i]);
struct bch_replicas_usage *r;
for_each_usage_replica(u, r)
if (r->r.data_type < BCH_DATA_user)
replicas_usage_to_text(out, r, &dev_names);
replicas_usage_to_text(out, &r->r, r->sectors, &dev_names);
for_each_usage_replica(u, r)
if (r->r.data_type == BCH_DATA_user &&
r->r.nr_required <= 1)
replicas_usage_to_text(out, r, &dev_names);
replicas_usage_to_text(out, &r->r, r->sectors, &dev_names);
for_each_usage_replica(u, r)
if (r->r.data_type == BCH_DATA_user &&
r->r.nr_required > 1)
replicas_usage_to_text(out, r, &dev_names);
replicas_usage_to_text(out, &r->r, r->sectors, &dev_names);
for_each_usage_replica(u, r)
if (r->r.data_type > BCH_DATA_user)
replicas_usage_to_text(out, r, &dev_names);
replicas_usage_to_text(out, &r->r, r->sectors, &dev_names);
free(u);
}
sort(dev_names.data, dev_names.nr,
sizeof(dev_names.data[0]), dev_by_label_cmp, NULL);
static void fs_usage_to_text(struct printbuf *out, const char *path)
{
struct bchfs_handle fs = bcache_fs_open(path);
printbuf_tabstops_reset(out);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 20);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 14);
dev_names dev_names = bchu_fs_get_devices(fs);
darray_for_each(dev_names, dev)
dev_usage_to_text(out, fs, dev);
if (!fs_usage_v1_to_text(out, fs, dev_names))
goto devs;
fs_usage_v0_to_text(out, fs, dev_names);
devs:
devs_usage_to_text(out, fs, dev_names);
darray_for_each(dev_names, dev) {
free(dev->dev);
free(dev->label);
}
darray_exit(&dev_names);
bcache_fs_close(fs);
}
int fs_usage(void)
{
puts("bcachefs fs - manage a running filesystem\n"
"Usage: bcachefs fs <CMD> [OPTIONS]\n"
"\n"
"Commands:\n"
" usage Display detailed filesystem usage\n"
" top Show runtime performance information\n"
"\n"
"Report bugs to <linux-bcachefs@vger.kernel.org>");
return 0;
}
static void fs_usage_usage(void)
{
puts("bcachefs fs usage - display detailed filesystem usage\n"

View File

@ -1,4 +1,5 @@
#include <errno.h>
#include <getopt.h>
#include <sys/uio.h>
#include <unistd.h>
@ -20,7 +21,6 @@ static void fsck_usage(void)
" -y Assume \"yes\" to all questions\n"
" -f Force checking even if filesystem is marked clean\n"
" -r, --ratelimit_errors Don't display more than 10 errors of a given type\n"
" -R, --reconstruct_alloc Reconstruct the alloc btree\n"
" -k, --kernel Use the in-kernel fsck implementation\n"
" -v Be verbose\n"
" -h, --help Display this help and exit\n"
@ -60,14 +60,18 @@ static int splice_fd_to_stdinout(int fd)
setnonblocking(STDIN_FILENO);
setnonblocking(fd);
bool stdin_closed = false;
while (true) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(fd, &fds);
if (!stdin_closed)
FD_SET(STDIN_FILENO, &fds);
select(fd + 1, &fds, NULL, NULL, NULL);
if (select(fd + 1, &fds, NULL, NULL, NULL) < 0)
die("select error: %m");
int r = do_splice(fd, STDOUT_FILENO);
if (r < 0)
@ -78,21 +82,25 @@ static int splice_fd_to_stdinout(int fd)
r = do_splice(STDIN_FILENO, fd);
if (r < 0)
return r;
if (r)
stdin_closed = true;
}
return close(fd);
}
static int fsck_online(const char *dev_path)
static int fsck_online(const char *dev_path, const char *opt_str)
{
int dev_idx;
struct bchfs_handle fs = bchu_fs_open_by_dev(dev_path, &dev_idx);
struct bch_ioctl_fsck_online fsck = { 0 };
struct bch_ioctl_fsck_online fsck = {
.opts = (unsigned long) opt_str
};
int fsck_fd = ioctl(fs.ioctl_fd, BCH_IOCTL_FSCK_ONLINE, &fsck);
if (fsck_fd < 0)
die("BCH_IOCTL_FSCK_ONLINE error: %s", bch2_err_str(fsck_fd));
die("BCH_IOCTL_FSCK_ONLINE error: %s", bch2_err_str(errno));
return splice_fd_to_stdinout(fsck_fd);
}
@ -106,9 +114,9 @@ static void append_opt(struct printbuf *out, const char *opt)
static bool should_use_kernel_fsck(darray_str devs)
{
unsigned kernel_version = !access("/sys/module/bcachefs/parameters/version", R_OK)
? read_file_u64(AT_FDCWD, "/sys/module/bcachefs/parameters/version")
: 0;
system("modprobe bcachefs");
unsigned kernel_version = bcachefs_kernel_version();
if (!kernel_version)
return false;
@ -151,11 +159,49 @@ static bool should_use_kernel_fsck(darray_str devs)
return ret;
}
static bool is_blockdev(const char *path)
{
struct stat s;
if (stat(path, &s))
return true;
return S_ISBLK(s.st_mode);
}
static void loopdev_free(const char *path)
{
char *cmd = mprintf("losetup -d %s", path);
system(cmd);
free(cmd);
}
static char *loopdev_alloc(const char *path)
{
char *cmd = mprintf("losetup --show -f %s", path);
FILE *f = popen(cmd, "r");
free(cmd);
if (!f) {
fprintf(stderr, "error executing losetup: %m\n");
return NULL;
}
char *line = NULL;
size_t n = 0;
getline(&line, &n, f);
int ret = pclose(f);
if (ret) {
fprintf(stderr, "error executing losetup: %i\n", ret);
free(line);
return NULL;
}
strim(line);
return line;
}
int cmd_fsck(int argc, char *argv[])
{
static const struct option longopts[] = {
{ "ratelimit_errors", no_argument, NULL, 'r' },
{ "reconstruct_alloc", no_argument, NULL, 'R' },
{ "kernel", no_argument, NULL, 'k' },
{ "no-kernel", no_argument, NULL, 'K' },
{ "help", no_argument, NULL, 'h' },
@ -165,16 +211,22 @@ int cmd_fsck(int argc, char *argv[])
int opt, ret = 0;
struct printbuf opts_str = PRINTBUF;
if (getenv("BCACHEFS_KERNEL_ONLY"))
kernel = true;
append_opt(&opts_str, "degraded");
append_opt(&opts_str, "fsck");
append_opt(&opts_str, "fix_errors=ask");
append_opt(&opts_str, "read_only");
while ((opt = getopt_long(argc, argv,
"apynfo:rRkvh",
"apynfo:rkKvh",
longopts, NULL)) != -1)
switch (opt) {
case 'a': /* outdated alias for -p */
case 'a':
/* "automatic" run, called by the system, for us to do checks as needed.
* we don't need checks here: */
exit(EXIT_SUCCESS);
case 'p':
case 'y':
append_opt(&opts_str, "fix_errors=yes");
@ -192,9 +244,6 @@ int cmd_fsck(int argc, char *argv[])
case 'r':
append_opt(&opts_str, "ratelimit_errors");
break;
case 'R':
append_opt(&opts_str, "reconstruct_alloc");
break;
case 'k':
kernel = true;
break;
@ -217,42 +266,63 @@ int cmd_fsck(int argc, char *argv[])
darray_str devs = get_or_split_cmdline_devs(argc, argv);
darray_for_each(devs, i)
if (dev_mounted(*i)) {
printf("Running fsck online\n");
return fsck_online(*i, opts_str.buf);
}
int kernel_probed = kernel;
if (kernel_probed < 0)
kernel_probed = should_use_kernel_fsck(devs);
struct bch_opts opts = bch2_opts_empty();
struct printbuf parse_later = PRINTBUF;
if (kernel_probed) {
struct bch_ioctl_fsck_offline *fsck = calloc(sizeof(*fsck) +
sizeof(u64) * devs.nr, 1);
darray_str loopdevs = {};
int fsck_fd = -1;
printf("Running in-kernel offline fsck\n");
struct bch_ioctl_fsck_offline *fsck = calloc(sizeof(*fsck) + sizeof(u64) * devs.nr, 1);
fsck->opts = (unsigned long)opts_str.buf;
darray_for_each(devs, i)
fsck->devs[i - devs.data] = (unsigned long) *i;
darray_for_each(devs, i) {
if (is_blockdev(*i)) {
fsck->devs[i - devs.data] = (unsigned long) *i;
} else {
char *l = loopdev_alloc(*i);
if (!l)
goto kernel_fsck_err;
darray_push(&loopdevs, l);
fsck->devs[i - devs.data] = (unsigned long) l;
}
}
fsck->nr_devs = devs.nr;
int ctl_fd = bcachectl_open();
int fsck_fd = ioctl(ctl_fd, BCH_IOCTL_FSCK_OFFLINE, fsck);
fsck_fd = ioctl(ctl_fd, BCH_IOCTL_FSCK_OFFLINE, fsck);
kernel_fsck_err:
free(fsck);
darray_for_each(loopdevs, i)
loopdev_free(*i);
darray_exit(&loopdevs);
if (fsck_fd < 0 && kernel < 0)
goto userland_fsck;
if (fsck_fd < 0)
die("BCH_IOCTL_FSCK_OFFLINE error: %s", bch2_err_str(fsck_fd));
die("BCH_IOCTL_FSCK_OFFLINE error: %s", bch2_err_str(errno));
ret = splice_fd_to_stdinout(fsck_fd);
} else {
userland_fsck:
ret = bch2_parse_mount_opts(NULL, &opts, opts_str.buf);
printf("Running userspace offline fsck\n");
ret = bch2_parse_mount_opts(NULL, &opts, &parse_later, opts_str.buf, false);
if (ret)
return ret;
darray_for_each(devs, i)
if (dev_mounted(*i))
return fsck_online(*i);
struct bch_fs *c = bch2_fs_open(devs.data, devs.nr, opts);
if (IS_ERR(c))
exit(8);

View File

@ -19,7 +19,7 @@
#include "libbcachefs/dirent.h"
#include "libbcachefs/errcode.h"
#include "libbcachefs/error.h"
#include "libbcachefs/fs-common.h"
#include "libbcachefs/namei.h"
#include "libbcachefs/inode.h"
#include "libbcachefs/io_read.h"
#include "libbcachefs/io_write.h"
@ -31,9 +31,6 @@
#include <linux/dcache.h>
/* XXX cut and pasted from fsck.c */
#define QSTR(n) { { { .len = strlen(n) } }, .name = n }
/* used by write_aligned function for waiting on bch2_write closure */
struct write_aligned_op_t {
struct closure cl;
@ -191,7 +188,7 @@ retry:
bch2_trans_begin(trans);
now = bch2_current_time(c);
ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_INTENT);
ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent);
if (ret)
goto err;
@ -242,7 +239,7 @@ static int do_create(struct bch_fs *c, subvol_inum dir,
bch2_inode_init_early(c, new_inode);
return bch2_trans_do(c, NULL, NULL, 0,
return bch2_trans_commit_do(c, NULL, NULL, 0,
bch2_create_trans(trans,
dir, &dir_u,
new_inode, &qstr,
@ -295,7 +292,7 @@ static void bcachefs_fuse_unlink(fuse_req_t req, fuse_ino_t dir_ino,
fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_unlink(%llu, %s)\n", dir.inum, name);
int ret = bch2_trans_do(c, NULL, NULL,
int ret = bch2_trans_commit_do(c, NULL, NULL,
BCH_TRANS_COMMIT_no_enospc,
bch2_unlink_trans(trans, dir, &dir_u,
&inode_u, &qstr, false));
@ -330,7 +327,7 @@ static void bcachefs_fuse_rename(fuse_req_t req,
src_dir.inum, srcname, dst_dir.inum, dstname, flags);
/* XXX handle overwrites */
ret = bch2_trans_do(c, NULL, NULL, 0,
ret = bch2_trans_commit_do(c, NULL, NULL, 0,
bch2_rename_trans(trans,
src_dir, &src_dir_u,
dst_dir, &dst_dir_u,
@ -354,7 +351,7 @@ static void bcachefs_fuse_link(fuse_req_t req, fuse_ino_t ino,
fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_link(%llu, %llu, %s)\n",
inum.inum, newparent.inum, newname);
ret = bch2_trans_do(c, NULL, NULL, 0,
ret = bch2_trans_commit_do(c, NULL, NULL, 0,
bch2_link_trans(trans, newparent, &dir_u,
inum, &inode_u, &qstr));
@ -478,10 +475,9 @@ static int read_aligned(struct bch_fs *c, subvol_inum inum, size_t aligned_size,
closure_init_stack(&cl);
closure_get(&cl);
rbio.bio.bi_end_io = bcachefs_fuse_read_endio;
rbio.bio.bi_private = &cl;
rbio.bio.bi_private = &cl;
bch2_read(c, rbio_init(&rbio.bio, io_opts), inum);
bch2_read(c, rbio_init(&rbio.bio, c, io_opts, bcachefs_fuse_read_endio), inum);
closure_sync(&cl);
@ -544,7 +540,7 @@ retry:
bch2_trans_begin(trans);
now = bch2_current_time(c);
ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_INTENT);
ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent);
if (ret)
goto err;
@ -1203,6 +1199,7 @@ int cmd_fusemount(int argc, char *argv[])
struct bch_opts bch_opts = bch2_opts_empty();
struct bf_context ctx = { 0 };
struct bch_fs *c = NULL;
struct fuse_session *se = NULL;
int ret = 0, i;
/* Parse arguments. */
@ -1221,9 +1218,9 @@ int cmd_fusemount(int argc, char *argv[])
goto out;
}
if (fuse_opts.show_version) {
/* TODO: Show bcachefs version. */
printf("FUSE library version %s\n", fuse_pkgversion());
fuse_lowlevel_version();
printf("bcachefs version: %s\n", VERSION_STRING);
ret = 0;
goto out;
}
@ -1263,17 +1260,22 @@ int cmd_fusemount(int argc, char *argv[])
bch2_err_str(PTR_ERR(c)));
/* Fuse */
struct fuse_session *se =
fuse_session_new(&args, &bcachefs_fuse_ops,
sizeof(bcachefs_fuse_ops), c);
if (!se)
die("fuse_lowlevel_new err: %m");
se = fuse_session_new(&args, &bcachefs_fuse_ops,
sizeof(bcachefs_fuse_ops), c);
if (!se) {
fprintf(stderr, "fuse_lowlevel_new err: %m\n");
goto err;
}
if (fuse_set_signal_handlers(se) < 0)
die("fuse_set_signal_handlers err: %m");
if (fuse_set_signal_handlers(se) < 0) {
fprintf(stderr, "fuse_set_signal_handlers err: %m\n");
goto err;
}
if (fuse_session_mount(se, fuse_opts.mountpoint))
die("fuse_mount err: %m");
if (fuse_session_mount(se, fuse_opts.mountpoint)) {
fprintf(stderr, "fuse_mount err: %m\n");
goto err;
}
/* This print statement is a trigger for tests. */
printf("Fuse mount initialized.\n");
@ -1287,17 +1289,22 @@ int cmd_fusemount(int argc, char *argv[])
ret = fuse_session_loop(se);
/* Cleanup */
fuse_session_unmount(se);
fuse_remove_signal_handlers(se);
fuse_session_destroy(se);
out:
if (se) {
fuse_session_unmount(se);
fuse_remove_signal_handlers(se);
fuse_session_destroy(se);
}
free(fuse_opts.mountpoint);
fuse_opt_free_args(&args);
bf_context_free(&ctx);
return ret ? 1 : 0;
err:
bch2_fs_stop(c);
goto out;
}
#endif /* BCACHEFS_FUSE */

View File

@ -66,7 +66,7 @@ int cmd_unlock(int argc, char *argv[])
if (ret)
die("Error opening %s: %s", dev, bch2_err_str(ret));
if (!bch2_sb_is_encrypted_and_locked(sb.sb))
if (!bch2_sb_is_encrypted(sb.sb))
die("%s is not encrypted", dev);
if (check)
@ -104,24 +104,19 @@ int cmd_set_passphrase(int argc, char *argv[])
if (IS_ERR(c))
die("Error opening %s: %s", argv[1], bch2_err_str(PTR_ERR(c)));
struct bch_sb_field_crypt *crypt = bch2_sb_field_get(c->disk_sb.sb, crypt);
struct bch_sb *sb = c->disk_sb.sb;
struct bch_sb_field_crypt *crypt = bch2_sb_field_get(sb, crypt);
if (!crypt)
die("Filesystem does not have encryption enabled");
struct bch_encrypted_key new_key;
new_key.magic = BCH_KEY_MAGIC;
int ret = bch2_decrypt_sb_key(c, crypt, &new_key.key);
struct bch_key key;
int ret = bch2_decrypt_sb_key(c, crypt, &key);
if (ret)
die("Error getting current key");
char *new_passphrase = read_passphrase_twice("Enter new passphrase: ");
struct bch_key passphrase_key = derive_passphrase(crypt, new_passphrase);
if (bch2_chacha_encrypt_key(&passphrase_key, __bch2_sb_key_nonce(c->disk_sb.sb),
&new_key, sizeof(new_key)))
die("error encrypting key");
crypt->key = new_key;
bch_crypt_update_passphrase(sb, crypt, &key, new_passphrase);
bch2_revoke_key(c->disk_sb.sb);
bch2_write_super(c);
@ -142,18 +137,17 @@ int cmd_remove_passphrase(int argc, char *argv[])
if (IS_ERR(c))
die("Error opening %s: %s", argv[1], bch2_err_str(PTR_ERR(c)));
struct bch_sb_field_crypt *crypt = bch2_sb_field_get(c->disk_sb.sb, crypt);
struct bch_sb *sb = c->disk_sb.sb;
struct bch_sb_field_crypt *crypt = bch2_sb_field_get(sb, crypt);
if (!crypt)
die("Filesystem does not have encryption enabled");
struct bch_encrypted_key new_key;
new_key.magic = BCH_KEY_MAGIC;
int ret = bch2_decrypt_sb_key(c, crypt, &new_key.key);
struct bch_key key;
int ret = bch2_decrypt_sb_key(c, crypt, &key);
if (ret)
die("Error getting current key");
crypt->key = new_key;
bch_crypt_update_passphrase(sb, crypt, &key, NULL);
bch2_write_super(c);
bch2_fs_stop(c);

View File

@ -27,30 +27,44 @@ static void kill_btree_node_usage(void)
"Report bugs to <linux-bcachefs@vger.kernel.org>");
}
struct kill_node {
unsigned btree;
unsigned level;
u64 idx;
};
int cmd_kill_btree_node(int argc, char *argv[])
{
struct bch_opts opts = bch2_opts_empty();
enum btree_id btree_id = 0;
unsigned level = 0;
u64 node_index = 0;
DARRAY(struct kill_node) kill_nodes = {};
int opt;
opt_set(opts, read_only, true);
while ((opt = getopt(argc, argv, "b:l:i:h")) != -1)
while ((opt = getopt(argc, argv, "n:h")) != -1)
switch (opt) {
case 'b':
btree_id = read_string_list_or_die(optarg,
__bch2_btree_ids, "btree id");
break;
case 'l':
if (kstrtouint(optarg, 10, &level) || level >= BTREE_MAX_DEPTH)
case 'n': {
char *p = optarg;
const char *str_btree = strsep(&p, ":");
const char *str_level = strsep(&p, ":");
const char *str_idx = strsep(&p, ":");
struct kill_node n = {
.btree = read_string_list_or_die(str_btree,
__bch2_btree_ids, "btree id"),
};
if (str_level &&
(kstrtouint(str_level, 10, &n.level) || n.level >= BTREE_MAX_DEPTH))
die("invalid level");
if (str_idx &&
kstrtoull(str_idx, 10, &n.idx))
die("invalid index %s", str_idx);
darray_push(&kill_nodes, n);
break;
case 'i':
if (kstrtoull(optarg, 10, &node_index))
die("invalid index %s", optarg);
break;
}
case 'h':
kill_btree_node_usage();
exit(EXIT_SUCCESS);
@ -64,9 +78,6 @@ int cmd_kill_btree_node(int argc, char *argv[])
if (IS_ERR(c))
die("error opening %s: %s", argv[0], bch2_err_str(PTR_ERR(c)));
struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter;
struct btree *b;
int ret;
void *zeroes;
@ -74,44 +85,56 @@ int cmd_kill_btree_node(int argc, char *argv[])
if (ret)
die("error %s from posix_memalign", bch2_err_str(ret));
__for_each_btree_node(trans, iter, btree_id, POS_MIN, 0, level, 0, b, ret) {
if (b->c.level != level)
continue;
struct btree_trans *trans = bch2_trans_get(c);
if (!node_index) {
struct printbuf buf = PRINTBUF;
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
bch_info(c, "killing btree node %s", buf.buf);
printbuf_exit(&buf);
darray_for_each(kill_nodes, i) {
ret = __for_each_btree_node(trans, iter, i->btree, POS_MIN, 0, i->level, 0, b, ({
if (b->c.level != i->level)
continue;
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key));
bkey_for_each_ptr(ptrs, ptr) {
struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
int ret2 = 0;
if (!i->idx) {
struct printbuf buf = PRINTBUF;
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
bch_info(c, "killing btree node %s l=%u %s",
bch2_btree_id_str(i->btree), i->level, buf.buf);
printbuf_exit(&buf);
ret = pwrite(ca->disk_sb.bdev->bd_fd, zeroes,
c->opts.block_size, ptr->offset << 9);
if (ret != c->opts.block_size) {
bch_err(c, "pwrite error: expected %u got %i %s",
c->opts.block_size, ret, strerror(errno));
ret = EXIT_FAILURE;
goto done;
ret2 = 1;
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key));
bkey_for_each_ptr(ptrs, ptr) {
struct bch_dev *ca = bch2_dev_tryget(c, ptr->dev);
if (!ca)
continue;
int ret3 = pwrite(ca->disk_sb.bdev->bd_fd, zeroes,
c->opts.block_size, ptr->offset << 9);
bch2_dev_put(ca);
if (ret3 != c->opts.block_size) {
bch_err(c, "pwrite error: expected %u got %i %s",
c->opts.block_size, ret, strerror(errno));
ret2 = EXIT_FAILURE;
}
}
}
ret = 0;
goto done;
i->idx--;
ret2;
}));
if (ret < 0) {
bch_err(c, "error %i walking btree nodes", ret);
break;
} else if (!ret) {
bch_err(c, "node at specified index not found");
ret = EXIT_FAILURE;
break;
}
node_index--;
}
if (ret)
bch_err(c, "error %i walking btree nodes", ret);
else
bch_err(c, "node at specified index not found");
ret = EXIT_FAILURE;
done:
bch2_trans_iter_exit(trans, &iter);
bch2_trans_put(trans);
bch2_trans_put(trans);
bch2_fs_stop(c);
return ret;
darray_exit(&kill_nodes);
return ret < 0 ? ret : 0;
}

View File

@ -51,6 +51,11 @@ static inline bool entry_is_transaction_start(struct jset_entry *entry)
return entry->type == BCH_JSET_ENTRY_log && !entry->level;
}
static inline bool entry_is_log_msg(struct jset_entry *entry)
{
return entry->type == BCH_JSET_ENTRY_log && entry->level;
}
typedef DARRAY(struct bbpos_range) d_bbpos_range;
typedef DARRAY(enum btree_id) d_btree_id;
@ -60,9 +65,21 @@ static bool bkey_matches_filter(d_bbpos_range filter, struct jset_entry *entry,
struct bbpos k_start = BBPOS(entry->btree_id, bkey_start_pos(&k->k));
struct bbpos k_end = BBPOS(entry->btree_id, k->k.p);
if (bbpos_cmp(k_start, i->end) < 0 &&
bbpos_cmp(k_end, i->start) > 0)
return true;
if (!i->start.pos.snapshot &&
!i->end.pos.snapshot) {
k_start.pos.snapshot = 0;
k_end.pos.snapshot = 0;
}
if (!k->k.size) {
if (bbpos_cmp(k_start, i->start) >= 0 &&
bbpos_cmp(k_end, i->end) <= 0)
return true;
} else {
if (bbpos_cmp(i->start, k_end) <= 0 &&
bbpos_cmp(i->end, k_start) >= 0)
return true;
}
}
return false;
}
@ -70,9 +87,9 @@ static bool bkey_matches_filter(d_bbpos_range filter, struct jset_entry *entry,
static bool entry_matches_transaction_filter(struct jset_entry *entry,
d_bbpos_range filter)
{
if (entry->type == BCH_JSET_ENTRY_btree_root ||
entry->type == BCH_JSET_ENTRY_btree_keys ||
entry->type == BCH_JSET_ENTRY_overwrite)
if (!entry->level &&
(entry->type == BCH_JSET_ENTRY_btree_keys ||
entry->type == BCH_JSET_ENTRY_overwrite))
jset_entry_for_each_key(entry, k)
if (bkey_matches_filter(filter, entry, k))
return true;
@ -80,17 +97,36 @@ static bool entry_matches_transaction_filter(struct jset_entry *entry,
}
static bool should_print_transaction(struct jset_entry *entry, struct jset_entry *end,
d_bbpos_range filter)
darray_str msg_filter,
d_bbpos_range key_filter)
{
if (!filter.nr)
struct jset_entry_log *l = container_of(entry, struct jset_entry_log, entry);
unsigned b = jset_entry_log_msg_bytes(l);
bool have_log_messages = false;
bool have_non_log_messages = false;
darray_for_each(msg_filter, i)
if (!strncmp(*i, l->d, b))
return false;
if (!key_filter.nr)
return true;
for (entry = vstruct_next(entry);
entry != end && !entry_is_transaction_start(entry);
entry = vstruct_next(entry))
if (entry_matches_transaction_filter(entry, filter))
entry = vstruct_next(entry)) {
if (entry_matches_transaction_filter(entry, key_filter))
return true;
if (entry_is_log_msg(entry))
have_log_messages = true;
else
have_non_log_messages = true;
}
if (have_log_messages && !have_non_log_messages)
return true;
return false;
}
@ -112,8 +148,41 @@ static bool should_print_entry(struct jset_entry *entry, d_btree_id filter)
return false;
}
static void journal_entry_header_to_text(struct printbuf *out,
struct bch_fs *c,
struct journal_replay *p, bool blacklisted)
{
if (blacklisted)
prt_str(out, "blacklisted ");
prt_printf(out,
"\n"
"journal entry %llu\n"
" version %u\n"
" last seq %llu\n"
" flush %u\n"
" written at ",
le64_to_cpu(p->j.seq),
le32_to_cpu(p->j.version),
le64_to_cpu(p->j.last_seq),
!JSET_NO_FLUSH(&p->j));
bch2_journal_ptrs_to_text(out, c, p);
if (blacklisted)
star_start_of_lines(out->buf);
}
static void journal_entry_header_print(struct bch_fs *c, struct journal_replay *p, bool blacklisted)
{
struct printbuf buf = PRINTBUF;
journal_entry_header_to_text(&buf, c, p, blacklisted);
printf("%s\n", buf.buf);
printbuf_exit(&buf);
}
static void journal_entries_print(struct bch_fs *c, unsigned nr_entries,
d_bbpos_range transaction_filter,
darray_str transaction_msg_filter,
d_bbpos_range transaction_key_filter,
d_btree_id key_filter)
{
struct journal_replay *p, **_p;
@ -121,6 +190,8 @@ static void journal_entries_print(struct bch_fs *c, unsigned nr_entries,
struct printbuf buf = PRINTBUF;
genradix_for_each(&c->journal_entries, iter, _p) {
bool printed_header = false;
p = *_p;
if (!p)
continue;
@ -132,28 +203,10 @@ static void journal_entries_print(struct bch_fs *c, unsigned nr_entries,
bch2_journal_seq_is_blacklisted(c,
le64_to_cpu(p->j.seq), false);
if (!transaction_filter.nr) {
if (blacklisted)
printf("blacklisted ");
printf("journal entry %llu\n", le64_to_cpu(p->j.seq));
printbuf_reset(&buf);
prt_printf(&buf,
" version %u\n"
" last seq %llu\n"
" flush %u\n"
" written at ",
le32_to_cpu(p->j.version),
le64_to_cpu(p->j.last_seq),
!JSET_NO_FLUSH(&p->j));
bch2_journal_ptrs_to_text(&buf, c, p);
if (blacklisted)
star_start_of_lines(buf.buf);
printf("%s\n", buf.buf);
printbuf_reset(&buf);
if (!transaction_msg_filter.nr &&
!transaction_key_filter.nr) {
journal_entry_header_print(c, p, blacklisted);
printed_header = true;
}
struct jset_entry *entry = p->j.start;
@ -165,7 +218,9 @@ static void journal_entries_print(struct bch_fs *c, unsigned nr_entries,
* commit:
*/
if (entry_is_transaction_start(entry)) {
if (!should_print_transaction(entry, end, transaction_filter)) {
if (!should_print_transaction(entry, end,
transaction_msg_filter,
transaction_key_filter)) {
do {
entry = vstruct_next(entry);
} while (entry != end && !entry_is_transaction_start(entry));
@ -179,7 +234,11 @@ static void journal_entries_print(struct bch_fs *c, unsigned nr_entries,
if (!should_print_entry(entry, key_filter))
goto next;
bool highlight = entry_matches_transaction_filter(entry, transaction_filter);
if (!printed_header)
journal_entry_header_print(c, p, blacklisted);
printed_header = true;
bool highlight = entry_matches_transaction_filter(entry, transaction_key_filter);
if (highlight)
fputs(RED, stdout);
@ -213,10 +272,12 @@ int cmd_list_journal(int argc, char *argv[])
};
struct bch_opts opts = bch2_opts_empty();
u32 nr_entries = U32_MAX;
d_bbpos_range transaction_filter = { 0 };
d_btree_id key_filter = { 0 };
darray_str transaction_msg_filter = {};
d_bbpos_range transaction_key_filter = {};
d_btree_id key_filter = {};
int opt;
opt_set(opts, noexcl, true);
opt_set(opts, nochanges, true);
opt_set(opts, norecovery, true);
opt_set(opts, read_only, true);
@ -227,7 +288,7 @@ int cmd_list_journal(int argc, char *argv[])
opt_set(opts, retain_recovery_info ,true);
opt_set(opts, read_journal_only,true);
while ((opt = getopt_long(argc, argv, "an:t:k:vh",
while ((opt = getopt_long(argc, argv, "an:m:t:k:vh",
longopts, NULL)) != -1)
switch (opt) {
case 'a':
@ -238,8 +299,11 @@ int cmd_list_journal(int argc, char *argv[])
die("error parsing nr_entries");
opt_set(opts, read_entire_journal, true);
break;
case 'm':
darray_push(&transaction_msg_filter, strdup(optarg));
break;
case 't':
darray_push(&transaction_filter, bbpos_range_parse(optarg));
darray_push(&transaction_key_filter, bbpos_range_parse(optarg));
break;
case 'k':
darray_push(&key_filter, read_string_list_or_die(optarg, __bch2_btree_ids, "btree id"));
@ -262,7 +326,10 @@ int cmd_list_journal(int argc, char *argv[])
if (IS_ERR(c))
die("error opening %s: %s", argv[0], bch2_err_str(PTR_ERR(c)));
journal_entries_print(c, nr_entries, transaction_filter, key_filter);
journal_entries_print(c, nr_entries,
transaction_msg_filter,
transaction_key_filter,
key_filter);
bch2_fs_stop(c);
return 0;
}

View File

@ -1,9 +1,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <sys/xattr.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
@ -20,27 +18,18 @@
#include "cmds.h"
#include "crypto.h"
#include "libbcachefs.h"
#include "posix_to_bcachefs.h"
#include <linux/dcache.h>
#include <linux/generic-radix-tree.h>
#include <linux/xattr.h>
#include "libbcachefs/bcachefs.h"
#include "libbcachefs/alloc_background.h"
#include "libbcachefs/alloc_foreground.h"
#include "libbcachefs/btree_update.h"
#include "libbcachefs/buckets.h"
#include "libbcachefs/dirent.h"
#include "libbcachefs/errcode.h"
#include "libbcachefs/fs-common.h"
#include "libbcachefs/inode.h"
#include "libbcachefs/io_write.h"
#include "libbcachefs/replicas.h"
#include "libbcachefs/str_hash.h"
#include "libbcachefs/super.h"
#include "libbcachefs/xattr.h"
/* XXX cut and pasted from fsck.c */
#define QSTR(n) { { { .len = strlen(n) } }, .name = n }
static char *dev_t_to_path(dev_t dev)
{
@ -117,403 +106,6 @@ static void mark_unreserved_space(struct bch_fs *c, ranges extents)
}
}
static void update_inode(struct bch_fs *c,
struct bch_inode_unpacked *inode)
{
struct bkey_inode_buf packed;
int ret;
bch2_inode_pack(&packed, inode);
packed.inode.k.p.snapshot = U32_MAX;
ret = bch2_btree_insert(c, BTREE_ID_inodes, &packed.inode.k_i,
NULL, 0);
if (ret)
die("error updating inode: %s", bch2_err_str(ret));
}
static void create_link(struct bch_fs *c,
struct bch_inode_unpacked *parent,
const char *name, u64 inum, mode_t mode)
{
struct qstr qstr = QSTR(name);
struct bch_inode_unpacked parent_u;
struct bch_inode_unpacked inode;
int ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_link_trans(trans,
(subvol_inum) { 1, parent->bi_inum }, &parent_u,
(subvol_inum) { 1, inum }, &inode, &qstr));
if (ret)
die("error creating hardlink: %s", bch2_err_str(ret));
}
static struct bch_inode_unpacked create_file(struct bch_fs *c,
struct bch_inode_unpacked *parent,
const char *name,
uid_t uid, gid_t gid,
mode_t mode, dev_t rdev)
{
struct qstr qstr = QSTR(name);
struct bch_inode_unpacked new_inode;
bch2_inode_init_early(c, &new_inode);
int ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_create_trans(trans,
(subvol_inum) { 1, parent->bi_inum }, parent,
&new_inode, &qstr,
uid, gid, mode, rdev, NULL, NULL,
(subvol_inum) {}, 0));
if (ret)
die("error creating %s: %s", name, bch2_err_str(ret));
return new_inode;
}
#define for_each_xattr_handler(handlers, handler) \
if (handlers) \
for ((handler) = *(handlers)++; \
(handler) != NULL; \
(handler) = *(handlers)++)
static const struct xattr_handler *xattr_resolve_name(char **name)
{
const struct xattr_handler **handlers = bch2_xattr_handlers;
const struct xattr_handler *handler;
for_each_xattr_handler(handlers, handler) {
char *n;
n = strcmp_prefix(*name, xattr_prefix(handler));
if (n) {
if (!handler->prefix ^ !*n) {
if (*n)
continue;
return ERR_PTR(-EINVAL);
}
*name = n;
return handler;
}
}
return ERR_PTR(-EOPNOTSUPP);
}
static void copy_times(struct bch_fs *c, struct bch_inode_unpacked *dst,
struct stat *src)
{
dst->bi_atime = timespec_to_bch2_time(c, src->st_atim);
dst->bi_mtime = timespec_to_bch2_time(c, src->st_mtim);
dst->bi_ctime = timespec_to_bch2_time(c, src->st_ctim);
}
static void copy_xattrs(struct bch_fs *c, struct bch_inode_unpacked *dst,
char *src)
{
struct bch_hash_info hash_info = bch2_hash_info_init(c, dst);
char attrs[XATTR_LIST_MAX];
ssize_t attrs_size = llistxattr(src, attrs, sizeof(attrs));
if (attrs_size < 0)
die("listxattr error: %m");
char *next, *attr;
for (attr = attrs;
attr < attrs + attrs_size;
attr = next) {
next = attr + strlen(attr) + 1;
char val[XATTR_SIZE_MAX];
ssize_t val_size = lgetxattr(src, attr, val, sizeof(val));
if (val_size < 0)
die("error getting xattr val: %m");
const struct xattr_handler *h = xattr_resolve_name(&attr);
struct bch_inode_unpacked inode_u;
int ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_xattr_set(trans,
(subvol_inum) { 1, dst->bi_inum },
&inode_u, &hash_info, attr,
val, val_size, h->flags, 0));
if (ret < 0)
die("error creating xattr: %s", bch2_err_str(ret));
}
}
#define WRITE_DATA_BUF (1 << 20)
static char buf[WRITE_DATA_BUF] __aligned(PAGE_SIZE);
static void write_data(struct bch_fs *c,
struct bch_inode_unpacked *dst_inode,
u64 dst_offset, void *buf, size_t len)
{
struct bch_write_op op;
struct bio_vec bv[WRITE_DATA_BUF / PAGE_SIZE];
BUG_ON(dst_offset & (block_bytes(c) - 1));
BUG_ON(len & (block_bytes(c) - 1));
BUG_ON(len > WRITE_DATA_BUF);
bio_init(&op.wbio.bio, NULL, bv, ARRAY_SIZE(bv), 0);
bch2_bio_map(&op.wbio.bio, buf, len);
bch2_write_op_init(&op, c, bch2_opts_to_inode_opts(c->opts));
op.write_point = writepoint_hashed(0);
op.nr_replicas = 1;
op.subvol = 1;
op.pos = SPOS(dst_inode->bi_inum, dst_offset >> 9, U32_MAX);
op.flags |= BCH_WRITE_SYNC;
int ret = bch2_disk_reservation_get(c, &op.res, len >> 9,
c->opts.data_replicas, 0);
if (ret)
die("error reserving space in new filesystem: %s", bch2_err_str(ret));
closure_call(&op.cl, bch2_write, NULL, NULL);
BUG_ON(!(op.flags & BCH_WRITE_DONE));
dst_inode->bi_sectors += len >> 9;
if (op.error)
die("write error: %s", bch2_err_str(op.error));
}
static void copy_data(struct bch_fs *c,
struct bch_inode_unpacked *dst_inode,
int src_fd, u64 start, u64 end)
{
while (start < end) {
unsigned len = min_t(u64, end - start, sizeof(buf));
unsigned pad = round_up(len, block_bytes(c)) - len;
xpread(src_fd, buf, len, start);
memset(buf + len, 0, pad);
write_data(c, dst_inode, start, buf, len + pad);
start += len;
}
}
static void link_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
u64 logical, u64 physical, u64 length)
{
struct bch_dev *ca = c->devs[0];
BUG_ON(logical & (block_bytes(c) - 1));
BUG_ON(physical & (block_bytes(c) - 1));
BUG_ON(length & (block_bytes(c) - 1));
logical >>= 9;
physical >>= 9;
length >>= 9;
BUG_ON(physical + length > bucket_to_sector(ca, ca->mi.nbuckets));
while (length) {
struct bkey_i_extent *e;
BKEY_PADDED_ONSTACK(k, BKEY_EXTENT_VAL_U64s_MAX) k;
u64 b = sector_to_bucket(ca, physical);
struct disk_reservation res;
unsigned sectors;
int ret;
sectors = min(ca->mi.bucket_size -
(physical & (ca->mi.bucket_size - 1)),
length);
e = bkey_extent_init(&k.k);
e->k.p.inode = dst->bi_inum;
e->k.p.offset = logical + sectors;
e->k.p.snapshot = U32_MAX;
e->k.size = sectors;
bch2_bkey_append_ptr(&e->k_i, (struct bch_extent_ptr) {
.offset = physical,
.dev = 0,
.gen = *bucket_gen(ca, b),
});
ret = bch2_disk_reservation_get(c, &res, sectors, 1,
BCH_DISK_RESERVATION_NOFAIL);
if (ret)
die("error reserving space in new filesystem: %s",
bch2_err_str(ret));
ret = bch2_btree_insert(c, BTREE_ID_extents, &e->k_i, &res, 0);
if (ret)
die("btree insert error %s", bch2_err_str(ret));
bch2_disk_reservation_put(c, &res);
dst->bi_sectors += sectors;
logical += sectors;
physical += sectors;
length -= sectors;
}
}
static void copy_link(struct bch_fs *c, struct bch_inode_unpacked *dst,
char *src)
{
ssize_t ret = readlink(src, buf, sizeof(buf));
if (ret < 0)
die("readlink error: %m");
write_data(c, dst, 0, buf, round_up(ret, block_bytes(c)));
}
static void copy_file(struct bch_fs *c, struct bch_inode_unpacked *dst,
int src_fd, u64 src_size,
char *src_path, ranges *extents)
{
struct fiemap_iter iter;
struct fiemap_extent e;
fiemap_for_each(src_fd, iter, e)
if (e.fe_flags & FIEMAP_EXTENT_UNKNOWN) {
fsync(src_fd);
break;
}
fiemap_iter_exit(&iter);
fiemap_for_each(src_fd, iter, e) {
u64 src_max = roundup(src_size, block_bytes(c));
e.fe_length = min(e.fe_length, src_max - e.fe_logical);
if ((e.fe_logical & (block_bytes(c) - 1)) ||
(e.fe_length & (block_bytes(c) - 1)))
die("Unaligned extent in %s - can't handle", src_path);
if (e.fe_flags & (FIEMAP_EXTENT_UNKNOWN|
FIEMAP_EXTENT_ENCODED|
FIEMAP_EXTENT_NOT_ALIGNED|
FIEMAP_EXTENT_DATA_INLINE)) {
copy_data(c, dst, src_fd, e.fe_logical,
min(src_size - e.fe_logical,
e.fe_length));
continue;
}
/*
* if the data is below 1 MB, copy it so it doesn't conflict
* with bcachefs's potentially larger superblock:
*/
if (e.fe_physical < 1 << 20) {
copy_data(c, dst, src_fd, e.fe_logical,
min(src_size - e.fe_logical,
e.fe_length));
continue;
}
if ((e.fe_physical & (block_bytes(c) - 1)))
die("Unaligned extent in %s - can't handle", src_path);
range_add(extents, e.fe_physical, e.fe_length);
link_data(c, dst, e.fe_logical, e.fe_physical, e.fe_length);
}
fiemap_iter_exit(&iter);
}
struct copy_fs_state {
u64 bcachefs_inum;
dev_t dev;
GENRADIX(u64) hardlinks;
ranges extents;
};
static void copy_dir(struct copy_fs_state *s,
struct bch_fs *c,
struct bch_inode_unpacked *dst,
int src_fd, const char *src_path)
{
DIR *dir = fdopendir(src_fd);
struct dirent *d;
while ((errno = 0), (d = readdir(dir))) {
struct bch_inode_unpacked inode;
int fd;
if (fchdir(src_fd))
die("chdir error: %m");
struct stat stat =
xfstatat(src_fd, d->d_name, AT_SYMLINK_NOFOLLOW);
if (!strcmp(d->d_name, ".") ||
!strcmp(d->d_name, "..") ||
!strcmp(d->d_name, "lost+found") ||
stat.st_ino == s->bcachefs_inum)
continue;
char *child_path = mprintf("%s/%s", src_path, d->d_name);
if (stat.st_dev != s->dev)
die("%s does not have correct st_dev!", child_path);
u64 *dst_inum = S_ISREG(stat.st_mode)
? genradix_ptr_alloc(&s->hardlinks, stat.st_ino, GFP_KERNEL)
: NULL;
if (dst_inum && *dst_inum) {
create_link(c, dst, d->d_name, *dst_inum, S_IFREG);
goto next;
}
inode = create_file(c, dst, d->d_name,
stat.st_uid, stat.st_gid,
stat.st_mode, stat.st_rdev);
if (dst_inum)
*dst_inum = inode.bi_inum;
copy_times(c, &inode, &stat);
copy_xattrs(c, &inode, d->d_name);
/* copy xattrs */
switch (mode_to_type(stat.st_mode)) {
case DT_DIR:
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
copy_dir(s, c, &inode, fd, child_path);
close(fd);
break;
case DT_REG:
inode.bi_size = stat.st_size;
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
copy_file(c, &inode, fd, stat.st_size,
child_path, &s->extents);
close(fd);
break;
case DT_LNK:
inode.bi_size = stat.st_size;
copy_link(c, &inode, d->d_name);
break;
case DT_FIFO:
case DT_CHR:
case DT_BLK:
case DT_SOCK:
case DT_WHT:
/* nothing else to copy for these: */
break;
default:
BUG();
}
update_inode(c, &inode);
next:
free(child_path);
}
if (errno)
die("readdir error: %m");
closedir(dir);
}
static ranges reserve_new_fs_space(const char *file_path, unsigned block_size,
u64 size, u64 *bcachefs_inum, dev_t dev,
bool force)
@ -561,71 +153,15 @@ static ranges reserve_new_fs_space(const char *file_path, unsigned block_size,
return extents;
}
static void reserve_old_fs_space(struct bch_fs *c,
struct bch_inode_unpacked *root_inode,
ranges *extents)
{
struct bch_dev *ca = c->devs[0];
struct bch_inode_unpacked dst;
struct hole_iter iter;
struct range i;
dst = create_file(c, root_inode, "old_migrated_filesystem",
0, 0, S_IFREG|0400, 0);
dst.bi_size = bucket_to_sector(ca, ca->mi.nbuckets) << 9;
ranges_sort_merge(extents);
for_each_hole(iter, *extents, bucket_to_sector(ca, ca->mi.nbuckets) << 9, i)
link_data(c, &dst, i.start, i.start, i.end - i.start);
update_inode(c, &dst);
}
static void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
u64 bcachefs_inum, ranges *extents)
{
syncfs(src_fd);
struct bch_inode_unpacked root_inode;
int ret = bch2_inode_find_by_inum(c, (subvol_inum) { 1, BCACHEFS_ROOT_INO },
&root_inode);
if (ret)
die("error looking up root directory: %s", bch2_err_str(ret));
if (fchdir(src_fd))
die("chdir error: %m");
struct stat stat = xfstat(src_fd);
copy_times(c, &root_inode, &stat);
copy_xattrs(c, &root_inode, ".");
struct copy_fs_state s = {
.bcachefs_inum = bcachefs_inum,
.dev = stat.st_dev,
.extents = *extents,
};
/* now, copy: */
copy_dir(&s, c, &root_inode, src_fd, src_path);
reserve_old_fs_space(c, &root_inode, &s.extents);
update_inode(c, &root_inode);
darray_exit(&s.extents);
genradix_free(&s.hardlinks);
}
static void find_superblock_space(ranges extents,
struct format_opts opts,
struct dev_opts *dev)
{
darray_for_each(extents, i) {
u64 start = round_up(max(256ULL << 10, i->start),
dev->bucket_size << 9);
dev->opts.bucket_size << 9);
u64 end = round_down(i->end,
dev->bucket_size << 9);
dev->opts.bucket_size << 9);
/* Need space for two superblocks: */
if (start + (opts.superblock_size << 9) * 2 <= end) {
@ -673,38 +209,43 @@ static int migrate_fs(const char *fs_path,
if (!S_ISDIR(stat.st_mode))
die("%s is not a directory", fs_path);
struct dev_opts dev = dev_opts_default();
dev_opts_list devs = {};
darray_push(&devs, dev_opts_default());
dev.path = dev_t_to_path(stat.st_dev);
dev.file = bdev_file_open_by_path(dev.path, BLK_OPEN_READ|BLK_OPEN_WRITE, &dev, NULL);
struct dev_opts *dev = &devs.data[0];
int ret = PTR_ERR_OR_ZERO(dev.file);
dev->path = dev_t_to_path(stat.st_dev);
dev->file = bdev_file_open_by_path(dev->path, BLK_OPEN_READ|BLK_OPEN_WRITE, dev, NULL);
int ret = PTR_ERR_OR_ZERO(dev->file);
if (ret < 0)
die("Error opening device to format %s: %s", dev.path, strerror(-ret));
dev.bdev = file_bdev(dev.file);
die("Error opening device to format %s: %s", dev->path, strerror(-ret));
dev->bdev = file_bdev(dev->file);
opt_set(fs_opts, block_size, get_blocksize(dev.bdev->bd_fd));
opt_set(fs_opts, block_size, get_blocksize(dev->bdev->bd_fd));
char *file_path = mprintf("%s/bcachefs", fs_path);
printf("Creating new filesystem on %s in space reserved at %s\n",
dev.path, file_path);
dev->path, file_path);
dev.size = get_size(dev.bdev->bd_fd);
dev.bucket_size = bch2_pick_bucket_size(fs_opts, &dev);
dev.nbuckets = dev.size / dev.bucket_size;
dev->fs_size = get_size(dev->bdev->bd_fd);
opt_set(dev->opts, bucket_size, bch2_pick_bucket_size(fs_opts, devs));
bch2_check_bucket_size(fs_opts, &dev);
dev->nbuckets = dev->fs_size / dev->opts.bucket_size;
bch2_check_bucket_size(fs_opts, dev);
u64 bcachefs_inum;
ranges extents = reserve_new_fs_space(file_path,
fs_opts.block_size >> 9,
get_size(dev.bdev->bd_fd) / 5,
get_size(dev->bdev->bd_fd) / 5,
&bcachefs_inum, stat.st_dev, force);
find_superblock_space(extents, format_opts, &dev);
find_superblock_space(extents, format_opts, dev);
struct bch_sb *sb = bch2_format(fs_opt_strs, fs_opts, format_opts, devs);
darray_exit(&devs);
struct bch_sb *sb = bch2_format(fs_opt_strs,
fs_opts, format_opts, &dev, 1);
u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]);
if (format_opts.passphrase)
@ -712,26 +253,38 @@ static int migrate_fs(const char *fs_path,
free(sb);
struct bch_opts opts = bch2_opts_empty();
struct bch_fs *c = NULL;
char *path[1] = { dev.path };
char *path[1] = { dev->path };
struct bch_opts opts = bch2_opts_empty();
opt_set(opts, sb, sb_offset);
opt_set(opts, nostart, true);
opt_set(opts, noexcl, true);
opt_set(opts, buckets_nouse, true);
c = bch2_fs_open(path, 1, opts);
struct bch_fs *c = bch2_fs_open(path, 1, opts);
if (IS_ERR(c))
die("Error opening new filesystem: %s", bch2_err_str(PTR_ERR(c)));
ret = bch2_buckets_nouse_alloc(c);
if (ret)
die("Error allocating buckets_nouse: %s", bch2_err_str(ret));
mark_unreserved_space(c, extents);
ret = bch2_fs_start(c);
if (ret)
die("Error starting new filesystem: %s", bch2_err_str(ret));
copy_fs(c, fs_fd, fs_path, bcachefs_inum, &extents);
struct copy_fs_state s = {
.bcachefs_inum = bcachefs_inum,
.dev = stat.st_dev,
.extents = extents,
.type = BCH_MIGRATE_migrate,
};
u64 reserve_start = round_up((format_opts.superblock_size * 2 + 8) << 9,
dev->opts.bucket_size);
copy_fs(c, fs_fd, fs_path, &s, reserve_start);
bch2_fs_stop(c);
@ -754,12 +307,12 @@ static int migrate_fs(const char *fs_path,
"superblock at the default offset and finish the migration run\n"
" bcachefs migrate-superblock -d %s -o %llu\n"
"\n"
"The new filesystem will have a file at /old_migrated_filestem\n"
"The new filesystem will have a file at /old_migrated_filesystem\n"
"referencing all disk space that might be used by the existing\n"
"filesystem. That file can be deleted once the old filesystem is\n"
"no longer needed (and should be deleted prior to running\n"
"bcachefs migrate-superblock)\n",
sb_offset, dev.path, dev.path, sb_offset);
sb_offset, dev->path, dev->path, sb_offset);
return 0;
}
@ -823,7 +376,7 @@ static void migrate_superblock_usage(void)
int cmd_migrate_superblock(int argc, char *argv[])
{
char *dev = NULL;
u64 offset = 0;
u64 sb_offset = 0;
int opt, ret;
while ((opt = getopt(argc, argv, "d:o:h")) != -1)
@ -832,7 +385,7 @@ int cmd_migrate_superblock(int argc, char *argv[])
dev = optarg;
break;
case 'o':
ret = kstrtou64(optarg, 10, &offset);
ret = kstrtou64(optarg, 10, &sb_offset);
if (ret)
die("Invalid offset");
break;
@ -844,29 +397,72 @@ int cmd_migrate_superblock(int argc, char *argv[])
if (!dev)
die("Please specify a device");
if (!offset)
if (!sb_offset)
die("Please specify offset of existing superblock");
int fd = xopen(dev, O_RDWR);
struct bch_sb *sb = __bch2_super_read(fd, offset);
struct bch_sb *sb = __bch2_super_read(fd, sb_offset);
unsigned sb_size = 1U << sb->layout.sb_max_size_bits;
if (sb->layout.nr_superblocks >= ARRAY_SIZE(sb->layout.sb_offset))
die("Can't add superblock: no space left in superblock layout");
unsigned i;
for (i = 0; i < sb->layout.nr_superblocks; i++)
if (le64_to_cpu(sb->layout.sb_offset[i]) == BCH_SB_SECTOR)
die("Superblock layout already has default superblock");
for (unsigned i = 0; i < sb->layout.nr_superblocks; i++)
if (le64_to_cpu(sb->layout.sb_offset[i]) == BCH_SB_SECTOR ||
le64_to_cpu(sb->layout.sb_offset[i]) == BCH_SB_SECTOR + sb_size)
die("Superblock layout already has default superblocks");
memmove(&sb->layout.sb_offset[1],
memmove(&sb->layout.sb_offset[2],
&sb->layout.sb_offset[0],
sb->layout.nr_superblocks * sizeof(u64));
sb->layout.nr_superblocks++;
sb->layout.nr_superblocks += 2;
sb->layout.sb_offset[0] = cpu_to_le64(BCH_SB_SECTOR);
sb->layout.sb_offset[1] = cpu_to_le64(BCH_SB_SECTOR + sb_size);
/* also write first 0-3.5k bytes with zeroes, ensure we blow away old
* superblock */
static const char zeroes[BCH_SB_SECTOR << 9];
xpwrite(fd, zeroes, BCH_SB_SECTOR << 9, 0, "zeroing start of disk");
bch2_super_write(fd, sb);
close(fd);
/* mark new superblocks */
struct bch_opts opts = bch2_opts_empty();
opt_set(opts, nostart, true);
opt_set(opts, sb, sb_offset);
struct bch_fs *c = bch2_fs_open(&dev, 1, opts);
ret = PTR_ERR_OR_ZERO(c) ?:
bch2_buckets_nouse_alloc(c);
if (ret)
die("error opening filesystem: %s", bch2_err_str(ret));
struct bch_dev *ca = c->devs[0];
for (u64 b = 0; bucket_to_sector(ca, b) < BCH_SB_SECTOR + sb_size * 2; b++)
set_bit(b, ca->buckets_nouse);
ret = bch2_fs_start(c);
if (ret)
die("Error starting filesystem: %s", bch2_err_str(ret));
bch2_fs_stop(c);
opts = bch2_opts_empty();
opt_set(opts, fsck, true);
opt_set(opts, fix_errors, true);
/*
* Hack: the free space counters are coming out wrong after marking the
* new superblock, but it's just the device counters so it's
* inconsequential:
*/
c = bch2_fs_open(&dev, 1, opts);
ret = PTR_ERR_OR_ZERO(c);
if (ret)
die("error opening filesystem: %s", bch2_err_str(ret));
bch2_fs_stop(c);
return 0;
}

View File

@ -26,28 +26,54 @@
static void set_option_usage(void)
{
puts("bcachefs set-option \n"
"Usage: bcachefs set-option [OPTION].. device\n"
puts("bcachefs set-fs-option \n"
"Usage: bcachefs set-fs-option [OPTION].. device\n"
"\n"
"Options:\n");
bch2_opts_usage(OPT_MOUNT);
puts(" -h, --help display this help and exit\n"
bch2_opts_usage(OPT_MOUNT|OPT_RUNTIME);
puts(" -d, --dev-idx index for device specific options\n"
" -h, --help display this help and exit\n"
"Report bugs to <linux-bcachefs@vger.kernel.org>");
exit(EXIT_SUCCESS);
}
static int name_to_dev_idx(struct bch_fs *c, const char *dev)
{
int ret = -1;
rcu_read_lock();
for_each_member_device_rcu(c, ca, NULL)
if (!strcmp(ca->name, dev)) {
ret = ca->dev_idx;
break;
}
rcu_read_unlock();
return ret;
}
int cmd_set_option(int argc, char *argv[])
{
struct bch_opt_strs new_opt_strs = bch2_cmdline_opts_get(&argc, argv, OPT_MOUNT);
struct bch_opt_strs new_opt_strs = bch2_cmdline_opts_get(&argc, argv, OPT_MOUNT|OPT_DEVICE);
struct bch_opts new_opts = bch2_parse_opts(new_opt_strs);
struct bch_opts open_opts = bch2_opts_empty();
unsigned i;
DARRAY(unsigned) dev_idxs = {};
int opt, ret = 0;
opt_set(open_opts, nostart, true);
static const struct option longopts[] = {
{ "dev-idx", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ NULL }
};
while ((opt = getopt(argc, argv, "h")) != -1)
while ((opt = getopt_long(argc, argv, "d:h", longopts, NULL)) != -1)
switch (opt) {
case 'd': {
unsigned dev_idx;
if (kstrtoint(optarg, 10, &dev_idx))
die("error parsing %s", optarg);
darray_push(&dev_idxs, dev_idx);
break;
}
case 'h':
set_option_usage();
break;
@ -59,48 +85,117 @@ int cmd_set_option(int argc, char *argv[])
exit(EXIT_FAILURE);
}
bool online = false;
unsigned i;
for (i = 0; i < argc; i++)
if (dev_mounted(argv[i]))
goto online;
struct bch_fs *c = bch2_fs_open(argv, argc, open_opts);
if (IS_ERR(c)) {
fprintf(stderr, "error opening %s: %s\n", argv[0], bch2_err_str(PTR_ERR(c)));
exit(EXIT_FAILURE);
}
for (i = 0; i < bch2_opts_nr; i++) {
u64 v = bch2_opt_get_by_id(&new_opts, i);
if (!bch2_opt_defined_by_id(&new_opts, i))
continue;
ret = bch2_opt_check_may_set(c, i, v);
if (ret < 0) {
fprintf(stderr, "error setting %s: %i\n",
bch2_opt_table[i].attr.name, ret);
if (dev_mounted(argv[i])) {
online = true;
break;
}
bch2_opt_set_sb(c, bch2_opt_table + i, v);
bch2_opt_set_by_id(&c->opts, i, v);
}
if (!online) {
struct bch_opts open_opts = bch2_opts_empty();
opt_set(open_opts, nostart, true);
bch2_fs_stop(c);
return ret;
online:
{
struct bch_fs *c = bch2_fs_open(argv, argc, open_opts);
if (IS_ERR(c)) {
fprintf(stderr, "error opening %s: %s\n", argv[0], bch2_err_str(PTR_ERR(c)));
exit(EXIT_FAILURE);
}
for (i = 0; i < bch2_opts_nr; i++) {
const struct bch_option *opt = bch2_opt_table + i;
u64 v = bch2_opt_get_by_id(&new_opts, i);
if (!bch2_opt_defined_by_id(&new_opts, i))
continue;
if (!(opt->flags & (OPT_FS|OPT_DEVICE)))
fprintf(stderr, "Can't set option %s\n", opt->attr.name);
if (opt->flags & OPT_FS) {
ret = bch2_opt_check_may_set(c, NULL, i, v);
if (ret < 0) {
fprintf(stderr, "error setting %s: %i\n", opt->attr.name, ret);
continue;
}
bch2_opt_set_sb(c, NULL, opt, v);
}
if (opt->flags & OPT_DEVICE) {
if (dev_idxs.nr) {
darray_for_each(dev_idxs, dev) {
struct bch_dev *ca = bch2_dev_tryget_noerror(c, *dev);
if (!ca) {
fprintf(stderr, "Couldn't look up device %u\n", *dev);
continue;
}
ret = bch2_opt_check_may_set(c, ca, i, v);
if (ret < 0) {
fprintf(stderr, "error setting %s: %i\n", opt->attr.name, ret);
continue;
}
bch2_opt_set_sb(c, ca, opt, v);
bch2_dev_put(ca);
}
} else {
for (unsigned dev = 0; dev < argc; dev++) {
int dev_idx = name_to_dev_idx(c, argv[dev]);
if (dev_idx < 0) {
fprintf(stderr, "Couldn't look up device %s\n", argv[i]);
continue;
}
bch2_opt_set_sb(c, c->devs[dev_idx], opt, v);
}
}
}
}
bch2_fs_stop(c);
return ret;
} else {
unsigned dev_idx;
struct bchfs_handle fs = bchu_fs_open_by_dev(argv[i], &dev_idx);
for (i = 0; i < argc; i++) {
struct bchfs_handle fs2 = bchu_fs_open_by_dev(argv[i], &dev_idx);
if (memcmp(&fs.uuid, &fs2.uuid, sizeof(fs2.uuid)))
die("Filesystem mounted, but not all devices are members");
bcache_fs_close(fs2);
}
for (i = 0; i < bch2_opts_nr; i++) {
if (!new_opt_strs.by_id[i])
continue;
char *path = mprintf("options/%s", bch2_opt_table[i].attr.name);
const struct bch_option *opt = bch2_opt_table + i;
write_file_str(fs.sysfs_fd, path, new_opt_strs.by_id[i]);
free(path);
if (!(opt->flags & (OPT_FS|OPT_DEVICE)))
fprintf(stderr, "Can't set option %s\n", opt->attr.name);
if (opt->flags & OPT_FS) {
char *path = mprintf("options/%s", opt->attr.name);
write_file_str(fs.sysfs_fd, path, new_opt_strs.by_id[i]);
free(path);
}
if (opt->flags & OPT_DEVICE) {
for (unsigned dev = 0; dev < argc; dev++) {
struct bchfs_handle fs2 = bchu_fs_open_by_dev(argv[i], &dev_idx);
bcache_fs_close(fs2);
char *path = mprintf("dev-%u/%s", dev_idx, opt->attr.name);
write_file_str(fs.sysfs_fd, path, new_opt_strs.by_id[i]);
free(path);
}
}
}
}
return 0;

98
c_src/cmd_top.c Normal file
View File

@ -0,0 +1,98 @@
#include <dirent.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "cmds.h"
#include "libbcachefs.h"
#include "libbcachefs/sb-counters.h"
static const u8 counters_to_stable_map[] = {
#define x(n, id, ...) [BCH_COUNTER_##n] = BCH_COUNTER_STABLE_##n,
BCH_PERSISTENT_COUNTERS()
#undef x
};
static struct bch_ioctl_query_counters *read_counters(struct bchfs_handle fs)
{
struct bch_ioctl_query_counters *ret =
kzalloc(sizeof(*ret) + sizeof(ret->d[0]) * BCH_COUNTER_NR, GFP_KERNEL);
ret->nr = BCH_COUNTER_NR;
xioctl(fs.ioctl_fd, BCH_IOCTL_QUERY_COUNTERS, ret);
return ret;
}
static void fs_top(const char *path, bool human_readable)
{
struct bchfs_handle fs = bcache_fs_open(path);
struct bch_ioctl_query_counters *curr, *prev = NULL;
curr = read_counters(fs);
while (true) {
sleep(1);
kfree(prev);
prev = curr;
curr = read_counters(fs);
printf("\033[2J");
printf("\033[H");
for (unsigned i = 0; i < BCH_COUNTER_NR; i++) {
unsigned stable = counters_to_stable_map[i];
u64 v = stable < curr->nr
? curr->d[stable] - prev->d[stable]
: 0;
printf("%-48s %llu\n",
bch2_counter_names[i],
v);
}
}
bcache_fs_close(fs);
}
static void fs_top_usage(void)
{
puts("bcachefs fs top - display runtime perfomance info\n"
"Usage: bcachefs fs top [OPTION]... <mountpoint>\n"
"\n"
"Options:\n"
" -h, --human-readable Human readable units\n"
" -H, --help Display this help and exit\n"
"Report bugs to <linux-bcachefs@vger.kernel.org>");
}
int cmd_fs_top(int argc, char *argv[])
{
static const struct option longopts[] = {
{ "help", no_argument, NULL, 'H' },
{ "human-readable", no_argument, NULL, 'h' },
{ NULL }
};
bool human_readable = false;
int opt;
while ((opt = getopt_long(argc, argv, "Hh",
longopts, NULL)) != -1)
switch (opt) {
case 'h':
human_readable = true;
break;
case 'H':
fs_top_usage();
exit(EXIT_SUCCESS);
default:
fs_top_usage();
exit(EXIT_FAILURE);
}
args_shift(optind);
fs_top(arg_pop() ?: ".", human_readable) ;
return 0;
}

View File

@ -11,10 +11,13 @@
int cmd_format(int argc, char *argv[]);
int cmd_show_super(int argc, char *argv[]);
int cmd_recover_super(int argc, char *argv[]);
int cmd_reset_counters(int argc, char *argv[]);
int cmd_set_option(int argc, char *argv[]);
int fs_usage(void);
int cmd_fs_usage(int argc, char *argv[]);
int cmd_fs_top(int argc, char *argv[]);
int device_usage(void);
int cmd_device_add(int argc, char *argv[]);
@ -28,6 +31,7 @@ int cmd_device_resize_journal(int argc, char *argv[]);
int data_usage(void);
int cmd_data_rereplicate(int argc, char *argv[]);
int cmd_data_scrub(int argc, char *argv[]);
int cmd_data_job(int argc, char *argv[]);
int cmd_unlock(int argc, char *argv[]);

View File

@ -101,7 +101,7 @@ struct bch_key derive_passphrase(struct bch_sb_field_crypt *crypt,
return key;
}
bool bch2_sb_is_encrypted_and_locked(struct bch_sb *sb)
bool bch2_sb_is_encrypted(struct bch_sb *sb)
{
struct bch_sb_field_crypt *crypt;
@ -176,26 +176,47 @@ void bch_sb_crypt_init(struct bch_sb *sb,
struct bch_sb_field_crypt *crypt,
const char *passphrase)
{
struct bch_key key;
get_random_bytes(&key, sizeof(key));
crypt->key.magic = BCH_KEY_MAGIC;
get_random_bytes(&crypt->key.key, sizeof(crypt->key.key));
crypt->key.key = key;
if (passphrase) {
bch_crypt_update_passphrase(sb, crypt, &key, passphrase);
}
void bch_crypt_update_passphrase(
struct bch_sb *sb,
struct bch_sb_field_crypt *crypt,
struct bch_key *key,
const char *new_passphrase)
{
struct bch_encrypted_key new_key;
new_key.magic = BCH_KEY_MAGIC;
new_key.key = *key;
if(!new_passphrase) {
crypt->key = new_key;
return;
}
// If crypt already has an encrypted key reuse it's encryption params
if (!bch2_key_is_encrypted(&crypt->key)) {
SET_BCH_CRYPT_KDF_TYPE(crypt, BCH_KDF_SCRYPT);
SET_BCH_KDF_SCRYPT_N(crypt, ilog2(16384));
SET_BCH_KDF_SCRYPT_R(crypt, ilog2(8));
SET_BCH_KDF_SCRYPT_P(crypt, ilog2(16));
struct bch_key passphrase_key = derive_passphrase(crypt, passphrase);
assert(!bch2_key_is_encrypted(&crypt->key));
if (bch2_chacha_encrypt_key(&passphrase_key, __bch2_sb_key_nonce(sb),
&crypt->key, sizeof(crypt->key)))
die("error encrypting key");
assert(bch2_key_is_encrypted(&crypt->key));
memzero_explicit(&passphrase_key, sizeof(passphrase_key));
}
struct bch_key passphrase_key = derive_passphrase(crypt, new_passphrase);
if (bch2_chacha_encrypt_key(&passphrase_key, __bch2_sb_key_nonce(sb),
&new_key, sizeof(new_key)))
die("error encrypting key");
memzero_explicit(&passphrase_key, sizeof(passphrase_key));
crypt->key = new_key;
assert(bch2_key_is_encrypted(&crypt->key));
}

View File

@ -12,11 +12,14 @@ char *read_passphrase(const char *);
char *read_passphrase_twice(const char *);
struct bch_key derive_passphrase(struct bch_sb_field_crypt *, const char *);
bool bch2_sb_is_encrypted_and_locked(struct bch_sb *);
bool bch2_sb_is_encrypted(struct bch_sb *);
void bch2_passphrase_check(struct bch_sb *, const char *,
struct bch_key *, struct bch_encrypted_key *);
void bch2_add_key(struct bch_sb *, const char *, const char *, const char *);
void bch_sb_crypt_init(struct bch_sb *sb, struct bch_sb_field_crypt *,
const char *);
void bch_crypt_update_passphrase(struct bch_sb *sb, struct bch_sb_field_crypt *crypt,
struct bch_key *key, const char *new_passphrase);
#endif /* _CRYPTO_H */

View File

@ -16,6 +16,8 @@
#include <uuid/uuid.h>
#include <linux/mm.h>
#include "libbcachefs.h"
#include "crypto.h"
#include "libbcachefs/bcachefs_format.h"
@ -31,10 +33,10 @@
#define NSEC_PER_SEC 1000000000L
static void init_layout(struct bch_sb_layout *l,
unsigned block_size,
unsigned sb_size,
u64 sb_start, u64 sb_end)
void bch2_sb_layout_init(struct bch_sb_layout *l,
unsigned block_size,
unsigned sb_size,
u64 sb_start, u64 sb_end)
{
u64 sb_pos = sb_start;
unsigned i;
@ -60,83 +62,86 @@ static void init_layout(struct bch_sb_layout *l,
sb_start, sb_pos, sb_end, sb_size);
}
/* minimum size filesystem we can create, given a bucket size: */
static u64 min_size(unsigned bucket_size)
static u64 dev_max_bucket_size(u64 dev_size)
{
return BCH_MIN_NR_NBUCKETS * bucket_size;
return rounddown_pow_of_two(dev_size / (BCH_MIN_NR_NBUCKETS * 4));
}
u64 bch2_pick_bucket_size(struct bch_opts opts, struct dev_opts *dev)
u64 bch2_pick_bucket_size(struct bch_opts opts, dev_opts_list devs)
{
u64 bucket_size;
if (dev->size < min_size(opts.block_size))
die("cannot format %s, too small (%llu bytes, min %llu)",
dev->path, dev->size, min_size(opts.block_size));
/* Bucket size must be >= block size: */
bucket_size = opts.block_size;
u64 bucket_size = opts.block_size;
/* Bucket size must be >= btree node size: */
if (opt_defined(opts, btree_node_size))
bucket_size = max_t(unsigned, bucket_size,
opts.btree_node_size);
bucket_size = max_t(u64, bucket_size, opts.btree_node_size);
/* Want a bucket size of at least 128k, if possible: */
bucket_size = max(bucket_size, 128ULL << 10);
u64 min_dev_size = BCH_MIN_NR_NBUCKETS * bucket_size;
darray_for_each(devs, i)
if (i->fs_size < min_dev_size)
die("cannot format %s, too small (%llu bytes, min %llu)",
i->path, i->fs_size, min_dev_size);
if (dev->size >= min_size(bucket_size)) {
unsigned scale = max(1,
ilog2(dev->size / min_size(bucket_size)) / 4);
u64 total_fs_size = 0;
darray_for_each(devs, i)
total_fs_size += i->fs_size;
scale = rounddown_pow_of_two(scale);
struct sysinfo info;
si_meminfo(&info);
/* max bucket size 1 mb */
bucket_size = min(bucket_size * scale, 1ULL << 20);
} else {
do {
bucket_size /= 2;
} while (dev->size < min_size(bucket_size));
}
/*
* Large fudge factor to allow for other fsck processes and devices
* being added after creation
*/
u64 mem_available_for_fsck = info.totalram / 8;
u64 buckets_can_fsck = mem_available_for_fsck / (sizeof(struct bucket) * 1.5);
u64 mem_lower_bound = roundup_pow_of_two(total_fs_size / buckets_can_fsck);
/*
* Lower bound to avoid fragmenting encoded (checksummed, compressed)
* extents too much as they're moved:
*/
bucket_size = max(bucket_size, opt_get(opts, encoded_extent_max) * 4);
/* Lower bound to ensure we can fsck: */
bucket_size = max(bucket_size, mem_lower_bound);
u64 perf_lower_bound = min(2ULL << 20, total_fs_size / (1ULL << 20));
/* We also prefer larger buckets for performance, up to 2MB at 2T */
bucket_size = max(bucket_size, perf_lower_bound);
return bucket_size;
}
void bch2_check_bucket_size(struct bch_opts opts, struct dev_opts *dev)
{
if (dev->bucket_size < opts.block_size)
die("Bucket size (%llu) cannot be smaller than block size (%u)",
dev->bucket_size, opts.block_size);
if (dev->opts.bucket_size < opts.block_size)
die("Bucket size (%u) cannot be smaller than block size (%u)",
dev->opts.bucket_size, opts.block_size);
if (opt_defined(opts, btree_node_size) &&
dev->bucket_size < opts.btree_node_size)
die("Bucket size (%llu) cannot be smaller than btree node size (%u)",
dev->bucket_size, opts.btree_node_size);
dev->opts.bucket_size < opts.btree_node_size)
die("Bucket size (%u) cannot be smaller than btree node size (%u)",
dev->opts.bucket_size, opts.btree_node_size);
if (dev->nbuckets < BCH_MIN_NR_NBUCKETS)
die("Not enough buckets: %llu, need %u (bucket size %llu)",
dev->nbuckets, BCH_MIN_NR_NBUCKETS, dev->bucket_size);
if (dev->bucket_size > (u32) U16_MAX << 9)
die("Bucket size (%llu) too big (max %u)",
dev->bucket_size, (u32) U16_MAX << 9);
die("Not enough buckets: %llu, need %u (bucket size %u)",
dev->nbuckets, BCH_MIN_NR_NBUCKETS, dev->opts.bucket_size);
}
static unsigned parse_target(struct bch_sb_handle *sb,
struct dev_opts *devs, size_t nr_devs,
dev_opts_list devs,
const char *s)
{
struct dev_opts *i;
int idx;
if (!s)
return 0;
for (i = devs; i < devs + nr_devs; i++)
darray_for_each(devs, i)
if (!strcmp(s, i->path))
return dev_to_target(i - devs);
return dev_to_target(i - devs.data);
idx = bch2_disk_path_find(sb, s);
int idx = bch2_disk_path_find(sb, s);
if (idx >= 0)
return group_to_target(idx);
@ -144,56 +149,61 @@ static unsigned parse_target(struct bch_sb_handle *sb,
return 0;
}
static void bch2_opt_set_sb_all(struct bch_sb *sb, int dev_idx, struct bch_opts *opts)
{
for (unsigned id = 0; id < bch2_opts_nr; id++) {
u64 v = bch2_opt_defined_by_id(opts, id)
? bch2_opt_get_by_id(opts, id)
: bch2_opt_get_by_id(&bch2_opts_default, id);
__bch2_opt_set_sb(sb, dev_idx, &bch2_opt_table[id], v);
}
}
struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
struct bch_opts fs_opts,
struct format_opts opts,
struct dev_opts *devs,
size_t nr_devs)
dev_opts_list devs)
{
struct bch_sb_handle sb = { NULL };
struct dev_opts *i;
unsigned max_dev_block_size = 0;
unsigned opt_id;
u64 min_bucket_size = U64_MAX;
for (i = devs; i < devs + nr_devs; i++)
darray_for_each(devs, i)
max_dev_block_size = max(max_dev_block_size, get_blocksize(i->bdev->bd_fd));
/* calculate block size: */
if (!opt_defined(fs_opts, block_size)) {
if (!opt_defined(fs_opts, block_size))
opt_set(fs_opts, block_size, max_dev_block_size);
} else if (fs_opts.block_size < max_dev_block_size)
if (fs_opts.block_size < max_dev_block_size)
die("blocksize too small: %u, must be greater than device blocksize %u",
fs_opts.block_size, max_dev_block_size);
/* get device size, if it wasn't specified: */
for (i = devs; i < devs + nr_devs; i++)
if (!i->size)
i->size = get_size(i->bdev->bd_fd);
darray_for_each(devs, i)
if (!i->fs_size)
i->fs_size = get_size(i->bdev->bd_fd);
/* calculate bucket sizes: */
for (i = devs; i < devs + nr_devs; i++)
min_bucket_size = min(min_bucket_size,
i->bucket_size ?: bch2_pick_bucket_size(fs_opts, i));
u64 fs_bucket_size = bch2_pick_bucket_size(fs_opts, devs);
for (i = devs; i < devs + nr_devs; i++)
if (!i->bucket_size)
i->bucket_size = min_bucket_size;
darray_for_each(devs, i)
if (!opt_defined(i->opts, bucket_size))
opt_set(i->opts, bucket_size,
min(fs_bucket_size, dev_max_bucket_size(i->fs_size)));
for (i = devs; i < devs + nr_devs; i++) {
i->nbuckets = i->size / i->bucket_size;
darray_for_each(devs, i) {
i->nbuckets = i->fs_size / i->opts.bucket_size;
bch2_check_bucket_size(fs_opts, i);
}
/* calculate btree node size: */
if (!opt_defined(fs_opts, btree_node_size)) {
/* 256k default btree node size */
opt_set(fs_opts, btree_node_size, 256 << 10);
unsigned s = bch2_opts_default.btree_node_size;
for (i = devs; i < devs + nr_devs; i++)
fs_opts.btree_node_size =
min_t(unsigned, fs_opts.btree_node_size,
i->bucket_size);
darray_for_each(devs, i)
s = min(s, i->opts.bucket_size);
opt_set(fs_opts, btree_node_size, s);
}
if (uuid_is_null(opts.uuid.b))
@ -206,7 +216,8 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
sb.sb->version_min = le16_to_cpu(opts.version);
sb.sb->magic = BCHFS_MAGIC;
sb.sb->user_uuid = opts.uuid;
sb.sb->nr_devices = nr_devs;
sb.sb->nr_devices = devs.nr;
SET_BCH_SB_VERSION_INCOMPAT_ALLOWED(sb.sb, opts.version);
if (opts.version == bcachefs_metadata_version_current)
sb.sb->features[0] |= cpu_to_le64(BCH_SB_FEATURES_ALL);
@ -218,17 +229,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
opts.label,
min(strlen(opts.label), sizeof(sb.sb->label)));
for (opt_id = 0;
opt_id < bch2_opts_nr;
opt_id++) {
u64 v;
v = bch2_opt_defined_by_id(&fs_opts, opt_id)
? bch2_opt_get_by_id(&fs_opts, opt_id)
: bch2_opt_get_by_id(&bch2_opts_default, opt_id);
__bch2_opt_set_sb(sb.sb, &bch2_opt_table[opt_id], v);
}
bch2_opt_set_sb_all(sb.sb, -1, &fs_opts);
struct timespec now;
if (clock_gettime(CLOCK_REALTIME, &now))
@ -240,31 +241,25 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
/* Member info: */
struct bch_sb_field_members_v2 *mi =
bch2_sb_field_resize(&sb, members_v2,
(sizeof(*mi) + sizeof(struct bch_member) *
nr_devs) / sizeof(u64));
(sizeof(*mi) + sizeof(struct bch_member) * devs.nr) / sizeof(u64));
mi->member_bytes = cpu_to_le16(sizeof(struct bch_member));
for (i = devs; i < devs + nr_devs; i++) {
struct bch_member *m = bch2_members_v2_get_mut(sb.sb, (i - devs));
darray_for_each(devs, i) {
unsigned idx = i - devs.data;
struct bch_member *m = bch2_members_v2_get_mut(sb.sb, idx);
uuid_generate(m->uuid.b);
m->nbuckets = cpu_to_le64(i->nbuckets);
m->first_bucket = 0;
m->bucket_size = cpu_to_le16(i->bucket_size >> 9);
SET_BCH_MEMBER_DISCARD(m, i->discard);
SET_BCH_MEMBER_DATA_ALLOWED(m, i->data_allowed);
SET_BCH_MEMBER_DURABILITY(m, i->durability + 1);
bch2_opt_set_sb_all(sb.sb, idx, &i->opts);
}
/* Disk labels*/
for (i = devs; i < devs + nr_devs; i++) {
struct bch_member *m;
int idx;
darray_for_each(devs, i) {
if (!i->label)
continue;
idx = bch2_disk_path_find_or_create(&sb, i->label);
int idx = bch2_disk_path_find_or_create(&sb, i->label);
if (idx < 0)
die("error creating disk path: %s", strerror(-idx));
@ -272,18 +267,18 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
* Recompute mi and m after each sb modification: its location
* in memory may have changed due to reallocation.
*/
m = bch2_members_v2_get_mut(sb.sb, (i - devs));
struct bch_member *m = bch2_members_v2_get_mut(sb.sb, (i - devs.data));
SET_BCH_MEMBER_GROUP(m, idx + 1);
}
SET_BCH_SB_FOREGROUND_TARGET(sb.sb,
parse_target(&sb, devs, nr_devs, fs_opt_strs.foreground_target));
parse_target(&sb, devs, fs_opt_strs.foreground_target));
SET_BCH_SB_BACKGROUND_TARGET(sb.sb,
parse_target(&sb, devs, nr_devs, fs_opt_strs.background_target));
parse_target(&sb, devs, fs_opt_strs.background_target));
SET_BCH_SB_PROMOTE_TARGET(sb.sb,
parse_target(&sb, devs, nr_devs, fs_opt_strs.promote_target));
parse_target(&sb, devs, fs_opt_strs.promote_target));
SET_BCH_SB_METADATA_TARGET(sb.sb,
parse_target(&sb, devs, nr_devs, fs_opt_strs.metadata_target));
parse_target(&sb, devs, fs_opt_strs.metadata_target));
/* Crypt: */
if (opts.encrypted) {
@ -296,19 +291,19 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
bch2_sb_members_cpy_v2_v1(&sb);
for (i = devs; i < devs + nr_devs; i++) {
u64 size_sectors = i->size >> 9;
darray_for_each(devs, i) {
u64 size_sectors = i->fs_size >> 9;
sb.sb->dev_idx = i - devs;
sb.sb->dev_idx = i - devs.data;
if (!i->sb_offset) {
i->sb_offset = BCH_SB_SECTOR;
i->sb_end = size_sectors;
}
init_layout(&sb.sb->layout, fs_opts.block_size,
opts.superblock_size,
i->sb_offset, i->sb_end);
bch2_sb_layout_init(&sb.sb->layout, fs_opts.block_size,
opts.superblock_size,
i->sb_offset, i->sb_end);
/*
* Also create a backup superblock at the end of the disk:
@ -321,7 +316,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
struct bch_sb_layout *l = &sb.sb->layout;
u64 backup_sb = size_sectors - (1 << l->sb_max_size_bits);
backup_sb = rounddown(backup_sb, i->bucket_size >> 9);
backup_sb = rounddown(backup_sb, i->opts.bucket_size >> 9);
l->sb_offset[l->nr_superblocks++] = cpu_to_le64(backup_sb);
}
@ -352,9 +347,9 @@ void bch2_super_write(int fd, struct bch_sb *sb)
if (sb->offset == BCH_SB_SECTOR) {
/* Write backup layout */
BUG_ON(bs > 4096);
unsigned buflen = max(bs, 4096);
char *buf = aligned_alloc(bs, bs);
char *buf = aligned_alloc(buflen, buflen);
xpread(fd, buf, bs, 4096 - bs);
memcpy(buf + bs - sizeof(sb->layout),
&sb->layout,
@ -411,43 +406,107 @@ void bcache_fs_close(struct bchfs_handle fs)
close(fs.sysfs_fd);
}
struct bchfs_handle bcache_fs_open(const char *path)
static int bcache_fs_open_by_uuid(const char *uuid_str, struct bchfs_handle *fs)
{
struct bchfs_handle ret;
if (uuid_parse(uuid_str, fs->uuid.b))
return -1;
if (!uuid_parse(path, ret.uuid.b)) {
/* It's a UUID, look it up in sysfs: */
char *sysfs = mprintf(SYSFS_BASE "%s", path);
ret.sysfs_fd = xopen(sysfs, O_RDONLY);
char *sysfs = mprintf(SYSFS_BASE "%s", uuid_str);
fs->sysfs_fd = open(sysfs, O_RDONLY);
free(sysfs);
char *minor = read_file_str(ret.sysfs_fd, "minor");
char *ctl = mprintf("/dev/bcachefs%s-ctl", minor);
ret.ioctl_fd = xopen(ctl, O_RDWR);
if (fs->sysfs_fd < 0)
return -errno;
free(sysfs);
free(minor);
free(ctl);
} else {
/* It's a path: */
ret.ioctl_fd = open(path, O_RDONLY);
if (ret.ioctl_fd < 0)
die("Error opening filesystem at %s: %m", path);
char *minor = read_file_str(fs->sysfs_fd, "minor");
char *ctl = mprintf("/dev/bcachefs%s-ctl", minor);
fs->ioctl_fd = open(ctl, O_RDWR);
free(minor);
free(ctl);
struct bch_ioctl_query_uuid uuid;
if (ioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid) < 0)
die("error opening %s: not a bcachefs filesystem", path);
return fs->ioctl_fd < 0 ? -errno : 0;
}
ret.uuid = uuid.uuid;
int bcache_fs_open_fallible(const char *path, struct bchfs_handle *fs)
{
memset(fs, 0, sizeof(*fs));
fs->dev_idx = -1;
if (!uuid_parse(path, fs->uuid.b))
return bcache_fs_open_by_uuid(path, fs);
/* It's a path: */
int path_fd = open(path, O_RDONLY);
if (path_fd < 0)
return -errno;
struct bch_ioctl_query_uuid uuid;
if (!ioctl(path_fd, BCH_IOCTL_QUERY_UUID, &uuid)) {
/* It's a path to the mounted filesystem: */
fs->ioctl_fd = path_fd;
fs->uuid = uuid.uuid;
char uuid_str[40];
uuid_unparse(uuid.uuid.b, uuid_str);
char *sysfs = mprintf(SYSFS_BASE "%s", uuid_str);
ret.sysfs_fd = xopen(sysfs, O_RDONLY);
fs->sysfs_fd = xopen(sysfs, O_RDONLY);
free(sysfs);
return 0;
}
return ret;
struct bch_opts opts = bch2_opts_empty();
char buf[1024], *uuid_str;
struct stat stat = xstat(path);
close(path_fd);
if (S_ISBLK(stat.st_mode)) {
char *sysfs = mprintf("/sys/dev/block/%u:%u/bcachefs",
major(stat.st_rdev),
minor(stat.st_rdev));
ssize_t len = readlink(sysfs, buf, sizeof(buf));
free(sysfs);
if (len <= 0)
goto read_super;
char *p = strrchr(buf, '/');
if (!p || sscanf(p + 1, "dev-%u", &fs->dev_idx) != 1)
die("error parsing sysfs");
*p = '\0';
p = strrchr(buf, '/');
uuid_str = p + 1;
} else {
read_super:
opt_set(opts, noexcl, true);
opt_set(opts, nochanges, true);
struct bch_sb_handle sb;
int ret = bch2_read_super(path, &opts, &sb);
if (ret)
die("Error opening %s: %s", path, strerror(-ret));
fs->dev_idx = sb.sb->dev_idx;
uuid_str = buf;
uuid_unparse(sb.sb->user_uuid.b, uuid_str);
bch2_free_super(&sb);
}
return bcache_fs_open_by_uuid(uuid_str, fs);
}
struct bchfs_handle bcache_fs_open(const char *path)
{
struct bchfs_handle fs;
int ret = bcache_fs_open_fallible(path, &fs);
if (ret)
die("Error opening filesystem at %s: %s", path, strerror(-ret));
return fs;
}
/*
@ -523,7 +582,7 @@ int bchu_data(struct bchfs_handle fs, struct bch_ioctl_data cmd)
if (e.type)
continue;
if (e.p.data_type == U8_MAX)
if (e.ret || e.p.data_type == U8_MAX)
break;
printf("\33[2K\r");
@ -554,6 +613,8 @@ int bchu_data(struct bchfs_handle fs, struct bch_ioctl_data cmd)
/* option parsing */
#include <getopt.h>
void bch2_opt_strs_free(struct bch_opt_strs *opts)
{
unsigned i;
@ -564,6 +625,64 @@ void bch2_opt_strs_free(struct bch_opt_strs *opts)
}
}
static bool opt_type_filter(const struct bch_option *opt, unsigned opt_types)
{
if (!(opt->flags & opt_types))
return false;
if ((opt_types & OPT_FORMAT) &&
!opt->set_sb && !opt->set_member)
return false;
return true;
}
const struct bch_option *bch2_cmdline_opt_parse(int argc, char *argv[],
unsigned opt_types)
{
if (optind >= argc)
return NULL;
if (argv[optind][0] != '-' ||
argv[optind][1] != '-')
return NULL;
char *optstr = strdup(argv[optind] + 2);
optarg = argv[optind + 1];
char *eq = strchr(optstr, '=');
if (eq) {
*eq = '\0';
optarg = eq + 1;
}
if (!optarg)
optarg = "1";
int optid = bch2_opt_lookup(optstr);
if (optid < 0)
goto noopt;
const struct bch_option *opt = bch2_opt_table + optid;
if (!opt_type_filter(opt, opt_types))
goto noopt;
optind++;
if (opt->type != BCH_OPT_BOOL) {
if (optarg == argv[optind])
optind++;
} else {
optarg = NULL;
}
return opt;
noopt:
free(optstr);
return NULL;
}
struct bch_opt_strs bch2_cmdline_opts_get(int *argc, char *argv[],
unsigned opt_types)
{
@ -638,7 +757,7 @@ struct bch_opts bch2_parse_opts(struct bch_opt_strs strs)
ret = bch2_opt_parse(NULL,
&bch2_opt_table[i],
strs.by_id[i], &v, &err);
if (ret < 0)
if (ret < 0 && ret != -BCH_ERR_option_needs_open_fs)
die("Invalid option %s", err.buf);
bch2_opt_set_by_id(&opts, i, v);
@ -651,19 +770,17 @@ struct bch_opts bch2_parse_opts(struct bch_opt_strs strs)
#define newline(c) \
do { \
printf("\n"); \
c = 0; \
c = 0; \
} while(0)
void bch2_opts_usage(unsigned opt_types)
{
const struct bch_option *opt;
unsigned i, c = 0, helpcol = 30;
for (opt = bch2_opt_table;
opt < bch2_opt_table + bch2_opts_nr;
opt++) {
if (!(opt->flags & opt_types))
if (!opt_type_filter(opt, opt_types))
continue;
c += printf(" --%s", opt->attr.name);
@ -733,6 +850,8 @@ dev_names bchu_fs_get_devices(struct bchfs_handle fs)
if (r > 0) {
sysfs_block_buf[r] = '\0';
n.dev = strdup(basename(sysfs_block_buf));
} else {
n.dev = mprintf("(offline dev %u)", n.idx);
}
free(block_attr);
@ -752,3 +871,11 @@ dev_names bchu_fs_get_devices(struct bchfs_handle fs)
return devs;
}
struct dev_name *dev_idx_to_name(dev_names *dev_names, unsigned idx)
{
darray_for_each(*dev_names, dev)
if (dev->idx == idx)
return dev;
return NULL;
}

View File

@ -4,8 +4,10 @@
#include <linux/uuid.h>
#include <stdbool.h>
#include "libbcachefs/bcachefs.h"
#include "libbcachefs/bcachefs_format.h"
#include "libbcachefs/bcachefs_ioctl.h"
#include "libbcachefs/inode.h"
#include "libbcachefs/opts.h"
#include "libbcachefs/vstructs.h"
#include "tools-util.h"
@ -26,6 +28,9 @@ struct {
};
void bch2_opt_strs_free(struct bch_opt_strs *);
const struct bch_option *bch2_cmdline_opt_parse(int argc, char *argv[],
unsigned opt_types);
struct bch_opt_strs bch2_cmdline_opts_get(int *, char *[], unsigned);
struct bch_opts bch2_parse_opts(struct bch_opt_strs);
void bch2_opts_usage(unsigned);
@ -37,16 +42,21 @@ struct format_opts {
unsigned superblock_size;
bool encrypted;
char *passphrase;
char *source;
};
static inline unsigned bcachefs_kernel_version(void)
{
return !access("/sys/module/bcachefs/parameters/version", R_OK)
? read_file_u64(AT_FDCWD, "/sys/module/bcachefs/parameters/version")
: 0;
}
static inline struct format_opts format_opts_default()
{
unsigned version = !access( "/sys/module/bcachefs/parameters/version", R_OK)
? read_file_u64(AT_FDCWD, "/sys/module/bcachefs/parameters/version")
: bcachefs_metadata_version_current;
return (struct format_opts) {
.version = version,
.version = bcachefs_kernel_version() ?:
bcachefs_metadata_version_current,
.superblock_size = SUPERBLOCK_SIZE_DEFAULT,
};
}
@ -55,33 +65,35 @@ struct dev_opts {
struct file *file;
struct block_device *bdev;
char *path;
u64 size; /* bytes*/
u64 bucket_size; /* bytes */
const char *label;
unsigned data_allowed;
unsigned durability;
bool discard;
u64 nbuckets;
u64 sb_offset;
u64 sb_end;
u64 nbuckets;
u64 fs_size;
const char *label; /* make this a bch_opt */
struct bch_opts opts;
};
typedef DARRAY(struct dev_opts) dev_opts_list;
static inline struct dev_opts dev_opts_default()
{
return (struct dev_opts) {
.data_allowed = ~0U << 2,
.durability = 1,
};
return (struct dev_opts) { .opts = bch2_opts_empty() };
}
u64 bch2_pick_bucket_size(struct bch_opts, struct dev_opts *);
void bch2_sb_layout_init(struct bch_sb_layout *,
unsigned, unsigned, u64, u64);
u64 bch2_pick_bucket_size(struct bch_opts, dev_opts_list);
void bch2_check_bucket_size(struct bch_opts, struct dev_opts *);
struct bch_sb *bch2_format(struct bch_opt_strs,
struct bch_opts,
struct format_opts, struct dev_opts *, size_t);
struct format_opts,
dev_opts_list devs);
void bch2_super_write(int, struct bch_sb *);
struct bch_sb *__bch2_super_read(int, u64);
@ -94,11 +106,16 @@ struct bchfs_handle {
__uuid_t uuid;
int ioctl_fd;
int sysfs_fd;
int dev_idx;
};
void bcache_fs_close(struct bchfs_handle);
int bcache_fs_open_fallible(const char *, struct bchfs_handle *);
struct bchfs_handle bcache_fs_open(const char *);
struct bchfs_handle bchu_fs_open_by_dev(const char *, int *);
int bchu_dev_path_to_idx(struct bchfs_handle, const char *);
static inline void bchu_disk_add(struct bchfs_handle fs, char *dev)
@ -168,6 +185,35 @@ static inline struct bch_ioctl_fs_usage *bchu_fs_usage(struct bchfs_handle fs)
}
}
static inline struct bch_ioctl_query_accounting *bchu_fs_accounting(struct bchfs_handle fs,
unsigned typemask)
{
unsigned accounting_u64s = 128;
struct bch_ioctl_query_accounting *ret = NULL;
while (1) {
ret = xrealloc(ret, sizeof(*ret) + accounting_u64s * sizeof(u64));
memset(ret, 0, sizeof(*ret));
ret->accounting_u64s = accounting_u64s;
ret->accounting_types_mask = typemask;
if (!ioctl(fs.ioctl_fd, BCH_IOCTL_QUERY_ACCOUNTING, ret))
return ret;
if (errno == ENOTTY)
return NULL;
if (errno == ERANGE) {
accounting_u64s *= 2;
continue;
}
die("BCH_IOCTL_USAGE error: %m");
}
}
static inline struct bch_ioctl_dev_usage_v2 *bchu_dev_usage(struct bchfs_handle fs,
unsigned idx)
{
@ -264,5 +310,6 @@ struct dev_name {
typedef DARRAY(struct dev_name) dev_names;
dev_names bchu_fs_get_devices(struct bchfs_handle);
struct dev_name *dev_idx_to_name(dev_names *dev_names, unsigned idx);
#endif /* _LIBBCACHE_H */

468
c_src/posix_to_bcachefs.c Normal file
View File

@ -0,0 +1,468 @@
#include <dirent.h>
#include <sys/xattr.h>
#include <linux/dcache.h>
#include <linux/xattr.h>
#include "posix_to_bcachefs.h"
#include "libbcachefs/alloc_foreground.h"
#include "libbcachefs/buckets.h"
#include "libbcachefs/io_write.h"
#include "libbcachefs/namei.h"
#include "libbcachefs/str_hash.h"
#include "libbcachefs/xattr.h"
void update_inode(struct bch_fs *c,
struct bch_inode_unpacked *inode)
{
struct bkey_inode_buf packed;
int ret;
bch2_inode_pack(&packed, inode);
packed.inode.k.p.snapshot = U32_MAX;
ret = bch2_btree_insert(c, BTREE_ID_inodes, &packed.inode.k_i,
NULL, 0, BTREE_ITER_cached);
if (ret)
die("error updating inode: %s", bch2_err_str(ret));
}
void create_link(struct bch_fs *c,
struct bch_inode_unpacked *parent,
const char *name, u64 inum, mode_t mode)
{
struct qstr qstr = QSTR(name);
struct bch_inode_unpacked parent_u;
struct bch_inode_unpacked inode;
int ret = bch2_trans_commit_do(c, NULL, NULL, 0,
bch2_link_trans(trans,
(subvol_inum) { 1, parent->bi_inum }, &parent_u,
(subvol_inum) { 1, inum }, &inode, &qstr));
if (ret)
die("error creating hardlink: %s", bch2_err_str(ret));
}
struct bch_inode_unpacked create_file(struct bch_fs *c,
struct bch_inode_unpacked *parent,
const char *name,
uid_t uid, gid_t gid,
mode_t mode, dev_t rdev)
{
struct qstr qstr = QSTR(name);
struct bch_inode_unpacked new_inode;
bch2_inode_init_early(c, &new_inode);
int ret = bch2_trans_commit_do(c, NULL, NULL, 0,
bch2_create_trans(trans,
(subvol_inum) { 1, parent->bi_inum }, parent,
&new_inode, &qstr,
uid, gid, mode, rdev, NULL, NULL,
(subvol_inum) {}, 0));
if (ret)
die("error creating %s: %s", name, bch2_err_str(ret));
return new_inode;
}
#define for_each_xattr_handler(handlers, handler) \
if (handlers) \
for ((handler) = *(handlers)++; \
(handler) != NULL; \
(handler) = *(handlers)++)
static const struct xattr_handler *xattr_resolve_name(char **name)
{
const struct xattr_handler * const *handlers = bch2_xattr_handlers;
const struct xattr_handler *handler;
for_each_xattr_handler(handlers, handler) {
char *n;
n = strcmp_prefix(*name, xattr_prefix(handler));
if (n) {
if (!handler->prefix ^ !*n) {
if (*n)
continue;
return ERR_PTR(-EINVAL);
}
*name = n;
return handler;
}
}
return ERR_PTR(-EOPNOTSUPP);
}
void copy_times(struct bch_fs *c, struct bch_inode_unpacked *dst,
struct stat *src)
{
dst->bi_atime = timespec_to_bch2_time(c, src->st_atim);
dst->bi_mtime = timespec_to_bch2_time(c, src->st_mtim);
dst->bi_ctime = timespec_to_bch2_time(c, src->st_ctim);
}
void copy_xattrs(struct bch_fs *c, struct bch_inode_unpacked *dst,
char *src)
{
struct bch_hash_info hash_info = bch2_hash_info_init(c, dst);
char attrs[XATTR_LIST_MAX];
ssize_t attrs_size = llistxattr(src, attrs, sizeof(attrs));
if (attrs_size < 0)
die("listxattr error: %m");
char *next, *attr;
for (attr = attrs;
attr < attrs + attrs_size;
attr = next) {
next = attr + strlen(attr) + 1;
char val[XATTR_SIZE_MAX];
ssize_t val_size = lgetxattr(src, attr, val, sizeof(val));
if (val_size < 0)
die("error getting xattr val: %m");
const struct xattr_handler *h = xattr_resolve_name(&attr);
if (IS_ERR(h))
continue;
int ret = bch2_trans_commit_do(c, NULL, NULL, 0,
bch2_xattr_set(trans,
(subvol_inum) { 1, dst->bi_inum },
dst, &hash_info, attr,
val, val_size, h->flags, 0));
if (ret < 0)
die("error creating xattr: %s", bch2_err_str(ret));
}
}
#define WRITE_DATA_BUF (1 << 20)
static char buf[WRITE_DATA_BUF] __aligned(PAGE_SIZE);
static void write_data(struct bch_fs *c,
struct bch_inode_unpacked *dst_inode,
u64 dst_offset, void *buf, size_t len)
{
struct bch_write_op op;
struct bio_vec bv[WRITE_DATA_BUF / PAGE_SIZE];
BUG_ON(dst_offset & (block_bytes(c) - 1));
BUG_ON(len & (block_bytes(c) - 1));
BUG_ON(len > WRITE_DATA_BUF);
bio_init(&op.wbio.bio, NULL, bv, ARRAY_SIZE(bv), 0);
bch2_bio_map(&op.wbio.bio, buf, len);
bch2_write_op_init(&op, c, bch2_opts_to_inode_opts(c->opts));
op.write_point = writepoint_hashed(0);
op.nr_replicas = 1;
op.subvol = 1;
op.pos = SPOS(dst_inode->bi_inum, dst_offset >> 9, U32_MAX);
op.flags |= BCH_WRITE_sync;
int ret = bch2_disk_reservation_get(c, &op.res, len >> 9,
c->opts.data_replicas, 0);
if (ret)
die("error reserving space in new filesystem: %s", bch2_err_str(ret));
closure_call(&op.cl, bch2_write, NULL, NULL);
BUG_ON(!(op.flags & BCH_WRITE_submitted));
dst_inode->bi_sectors += len >> 9;
if (op.error)
die("write error: %s", bch2_err_str(op.error));
}
void copy_data(struct bch_fs *c,
struct bch_inode_unpacked *dst_inode,
int src_fd, u64 start, u64 end)
{
while (start < end) {
unsigned len = min_t(u64, end - start, sizeof(buf));
unsigned pad = round_up(len, block_bytes(c)) - len;
xpread(src_fd, buf, len, start);
memset(buf + len, 0, pad);
write_data(c, dst_inode, start, buf, len + pad);
start += len;
}
}
static void link_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
u64 logical, u64 physical, u64 length)
{
struct bch_dev *ca = c->devs[0];
BUG_ON(logical & (block_bytes(c) - 1));
BUG_ON(physical & (block_bytes(c) - 1));
BUG_ON(length & (block_bytes(c) - 1));
logical >>= 9;
physical >>= 9;
length >>= 9;
BUG_ON(physical + length > bucket_to_sector(ca, ca->mi.nbuckets));
while (length) {
struct bkey_i_extent *e;
BKEY_PADDED_ONSTACK(k, BKEY_EXTENT_VAL_U64s_MAX) k;
u64 b = sector_to_bucket(ca, physical);
struct disk_reservation res;
unsigned sectors;
int ret;
sectors = min(ca->mi.bucket_size -
(physical & (ca->mi.bucket_size - 1)),
length);
e = bkey_extent_init(&k.k);
e->k.p.inode = dst->bi_inum;
e->k.p.offset = logical + sectors;
e->k.p.snapshot = U32_MAX;
e->k.size = sectors;
bch2_bkey_append_ptr(&e->k_i, (struct bch_extent_ptr) {
.offset = physical,
.dev = 0,
.gen = *bucket_gen(ca, b),
});
ret = bch2_disk_reservation_get(c, &res, sectors, 1,
BCH_DISK_RESERVATION_NOFAIL);
if (ret)
die("error reserving space in new filesystem: %s",
bch2_err_str(ret));
ret = bch2_btree_insert(c, BTREE_ID_extents, &e->k_i, &res, 0, 0);
if (ret)
die("btree insert error %s", bch2_err_str(ret));
bch2_disk_reservation_put(c, &res);
dst->bi_sectors += sectors;
logical += sectors;
physical += sectors;
length -= sectors;
}
}
void copy_link(struct bch_fs *c, struct bch_inode_unpacked *dst,
char *src)
{
ssize_t i;
ssize_t ret = readlink(src, buf, sizeof(buf));
if (ret < 0)
die("readlink error: %m");
for (i = ret; i < round_up(ret, block_bytes(c)); i++)
buf[i] = 0;
write_data(c, dst, 0, buf, round_up(ret, block_bytes(c)));
}
static void copy_file(struct bch_fs *c, struct bch_inode_unpacked *dst,
int src_fd, u64 src_size,
char *src_path, struct copy_fs_state *s,
u64 reserve_start)
{
struct fiemap_iter iter;
struct fiemap_extent e;
fiemap_for_each(src_fd, iter, e)
if (e.fe_flags & FIEMAP_EXTENT_UNKNOWN) {
fsync(src_fd);
break;
}
fiemap_iter_exit(&iter);
fiemap_for_each(src_fd, iter, e) {
u64 src_max = roundup(src_size, block_bytes(c));
e.fe_length = min(e.fe_length, src_max - e.fe_logical);
if ((e.fe_logical & (block_bytes(c) - 1)) ||
(e.fe_length & (block_bytes(c) - 1)))
die("Unaligned extent in %s - can't handle", src_path);
if (BCH_MIGRATE_copy == s->type || (e.fe_flags & (FIEMAP_EXTENT_UNKNOWN|
FIEMAP_EXTENT_ENCODED|
FIEMAP_EXTENT_NOT_ALIGNED|
FIEMAP_EXTENT_DATA_INLINE))) {
copy_data(c, dst, src_fd, e.fe_logical,
e.fe_logical + min(src_size - e.fe_logical,
e.fe_length));
continue;
}
/* If the data is in bcachefs's superblock region, copy it: */
if (e.fe_physical < reserve_start) {
copy_data(c, dst, src_fd, e.fe_logical,
e.fe_logical + min(src_size - e.fe_logical,
e.fe_length));
continue;
}
if ((e.fe_physical & (block_bytes(c) - 1)))
die("Unaligned extent in %s - can't handle", src_path);
range_add(&s->extents, e.fe_physical, e.fe_length);
link_data(c, dst, e.fe_logical, e.fe_physical, e.fe_length);
}
fiemap_iter_exit(&iter);
}
static void copy_dir(struct copy_fs_state *s,
struct bch_fs *c,
struct bch_inode_unpacked *dst,
int src_fd, const char *src_path,
u64 reserve_start)
{
DIR *dir = fdopendir(src_fd);
struct dirent *d;
while ((errno = 0), (d = readdir(dir))) {
struct bch_inode_unpacked inode;
int fd;
if (fchdir(src_fd))
die("chdir error: %m");
struct stat stat =
xfstatat(src_fd, d->d_name, AT_SYMLINK_NOFOLLOW);
if (!strcmp(d->d_name, ".") ||
!strcmp(d->d_name, "..") ||
!strcmp(d->d_name, "lost+found"))
continue;
if (BCH_MIGRATE_migrate == s->type && stat.st_ino == s->bcachefs_inum)
continue;
char *child_path = mprintf("%s/%s", src_path, d->d_name);
if (s->type == BCH_MIGRATE_migrate && stat.st_dev != s->dev)
die("%s does not have correct st_dev!", child_path);
u64 *dst_inum = S_ISREG(stat.st_mode)
? genradix_ptr_alloc(&s->hardlinks, stat.st_ino, GFP_KERNEL)
: NULL;
if (dst_inum && *dst_inum) {
create_link(c, dst, d->d_name, *dst_inum, S_IFREG);
goto next;
}
inode = create_file(c, dst, d->d_name,
stat.st_uid, stat.st_gid,
stat.st_mode, stat.st_rdev);
if (dst_inum)
*dst_inum = inode.bi_inum;
copy_xattrs(c, &inode, d->d_name);
/* copy xattrs */
switch (mode_to_type(stat.st_mode)) {
case DT_DIR:
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
copy_dir(s, c, &inode, fd, child_path, reserve_start);
close(fd);
break;
case DT_REG:
inode.bi_size = stat.st_size;
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
copy_file(c, &inode, fd, stat.st_size,
child_path, s, reserve_start);
close(fd);
break;
case DT_LNK:
inode.bi_size = stat.st_size;
copy_link(c, &inode, d->d_name);
break;
case DT_FIFO:
case DT_CHR:
case DT_BLK:
case DT_SOCK:
case DT_WHT:
/* nothing else to copy for these: */
break;
default:
BUG();
}
copy_times(c, &inode, &stat);
update_inode(c, &inode);
next:
free(child_path);
}
if (errno)
die("readdir error: %m");
closedir(dir);
}
static void reserve_old_fs_space(struct bch_fs *c,
struct bch_inode_unpacked *root_inode,
ranges *extents,
u64 reserve_start)
{
struct bch_dev *ca = c->devs[0];
struct bch_inode_unpacked dst;
struct hole_iter iter;
struct range i;
dst = create_file(c, root_inode, "old_migrated_filesystem",
0, 0, S_IFREG|0400, 0);
dst.bi_size = bucket_to_sector(ca, ca->mi.nbuckets) << 9;
ranges_sort_merge(extents);
for_each_hole(iter, *extents, bucket_to_sector(ca, ca->mi.nbuckets) << 9, i) {
if (i.end <= reserve_start)
continue;
u64 start = max(i.start, reserve_start);
link_data(c, &dst, start, start, i.end - start);
}
update_inode(c, &dst);
}
void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
struct copy_fs_state *s, u64 reserve_start)
{
syncfs(src_fd);
struct bch_inode_unpacked root_inode;
int ret = bch2_inode_find_by_inum(c, (subvol_inum) { 1, BCACHEFS_ROOT_INO },
&root_inode);
if (ret)
die("error looking up root directory: %s", bch2_err_str(ret));
if (fchdir(src_fd))
die("chdir error: %m");
struct stat stat = xfstat(src_fd);
copy_times(c, &root_inode, &stat);
copy_xattrs(c, &root_inode, ".");
/* now, copy: */
copy_dir(s, c, &root_inode, src_fd, src_path, reserve_start);
if (BCH_MIGRATE_migrate == s->type)
reserve_old_fs_space(c, &root_inode, &s->extents, reserve_start);
update_inode(c, &root_inode);
if (BCH_MIGRATE_migrate == s->type)
darray_exit(&s->extents);
genradix_free(&s->hardlinks);
}

54
c_src/posix_to_bcachefs.h Normal file
View File

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _POSIX_TO_BCACHEFS_H
#define _POSIX_TO_BCACHEFS_H
/*
* This header exports the functionality needed for copying data from existing
* posix compliant filesystems to bcachefs. There are two use cases:
* 1. Creating a new bcachefs filesystem using `bcachefs format`, we can
* specify a source directory tree which will be copied over the new
* bcachefs filesytem.
* 2. Migrating an existing filesystem in place, with `bcachefs migrate`.
* This will allocate space for the bcachefs metadata, but the actual data
* represented by the extents will not be duplicated. The bcachefs metadata
* will simply point to the existing extents.
*
* To avoid code duplication, `copy_fs` deals with both cases. See the function
* documentation for more details.
*/
#include "libbcachefs.h"
enum bch_migrate_type {
BCH_MIGRATE_copy,
BCH_MIGRATE_migrate
};
/*
* The migrate action uses all the fields in this struct.
* The copy action only uses the `hardlinks` field. Since `hardlinks` is
* initialized with zeroes, an empty `copy_fs_state` struct can be passed.
*/
struct copy_fs_state {
u64 bcachefs_inum;
dev_t dev;
GENRADIX(u64) hardlinks;
ranges extents;
enum bch_migrate_type type;
};
/*
* The `copy_fs` function is used for both copying a directory tree to a new
* bcachefs filesystem and migrating an existing one, depending on the value
* from the `type` field in `copy_fs_state` struct.
*
* In case of copy, an empty `copy_fs_state` structure is passed to `copy_fs`
* (only the `hardlinks` field is used, and that is initialized with zeroes).
*
* In the migrate case, all the fields from `copy_fs_state` need to be
* initialized (`hardlinks` is initialized with zeroes).
*/
void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
struct copy_fs_state *s, u64);
#endif /* _LIBBCACHE_H */

View File

@ -185,6 +185,24 @@ unsigned get_blocksize(int fd)
/* Open a block device, do magic blkid stuff to probe for existing filesystems: */
int open_for_format(struct dev_opts *dev, bool force)
{
int blkid_version_code = blkid_get_library_version(NULL, NULL);
if (blkid_version_code < 2401) {
if (force) {
fprintf(
stderr,
"Continuing with out of date libblkid %s because --force was passed.\n",
BLKID_VERSION);
} else {
// Reference for picking 2.40.1:
// https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.40/v2.40.1-ReleaseNotes
// https://github.com/util-linux/util-linux/issues/3103
die(
"Refusing to format when using libblkid %s\n"
"libblkid >= 2.40.1 is required to check for existing filesystems\n"
"Earlier versions may not recognize some bcachefs filesystems.\n", BLKID_VERSION);
}
}
blkid_probe pr;
const char *fs_type = NULL, *fs_label = NULL;
size_t fs_type_len, fs_label_len;
@ -271,7 +289,7 @@ void ranges_sort_merge(ranges *r)
/* Merge contiguous ranges: */
darray_for_each(*r, i) {
struct range *t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
struct range *t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL;
if (t && t->end >= i->start)
t->end = max(t->end, i->end);
@ -708,6 +726,28 @@ struct bbpos_range bbpos_range_parse(char *buf)
return (struct bbpos_range) { .start = start, .end = end };
}
unsigned version_parse(char *buf)
{
char *s = buf;
char *major_str = strsep(&s, ".");
char *minor_str = strsep(&s, ".");
unsigned major, minor;
if (!minor_str) {
major = 0;
if (kstrtouint(major_str, 10, &minor))
die("invalid version %s", buf);
} else {
if (kstrtouint(major_str, 10, &major) ||
kstrtouint(minor_str, 10, &minor))
die("invalid version %s", buf);
}
return BCH_VERSION(major, minor);
}
darray_str get_or_split_cmdline_devs(int argc, char *argv[])
{
darray_str ret = {};

View File

@ -174,6 +174,8 @@ struct fiemap_extent fiemap_iter_next(struct fiemap_iter *);
char *strcmp_prefix(char *, const char *);
/* Avoid conflicts with libblkid's crc32 function in static builds */
#define crc32c bch_crc32c
u32 crc32c(u32, const void *, size_t);
char *dev_to_name(dev_t);
@ -207,6 +209,8 @@ struct bbpos_range {
struct bbpos_range bbpos_range_parse(char *);
unsigned version_parse(char *);
darray_str get_or_split_cmdline_devs(int argc, char *argv[]);
#endif /* _TOOLS_UTIL_H */

View File

@ -97,7 +97,7 @@
* UNNEEDED - a variable/function may not be needed
*
* This suppresses warnings about unused variables or functions, but tells
* the compiler that if it is unused it need not emit it into the source code.
* the compiler that if it is unused it needs not emit it into the source code.
*
* Example:
* // With some preprocessor options, this is unnecessary.

1
debian/bcachefs.triggers vendored Normal file
View File

@ -0,0 +1 @@
activate update-initramfs

176
debian/changelog vendored
View File

@ -1,44 +1,158 @@
bcachefs-tools (1.0.8-2~bpo8+1) jessie-backports; urgency=medium
bcachefs-tools (1:1.9.1-1) unstable; urgency=medium
* Rebuild for jessie-backports.
* New upstream release
* New build-depency: librust-strum-dev
* Update copyright file
-- Mathieu Parent <sathieu@debian.org> Mon, 21 Sep 2015 21:18:39 +0200
-- Jonathan Carter <jcc@debian.org> Thu, 20 Jun 2024 17:28:12 +0200
bcachefs-tools (1.0.8-2) unstable; urgency=medium
bcachefs-tools (1:1.7.0-1) unstable; urgency=medium
* Only run update-initramfs if installed. Fix dracut. (Closes: #788442)
* Upload to unstable (Closes: #1066929)
* Bump epoch
- Ack from pochu:
https://lists.debian.org/msgid-search/1c5f86c9-1525-4d44-996f-3d4eed1e64d6@debian.org
-- David Mohr <david@mcbf.net> Thu, 11 Jun 2015 10:23:48 -0600
-- Jonathan Carter <jcc@debian.org> Wed, 15 May 2024 12:04:38 +0200
bcachefs-tools (1.0.8-1) unstable; urgency=medium
bcachefs-tools (24+really1.7.0-1~exp1) experimental; urgency=medium
[ James Page ]
* d/control: Add Vcs fields.
[ Steinar H. Gunderson ]
* New upstream release.
* Remove the do-not-install-mount-symlink patch.
* Add epoch to deal with new upstream versioning scheme,
and disable pristine-tar option in gbp.conf, since there is no
pristine-tar branch. (Closes: #1054620)
* revert-bindgen-changes.patch: New patch, reinstates upstream
hack that makes bcachefs-tools work with bindgen older than 0.69.4
(which isn't in Debian yet).
* Build-depend on systemd-dev, since udev.pc has moved there.
* Enable Rust parts, including mount.bcachefs. (Closes: #1060256)
* Include the right .mk flags to get DEB_HOST_RUST_TYPE etc., and
export that (needed for Debian's cargo wrapper).
* Override CARGO, and set CARGO_HOME during installation.
* Run prepare-debian in dh_auto_configure, and clean up the vendor dir
in dh_auto_clean.
* Remove Cargo.lock before the build, so that we can use Debian's versions
of all Rust crates. Also remove it in dh_auto_clean, so that it does not
take a diff.
* revert-bindgen-changes.patch: New patch, loosen required versions
of Rust crates
- errno (0.2 -> >= 0.2, < 1; Debian has 0.4)
- udev (0.7 -> >= 0.7, < 1; Debian has 0.8)
- memoffset (0.8.0 -> 0.6; Debian has 0.6.5, so a downgrade)
- paste (1.0.11 -> 1.0; Debian has 1.0.8, so a downgrade)
- bindgen (0.69.4 -> 0.66; see revert-bindgen-changes.patch above)
* Add build-dependency on all relevant Rust crates, and on python3:native
due to use of the Cargo wrapper.
* Build-Depend on pkgconf instead of pkg-config (Lintian warning).
* Add debhelper tokens to postinst and postrm scripts (Lintian warning).
* Depend on python3:any due to bcachefsck_all being a Python script
(Lintian warning).
[ David Mohr ]
* Don't depend on initramfs-tools, instead recommend it (Closes: #775674)
* New upstream release 1.0.8
* Update changelog
* Add patch to clean bcache-register
* Update changelog
* Adding dep3 headers to the 0001 patch
* Update watch to use http://evilpiepirate.org/git/bcache-tools.git
* Add patch for gcc-5 compatability.
Thanks to James Cowgill (Closes: #777798)
[ Jonathan Carter ]
* Upload to experimental
* Add librust-chrono-dev, librust-getset-dev and
librust-gag-dev to build-depends
* Recreate dependencies patch to match new upstream source
* Update standards version to 4.7.0
* Update above mentioned revert-bindgen-changes.patch
-- David Mohr <david@mcbf.net> Tue, 26 May 2015 20:57:58 -0600
-- Jonathan Carter <jcc@debian.org> Thu, 25 Apr 2024 13:53:55 +0200
bcachefs-tools (1.0.7-1) unstable; urgency=medium
bcachefs-tools (24+really1.3.4-2) unstable; urgency=medium
[ David Mohr ]
* Based on work by Gabriel de Perthuis <g2p.code+debian@gmail.com>
* Initial release. (Closes: #708132)
* Upload to unstable
[ Robie Basak ]
* Remove unnecessary file bcache-tools.postrm.
* debian/copyright fixes.
* Add shebang to bcache-tools.preinst.
* Drop Vcs-* for now.
* Add self to Uploaders.
-- Jonathan Carter <jcc@debian.org> Wed, 03 Jan 2024 17:06:16 +0200
-- Robie Basak <robie@justgohome.co.uk> Mon, 27 Oct 2014 13:32:08 +0000
bcachefs-tools (24+really1.3.4-2~exp1) experimental; urgency=medium
[ Chris Hofstaedtler ]
* Non-maintainer upload.
* Install files into /usr instead of /. (Closes: #1059373)
[ Jonathan Carter ]
* Do not install bcachefs.mount symlink (Closes: #1057295)
-- Jonathan Carter <jcc@debian.org> Wed, 27 Dec 2023 19:22:06 +0200
bcachefs-tools (24+really1.3.4-1) unstable; urgency=medium
* New upstream release
-- Jonathan Carter <jcc@debian.org> Tue, 21 Nov 2023 17:26:13 +0200
bcachefs-tools (24+really1.2-1) unstable; urgency=medium
* New upstream release (Closes: #1054613)
* Disable new rust build
(dependencies currently unavailable in Debian, see debian/README.todo)
* Remove unneeded override_dh_auto_clean from debian/rules
(Closes: #1043654)
-- Jonathan Carter <jcc@debian.org> Thu, 28 Sep 2023 19:54:47 +0200
bcachefs-tools (24-1) unstable; urgency=medium
* New upstream release
-- Jonathan Carter <jcc@debian.org> Tue, 29 Nov 2022 09:40:27 +0200
bcachefs-tools (23-1) unstable; urgency=medium
* New upstream release
* Update standards version to 4.6.1
-- Jonathan Carter <jcc@debian.org> Mon, 31 Oct 2022 11:45:25 +0200
bcachefs-tools (0.1+git20220216.a1e928a-1) unstable; urgency=medium
* New upstream snapshot
* Grab patch from Ubuntu to reduce memory on amd64 builders
(http://launchpadlibrarian.net/580140160/bcachefs-tools_0.1+git20210805.6c42566-2_0.1+git20210805.6c42566-2ubuntu1.diff.gz)
* Update copyright years
-- Jonathan Carter <jcc@debian.org> Wed, 16 Feb 2022 14:42:20 +0200
bcachefs-tools (0.1+git20210805.6c42566-2) unstable; urgency=medium
* Remove valgrind as build-dependency, seems unneeded unless
doing debug work and is not available on all architectures.
-- Jonathan Carter <jcc@debian.org> Fri, 03 Sep 2021 16:07:11 +0200
bcachefs-tools (0.1+git20210805.6c42566-1) unstable; urgency=medium
* New upstream snapshot
* Update standards version to 4.6.0
* Add python3-docutils as dependency
* Do not run tests at package build time
-- Jonathan Carter <jcc@debian.org> Tue, 06 Apr 2021 15:11:27 +0200
bcachefs-tools (0.1+git20201025.742dbbdb-1) unstable; urgency=medium
* New upstream snapshot
-- Jonathan Carter <jcc@debian.org> Mon, 26 Oct 2020 08:45:37 +0200
bcachefs-tools (0.1+git20201017.8a4408-1~exp1) unstable; urgency=medium
* New upstream release
* Bump debhelper-compat to 13
* Update standards version to 4.5.0
* Declare Rules-Requires-Root: no
* debian/copyright:
- Update copyright years
- Update copyright owners
- Add intel and ccan copyright
* Add build-dep on libudev-dev, python3-pytest and valgrind
-- Jonathan Carter <jcc@debian.org> Sun, 18 Oct 2020 17:29:27 +0200
bcachefs-tools (0.1+git20190829.aa2a42b-1~exp1) experimental; urgency=medium
* Initial Release (Closes: #935178)
-- Jonathan Carter <jcc@debian.org> Mon, 16 Sep 2019 10:36:04 +0000

1
debian/compat vendored
View File

@ -1 +0,0 @@
10

35
debian/control vendored
View File

@ -1,18 +1,39 @@
Source: bcachefs-tools
Maintainer: Kent Overstreet <kent.overstreet@gmail.com>
Maintainer: Jonathan Carter <jcc@debian.org>
Section: utils
Priority: optional
Standards-Version: 3.9.5
Build-Depends: debhelper (>= 9), dh-python, pkg-config, libaio-dev, libblkid-dev,
libkeyutils-dev, liblz4-dev, libsodium-dev, liburcu-dev, libudev-dev,
libzstd-dev, uuid-dev, zlib1g-dev, python3, python3-docutils,
rustc, cargo, llvm, clang, libclang-dev, systemd, udev
Standards-Version: 4.7.0
Rules-Requires-Root: no
Build-Depends: debhelper-compat (= 13),
cargo,
python3:native,
pkgconf,
python3-docutils,
libaio-dev,
libfuse3-dev,
libblkid-dev,
libkeyutils-dev,
liblz4-dev,
libscrypt-dev,
libsodium-dev,
libudev-dev,
liburcu-dev,
libzstd-dev,
systemd-dev,
uuid-dev,
zlib1g-dev,
Homepage: https://bcachefs.org/
Vcs-Git: https://salsa.debian.org/jcc/bcachefs-tools.git
Vcs-Browser: https://salsa.debian.org/jcc/bcachefs-tools
Package: bcachefs-tools
Architecture: linux-any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${python3:Depends}
Depends: ${shlibs:Depends}, ${misc:Depends}, python3:any
Recommends: initramfs-tools | linux-initramfs-tool
Description: bcachefs userspace tools
Userspace tools for bcachefs, a modern copy on write, checksumming, multi
device filesystem.
.
Note: The current Debian kernels do not come with bcachefs support, you
will have to use your own kernel or one provided by a 3rd party that
contains bcachefs support.

89
debian/copyright vendored
View File

@ -1,22 +1,67 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Contact: kent.overstreet@gmail.com
linux-bcachefs@vger.kernel.org
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Contact: kmo@daterainc.com
linux-bcache@vger.kernel.org
Source: https://evilpiepirate.org/git/bcachefs-tools.git
Files: *
Copyright: 2013 Kent Overstreet <kmo@daterainc.com>
Copyright: 2023-2024 Oracle
2013-2022 Kent Overstreet <kmo@daterainc.com>
2018 SUSE Linux
2012-2016, Yann Collet
2013 Gabriel de Perthuis <g2p.code@gmail.com>
2015 Martin Willi
2007-2015 Herbert Xu <herbert@gondor.apana.org.au>
2014-2015 Thomas Graf <tgraf@suug.ch>
2008-2014 Patrick McHardy <kaber@trash.net>
2004-2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
2012 Google Inc
2010-2011 Inter Corp
2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
2006-2008 Greg Kroah-Hartman <greg@kroah.com>
2006-2008 Novell Inc.
2007-2008 Intel Corporation <willy@linux.intel.com>
2002-2003 Patrick Mochel
2002-2003 Open Source Development Labs
2002 James Morris <jmorris@intercode.com.au>
2001-2002 Silicon Graphics, Inc.
2002 David S. Miller (davem@redhat.com)
2001 Jens Axboe <axboe@kernel.dk>
2001 Ming Lei <ming.lei@canonical.com>
2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
2001 Linus Torvalds
License: GPL-2
Files: bcache-super-show.c
Copyright: 2013 Gabriel de Perthuis <g2p.code@gmail.com>
License: GPL-2
Files: ccan/*
Copyright: Copyright waived
License: cc0-1.0
On Debian systems, the complete text of the Creative Commons CC0 1.0
Universal license (CC0-1.0) can be found in
"/usr/share/common-licenses/CC0-1.0".
Files: bcache.c
Copyright: 1996-2001, PostgreSQL Global Development Group
License: PostgreSQL
Files: ccan/darray/*
Copyright: 2011 Joseph Adams <joeyadams3.14159@gmail.com>
License: expat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Files: debian/*
Copyright: 2014 Tom Strickx <tstrickx@rootcu.be>,
Copyright: 2019-2024 Jonathan Carter <jcc@debian.org>
2014 Tom Strickx <tstrickx@rootcu.be>,
2014 David Mohr <david@mcbf.net>
License: GPL-2+
@ -62,25 +107,3 @@ License: GPL-2+
On Debian systems, the full text of the GNU General Public
License version 2 can be found in the file
`/usr/share/common-licenses/GPL-2'.
License: PostgreSQL
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose, without fee,
and without a written agreement is hereby granted, provided
that the above copyright notice and this paragraph and the
following two paragraphs appear in all copies.
.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO
ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

2
debian/gbp.conf vendored
View File

@ -1,5 +1,5 @@
[DEFAULT]
pristine-tar = True
pristine-tar = False
upstream-tag = v%(version)s
ignore-branch = True

36
debian/rules vendored
View File

@ -1,9 +1,41 @@
#!/usr/bin/make -f
include /usr/share/dpkg/architecture.mk
include /usr/share/rustc/architecture.mk
export DEB_HOST_RUST_TYPE DEB_HOST_GNU_TYPE
export DEB_BUILD_MAINT_OPTIONS=hardening=+all
export CARGO=/usr/share/cargo/bin/cargo
export CARGO_HOME=$(CURDIR)/debian/cargo_home
export DEB_CARGO_CRATE=bcachefs-tools_$(DEB_VERSION_UPSTREAM)
PREFIX := /usr
ROOT_SBINDIR := /usr/sbin
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
ifeq ($(DEB_BUILD_ARCH),amd64)
DEB_BUILD_MAINT_OPTIONS += optimize=-lto
endif
%:
dh $@ --with python3
dh $@
override_dh_auto_configure:
$(CARGO) prepare-debian $(CURDIR)/vendor --link-from-system
override_dh_auto_build:
$(RM) Cargo.lock
dh_auto_build -- CARGO="$(CARGO)"
override_dh_auto_install:
dh_auto_install -- "PREFIX=$(PREFIX)"
dh_auto_install -- "PREFIX=$(PREFIX)" "ROOT_SBINDIR=$(ROOT_SBINDIR)"
override_dh_auto_clean:
! [ -d $(CURDIR)/vendor ] || $(RM) -r $(CURDIR)/vendor
! [ -d $(CARGO_HOME) ] || $(RM) -r $(CARGO_HOME)
$(RM) Cargo.lock
dh_auto_clean
override_dh_auto_test:

2
debian/watch vendored
View File

@ -1,3 +1,3 @@
version=4
opts=filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/bcachefs-tools_$1\.tar\.gz/ \
opts=filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/bcachefs-tools_$1\.tar\.gz/,uversionmangle=s/(\d)/$1/ \
https://github.com/koverstreet/bcachefs-tools/tags .*/v?(\d\S+)\.tar\.gz

View File

@ -1,6 +1,9 @@
(import (let lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in fetchTarball {
url =
"https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}) { src = ./.; }).defaultNix
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) { src = ./.; }).defaultNix

View File

@ -388,13 +388,13 @@ limitation being disk space.
The following subcommands exist for managing subvolumes and snapshots:
\begin{itemize}
\item \texttt{bcachefs subvolume create}: Create a new, empty subvolume
\item \texttt{bcachefs subvolume destroy}: Delete an existing subvolume
\item \texttt{bcachefs subvolume delete}: Delete an existing subvolume
or snapshot
\item \texttt{bcachefs subvolume snapshot}: Create a snapshot of an
existing subvolume
\end{itemize}
A subvolume can also be deleting with a normal rmdir after deleting all the
A subvolume can also be deleted with a normal rmdir after deleting all the
contents, as with \texttt{rm -rf}. Still to be implemented: read-only snapshots,
recursive snapshot creation, and a method for recursively listing subvolumes.
@ -464,7 +464,7 @@ The \texttt{-o verbose} enables additional log output during the mount process.
It is possible to run fsck either in userspace with the \texttt{bcachefs fsck}
subcommand (also available as \texttt{fsck.bcachefs}, or in the kernel while
mounting by specifying the \texttt{-o fsck} mount option. In either case the
mounting by specifying the \texttt{-o fsck} mount option). In either case the
exact same fsck implementation is being run, only the environment is different.
Running fsck in the kernel at mount time has the advantage of somewhat better
performance, while running in userspace has the ability to be stopped with
@ -505,8 +505,8 @@ the \texttt{journal\_reclaim\_delay} parameter, with a default of 100
milliseconds.
The journal should be sized sufficiently that bursts of activity do not fill up
the journal too quickly; also, a larger journal mean that we can queue up larger
btree writes. The \texttt{bcachefs device resize-journal} can be used for
the journal too quickly; also, a larger journal means that we can queue up
larger btree writes. The \texttt{bcachefs device resize-journal} can be used for
resizing the journal on disk on a particular device - it can be used on a
mounted or unmounted filesystem.
@ -528,7 +528,7 @@ filesystem:
\begin{itemize}
\item \texttt{bcachefs device add}: Formats and adds a new device to an
existing filesystem.
\item \texttt{bcachefs device remove}: Permenantly removes a device from
\item \texttt{bcachefs device remove}: Permanently removes a device from
an existing filesystem.
\item \texttt{bcachefs device online}: Connects a device to a running
filesystem that was mounted without it (i.e. in degraded mode)
@ -578,8 +578,8 @@ ensuring that checksums are valid, fixing bitrot when a valid copy can be found.
Most bcachefs options can be set filesystem wide, and a significant subset can
also be set on inodes (files and directories), overriding the global defaults.
Filesystem wide options may be set when formatting, when mounting, or at runtime
via \texttt{/sys/fs/bcachefs/<uuid>/options/}. When set at runtime via sysfs the
persistent options in the superblock are updated as well; when options are
via \texttt{/sys/fs/bcachefs/<uuid>/options/}. When set at runtime via sysfs,
the persistent options in the superblock are updated as well; when options are
passed as mount parameters the persistent options are unmodified.
\subsection{File and directory options}
@ -593,8 +593,8 @@ inherited attributes to change we fail the rename with -EXDEV, causing userspace
to do the rename file by file so that inherited attributes stay consistent.
Inode options are available as extended attributes. The options that have been
explicitly set are available under the \texttt{bcachefs} namespace, and the effective
options (explicitly set and inherited options) are available under the
explicitly set are available under the \texttt{bcachefs} namespace, and the
effective options (explicitly set and inherited options) are available under the
\texttt{bcachefs\_effective} namespace. Examples of listing options with the
getfattr command:
@ -912,7 +912,7 @@ quantiles for latency/duration in the
\end{itemize}
\item \texttt{btree\_key\_cache} \\
Prints infromation on the btree key cache: number of freed keys
Prints information on the btree key cache: number of freed keys
(which must wait for a sRCU barrier to complete before being
freed), number of cached keys, and number of dirty keys.
@ -1036,7 +1036,7 @@ listing btree nodes and contents, but for offline filesystems.
\subsubsection{bcachefs list\_journal}
This subcommand lists the contents of the journal, which primarily records btree
updates ordered by when they occured.
updates ordered by when they occurred.
\subsubsection{bcachefs dump}
@ -1052,7 +1052,7 @@ This section documents bcachefs-specific ioctls:
\begin{description}
\item \texttt{BCH\_IOCTL\_QUERY\_UUID} \\
Returs the UUID of the filesystem: used to find the sysfs
Returns the UUID of the filesystem: used to find the sysfs
directory given a path to a mounted filesystem.
\item \texttt{BCH\_IOCTL\_FS\_USAGE} \\
@ -1102,7 +1102,7 @@ This section documents bcachefs-specific ioctls:
\item \texttt{BCH\_IOCTL\_DISK\_RESIZE\_JOURNAL} \\
\item \texttt{BCH\_IOCTL\_DATA} \\
Starts a data job, which walks all data and/or metadata in a
filesystem performing, performaing some operation on each btree
filesystem performing, performing some operations on each btree
node and extent. Returns a file descriptor which can be read
from to get the current status of the job, and closing the file
descriptor (i.e. on process exit stops the data job.
@ -1150,7 +1150,7 @@ variable length sections:
\item \texttt{BCH\_SB\_FIELD\_replicas} \\
Contains a list of replica entries, which are lists of devices
that have extents replicated across them.
that have extents replicated across them.
\item \texttt{BCH\_SB\_FIELD\_quota} \\
Contains timelimit and warnlimit fields for each quota type

View File

@ -29,9 +29,10 @@ time, mount time (as mount -o parameters), or changed at runtime via sysfs (via
the /sys/fs/bcachefs/<UUID>/options/ directory).
Many of those options (particularly those that control the IO path) can also be
set on individual files and directories, via the bcachefs setattr command (which
internally mostly works via the extended attribute interface, but the setattr
command takes care to propagate options to children correctly).
set on individual files and directories, via the bcachefs set-file-option
command (which internally mostly works via the extended attribute interface, but
the set-file-option command takes care to propagate options to children
correctly).
OPTIONS
-------
@ -48,14 +49,14 @@ at the same time.
We generally avoid per-device options, preferring instead options that can be
overridden on files or directories, but there are some:
*durability*
*durability*
Device labels, targets
----------------------
Configuration options that point to targets (i.e. a disk or group of disks) may
be passed either a device (i.e. /dev/sda), or a label. Labels are assigned to
disks (and need not be unique), and these labels form a nested heirarchy: this
disks (and need not be unique), and these labels form a nested hierarchy: this
allows disks to be grouped together and referred to either individually or as a
group.
@ -86,7 +87,7 @@ The foreground_target option is used to direct writes from applications. The
background_target option, if set, will cause data to be moved to that target in
the background by the rebalance thread some time after it has been initially
written - leaving behind the original copy, but marking it cached so that it can
be discarded by the allocator. The promote_target will will cause reads to write
be discarded by the allocator. The promote_target will cause reads to write
a cached copy of the data being read to that target, if it doesn't exist.
Together, these options can be used for writeback caching, like so:

137
flake.lock generated
View File

@ -1,13 +1,28 @@
{
"nodes": {
"crane": {
"locked": {
"lastModified": 1742394900,
"narHash": "sha256-vVOAp9ahvnU+fQoKd4SEXB2JG2wbENkpqcwlkIXgUC0=",
"owner": "ipetkov",
"repo": "crane",
"rev": "70947c1908108c0c551ddfd73d4f750ff2ea67cd",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"lastModified": 1733328505,
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github"
},
"original": {
@ -16,13 +31,51 @@
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1741352980,
"narHash": "sha256-+u2UunDA4Cl5Fci3m7S643HzKmIDAe+fiXrLqYsR2fs=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f4330d22f1c5d2ba72d3d22df5597d123fdb60a9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1737420293,
"narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1698924604,
"narHash": "sha256-GCFbkl2tj8fEZBZCw3Tc0AkGo0v+YrQlohhEGJ/X4s0=",
"lastModified": 1742422364,
"narHash": "sha256-mNqIplmEohk5jRkqYqG19GA8MbQ/D4gQSK0Mu4LvfRQ=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "fa804edfb7869c9fb230e174182a8a1a7e512c40",
"rev": "a84ebe20c6bc2ecbcfb000a50776219f48d134cc",
"type": "github"
},
"original": {
@ -32,43 +85,69 @@
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1740877520,
"narHash": "sha256-oiwv/ZK/2FhGxrCkQkB83i7GnWXPPLzoqFHpDD3uYpk=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "147dee35aab2193b174e4c0868bd80ead5ce755c",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"root": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"nix-github-actions": "nix-github-actions",
"nixpkgs": "nixpkgs",
"utils": "utils"
"rust-overlay": "rust-overlay",
"treefmt-nix": "treefmt-nix"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"rust-overlay": {
"inputs": {
"systems": "systems"
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"lastModified": 1742524367,
"narHash": "sha256-KzTwk/5ETJavJZYV1DEWdCx05M4duFCxCpRbQSKWpng=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "70bf752d176b2ce07417e346d85486acea9040ef",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1742370146,
"narHash": "sha256-XRE8hL4vKIQyVMDXykFh4ceo3KSpuJF3ts8GKwh5bIU=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"repo": "treefmt-nix",
"rev": "adc195eef5da3606891cedf80c0d9ce2d3190808",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"repo": "treefmt-nix",
"type": "github"
}
}

349
flake.nix
View File

@ -1,40 +1,327 @@
{
description = "Userspace tools for bcachefs";
# Nixpkgs / NixOS version to use.
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
inputs.utils.url = "github:numtide/flake-utils";
inputs.flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
crane.url = "github:ipetkov/crane";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
nix-github-actions = {
url = "github:nix-community/nix-github-actions";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, utils, ... }:
{
overlays.default = final: prev: {
bcachefs = final.callPackage ./build.nix { };
outputs =
inputs@{
self,
nixpkgs,
flake-parts,
treefmt-nix,
crane,
rust-overlay,
flake-compat,
nix-github-actions,
}:
let
systems = nixpkgs.lib.filter (s: nixpkgs.lib.hasSuffix "-linux" s) nixpkgs.lib.systems.flakeExposed;
in
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ inputs.treefmt-nix.flakeModule ];
flake = {
githubActions = nix-github-actions.lib.mkGithubMatrix {
# github actions supports fewer architectures
checks = nixpkgs.lib.getAttrs [ "aarch64-linux" "x86_64-linux" ] self.checks;
};
};
} // utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ self.overlays.default ];
};
in {
packages = {
inherit (pkgs) bcachefs;
bcachefs-fuse = pkgs.bcachefs.override { fuseSupport = true; };
default = pkgs.bcachefs;
};
formatter = pkgs.nixfmt;
inherit systems;
devShells.default = pkgs.callPackage ({ mkShell, rustc, cargo, gnumake
, gcc, clang, pkg-config, libuuid, libsodium, keyutils, liburcu, zlib
, libaio, zstd, lz4, udev, bcachefs }:
mkShell {
LIBCLANG_PATH = "${clang.cc.lib}/lib";
inherit (bcachefs) nativeBuildInputs buildInputs;
}) { };
});
perSystem =
{
self',
config,
lib,
system,
...
}:
let
inherit (builtins) readFile split;
inherit (lib.lists) findFirst;
inherit (lib.strings) hasPrefix removePrefix substring;
pkgs = import nixpkgs {
inherit system;
overlays = [ (import rust-overlay) ];
};
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
rustfmtToml = builtins.fromTOML (builtins.readFile ./rustfmt.toml);
rev = self.shortRev or self.dirtyShortRev or (substring 0 8 self.lastModifiedDate);
makefileVersion = removePrefix "VERSION=" (
findFirst (line: hasPrefix "VERSION=" line) "VERSION=0.0.0" (split "\n" (readFile ./Makefile))
);
version = "${makefileVersion}+${rev}";
mkCommon =
{
crane,
pkgs,
rustVersion ? "latest",
# build time
buildPackages,
pkg-config,
rustPlatform,
stdenv,
# run time
keyutils,
libaio,
libsodium,
liburcu,
libuuid,
lz4,
udev,
zlib,
zstd,
}:
let
inherit (stdenv) cc hostPlatform;
craneLib = (crane.mkLib pkgs).overrideToolchain (
p: p.rust-bin.stable."${rustVersion}".minimal.override { extensions = [ "clippy" ]; }
);
args = {
inherit version;
src = self;
strictDeps = true;
env = {
PKG_CONFIG_SYSTEMD_SYSTEMDSYSTEMUNITDIR = "${placeholder "out"}/lib/systemd/system";
PKG_CONFIG_UDEV_UDEVDIR = "${placeholder "out"}/lib/udev";
CARGO_BUILD_TARGET = hostPlatform.rust.rustcTargetSpec;
"CARGO_TARGET_${hostPlatform.rust.cargoEnvVarTarget}_LINKER" = "${cc.targetPrefix}cc";
HOST_CC = "${cc.nativePrefix}cc";
TARGET_CC = "${cc.targetPrefix}cc";
};
makeFlags = [
"INITRAMFS_DIR=${placeholder "out"}/etc/initramfs-tools"
"PREFIX=${placeholder "out"}"
"VERSION=${version}"
];
dontStrip = true;
depsBuildBuild = [
buildPackages.stdenv.cc
];
nativeBuildInputs = [
pkg-config
rustPlatform.bindgenHook
];
buildInputs = [
keyutils
libaio
libsodium
liburcu
libuuid
lz4
udev
zlib
zstd
];
meta = {
description = "Userspace tools for bcachefs";
license = lib.licenses.gpl2Only;
mainProgram = "bcachefs";
};
};
cargoArtifacts = craneLib.buildDepsOnly args;
in
{
inherit args cargoArtifacts craneLib;
};
common = pkgs.callPackage mkCommon { inherit crane; };
mkPackage =
{ common, name }:
common.craneLib.buildPackage (
common.args
// {
inherit (common) cargoArtifacts;
pname = name;
enableParallelBuilding = true;
buildPhaseCargoCommand = ''
make ''${enableParallelBuilding:+-j''${NIX_BUILD_CORES}} $makeFlags
'';
doNotPostBuildInstallCargoBinaries = true;
installPhaseCommand = ''
make ''${enableParallelBuilding:+-j''${NIX_BUILD_CORES}} $makeFlags install
'';
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
test "$($out/bin/bcachefs version)" = "${version}"
runHook postInstallCheck
'';
}
);
mkPackages =
name: systems:
let
packagesForSystem =
crossSystem:
let
localSystem = system;
pkgs' = import nixpkgs {
inherit crossSystem localSystem;
overlays = [ (import rust-overlay) ];
};
common = pkgs'.callPackage mkCommon { inherit crane; };
package = pkgs'.callPackage mkPackage { inherit common name; };
packageFuse = package.overrideAttrs (
final: prev: {
makeFlags = prev.makeFlags ++ [ "BCACHEFS_FUSE=1" ];
buildInputs = prev.buildInputs ++ [ pkgs'.fuse3 ];
}
);
in
[
(lib.nameValuePair "${name}-${crossSystem}" package)
(lib.nameValuePair "${name}-fuse-${crossSystem}" packageFuse)
];
in
lib.listToAttrs (lib.flatten (map packagesForSystem systems));
in
{
packages =
let
inherit (cargoToml.package) name;
in
(mkPackages name systems)
// {
${name} = config.packages."${name}-${system}";
"${name}-fuse" = config.packages."${name}-fuse-${system}";
default = config.packages.${name};
};
checks = {
inherit (config.packages)
bcachefs-tools
bcachefs-tools-fuse
bcachefs-tools-fuse-i686-linux
;
cargo-clippy = common.craneLib.cargoClippy (
common.args
// {
inherit (common) cargoArtifacts;
cargoClippyExtraArgs = "--all-targets --all-features -- --deny warnings";
}
);
# we have to build our own `craneLib.cargoTest`
cargo-test = common.craneLib.mkCargoDerivation (
common.args
// {
inherit (common) cargoArtifacts;
doCheck = true;
enableParallelChecking = true;
pnameSuffix = "-test";
buildPhaseCargoCommand = "";
checkPhaseCargoCommand = ''
make ''${enableParallelChecking:+-j''${NIX_BUILD_CORES}} $makeFlags libbcachefs.a
cargo test --profile release -- --nocapture
'';
}
);
# cargo clippy with the current minimum supported rust version
# according to Cargo.toml
msrv =
let
rustVersion = cargoToml.package.rust-version;
common = pkgs.callPackage mkCommon { inherit crane rustVersion; };
in
common.craneLib.cargoClippy (
common.args
// {
pname = "msrv";
inherit (common) cargoArtifacts;
cargoClippyExtraArgs = "--all-targets --all-features -- --deny warnings";
}
);
};
devShells.default = pkgs.mkShell {
inputsFrom = [
config.packages.default
config.treefmt.build.devShell
];
# here go packages that aren't required for builds but are used for
# development, and might need to be version matched with build
# dependencies (e.g. clippy or rust-analyzer).
packages = with pkgs; [
bear
cargo-audit
cargo-outdated
clang-tools
(rust-bin.stable.latest.minimal.override {
extensions = [
"rust-analyzer"
"rust-src"
];
})
];
};
treefmt.config = {
projectRootFile = "flake.nix";
flakeCheck = false;
programs = {
nixfmt.enable = true;
rustfmt.edition = rustfmtToml.edition;
rustfmt.enable = true;
rustfmt.package = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.rustfmt);
};
};
};
};
}

View File

@ -7,6 +7,7 @@
#define _CRYPTO_SHA_H
#include <linux/types.h>
#include <sodium/crypto_hash_sha256.h>
#define SHA1_DIGEST_SIZE 20
#define SHA1_BLOCK_SIZE 64
@ -112,4 +113,9 @@ extern int crypto_sha512_update(struct shash_desc *desc, const u8 *data,
extern int crypto_sha512_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *hash);
static inline void sha256(const u8 *data, unsigned int len, u8 *out)
{
crypto_hash_sha256(out, data, len);
}
#endif

View File

@ -112,6 +112,8 @@ static inline void skcipher_request_set_sync_tfm(struct skcipher_request *req,
skcipher_request_set_tfm(req, &tfm->base);
}
#define skcipher_request_set_callback(...) do {} while (0)
static inline void skcipher_request_set_crypt(
struct skcipher_request *req,
struct scatterlist *src, struct scatterlist *dst,

View File

@ -16,55 +16,31 @@ typedef struct {
u64 counter;
} atomic64_t;
#ifndef C11_ATOMICS
#include <urcu/uatomic.h>
#if (CAA_BITS_PER_LONG != 64)
#define ATOMIC64_SPINLOCK
#endif
#define __ATOMIC_READ(p) uatomic_read(p)
#define __ATOMIC_SET(p, v) uatomic_set(p, v)
#define __ATOMIC_ADD_RETURN(v, p) uatomic_add_return(p, v)
#define __ATOMIC_SUB_RETURN(v, p) uatomic_sub_return(p, v)
#define __ATOMIC_ADD(v, p) uatomic_add(p, v)
#define __ATOMIC_SUB(v, p) uatomic_sub(p, v)
#define __ATOMIC_INC(p) uatomic_inc(p)
#define __ATOMIC_DEC(p) uatomic_dec(p)
#define __ATOMIC_AND(v, p) uatomic_and(p, v)
#define __ATOMIC_OR(v, p) uatomic_or(p, v)
#define xchg(p, v) uatomic_xchg(p, v)
#define xchg_acquire(p, v) uatomic_xchg(p, v)
#define cmpxchg(p, old, new) uatomic_cmpxchg(p, old, new)
#define cmpxchg_acquire(p, old, new) uatomic_cmpxchg(p, old, new)
#define cmpxchg_release(p, old, new) uatomic_cmpxchg(p, old, new)
#define smp_mb__before_atomic() cmm_smp_mb__before_uatomic_add()
#define smp_mb__after_atomic() cmm_smp_mb__after_uatomic_add()
#define smp_wmb() cmm_smp_wmb()
#define smp_rmb() cmm_smp_rmb()
#define smp_mb() cmm_smp_mb()
#define smp_read_barrier_depends() cmm_smp_read_barrier_depends()
#define smp_acquire__after_ctrl_dep() cmm_smp_mb()
#else /* C11_ATOMICS */
#define __ATOMIC_READ(p) __atomic_load_n(p, __ATOMIC_RELAXED)
#define __ATOMIC_SET(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)
#define __ATOMIC_SET_RELEASE(p, v) __atomic_store_n(p, v, __ATOMIC_RELEASE)
#define __ATOMIC_ADD_RETURN(v, p) __atomic_add_fetch(p, v, __ATOMIC_RELAXED)
#define __ATOMIC_ADD_RETURN_RELEASE(v, p) \
__atomic_add_fetch(p, v, __ATOMIC_RELEASE)
#define __ATOMIC_SUB_RETURN(v, p) __atomic_sub_fetch(p, v, __ATOMIC_RELAXED)
#define __ATOMIC_SUB_RETURN_RELEASE(v, p) \
__atomic_sub_fetch(p, v, __ATOMIC_RELEASE)
#define __ATOMIC_AND(p) __atomic_and_fetch(p, v, __ATOMIC_RELAXED)
#define __ATOMIC_OR(p) __atomic_or_fetch(p, v, __ATOMIC_RELAXED)
#define __ATOMIC_AND(v, p) __atomic_and_fetch(&(p)->counter, v, __ATOMIC_RELAXED)
#define __ATOMIC_OR(v, p) __atomic_or_fetch(&(p)->counter, v, __ATOMIC_RELAXED)
#define xchg(p, v) __atomic_exchange_n(p, v, __ATOMIC_SEQ_CST)
#define xchg_acquire(p, v) __atomic_exchange_n(p, v, __ATOMIC_ACQUIRE)
#define try_cmpxchg(p, old, new) \
__atomic_compare_exchange_n((p), old, new, false, \
__ATOMIC_SEQ_CST, \
__ATOMIC_SEQ_CST)
#define try_cmpxchg_acquire(p, old, new) \
__atomic_compare_exchange_n((p), old, new, false, \
__ATOMIC_ACQUIRE, \
__ATOMIC_RELAXED)
#define cmpxchg(p, old, new) \
({ \
typeof(*(p)) __old = (old); \
@ -91,7 +67,7 @@ typedef struct {
\
__atomic_compare_exchange_n((p), &__old, new, false, \
__ATOMIC_RELEASE, \
__ATOMIC_RELEASE); \
__ATOMIC_RELAXED); \
__old; \
})
@ -101,9 +77,7 @@ typedef struct {
#define smp_rmb() __atomic_thread_fence(__ATOMIC_SEQ_CST)
#define smp_mb() __atomic_thread_fence(__ATOMIC_SEQ_CST)
#define smp_read_barrier_depends()
#endif
#define smp_acquire__after_ctrl_dep() __atomic_thread_fence(__ATOMIC_SEQ_CST)
#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); smp_mb(); } while (0)
#define smp_load_acquire(p) \
@ -170,7 +144,12 @@ static inline i_type a_type##_read_acquire(const a_type##_t *v) \
\
static inline void a_type##_set(a_type##_t *v, i_type i) \
{ \
return __ATOMIC_SET(&v->counter, i); \
__ATOMIC_SET(&v->counter, i); \
} \
\
static inline void a_type##_set_release(a_type##_t *v, i_type i) \
{ \
__ATOMIC_SET_RELEASE(&v->counter, i); \
} \
\
static inline i_type a_type##_add_return(i_type i, a_type##_t *v) \
@ -281,6 +260,11 @@ static inline i_type a_type##_cmpxchg(a_type##_t *v, i_type old, i_type new)\
return cmpxchg(&v->counter, old, new); \
} \
\
static inline bool a_type##_try_cmpxchg(a_type##_t *v, i_type *old, i_type new)\
{ \
return try_cmpxchg(&v->counter, old, new); \
} \
\
static inline i_type a_type##_cmpxchg_acquire(a_type##_t *v, i_type old, i_type new)\
{ \
return cmpxchg_acquire(&v->counter, old, new); \
@ -316,6 +300,7 @@ void atomic64_sub(s64, atomic64_t *);
s64 atomic64_xchg(atomic64_t *, s64);
s64 atomic64_cmpxchg(atomic64_t *, s64, s64);
bool atomic64_try_cmpxchg(atomic64_t *, s64 *, s64);
#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
#define atomic64_inc(v) atomic64_add(1LL, (v))

View File

@ -62,6 +62,29 @@ static inline void bitmap_complement(unsigned long *dst, const unsigned long *sr
dst[k] = ~src[k];
}
static inline bool __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int bits)
{
unsigned int k;
unsigned int lim = bits/BITS_PER_LONG;
unsigned long result = 0;
for (k = 0; k < lim; k++)
result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
if (bits % BITS_PER_LONG)
result |= (dst[k] = bitmap1[k] & ~bitmap2[k] &
BITMAP_LAST_WORD_MASK(bits));
return result != 0;
}
static inline bool bitmap_andnot(unsigned long *dst, const unsigned long *src1,
const unsigned long *src2, unsigned int nbits)
{
if (small_const_nbits(nbits))
return (*dst = *src1 & ~(*src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
return __bitmap_andnot(dst, src1, src2, nbits);
}
static inline void bitmap_zero(unsigned long *dst, int nbits)
{
memset(dst, 0, BITS_TO_LONGS(nbits) * sizeof(unsigned long));

View File

@ -6,9 +6,12 @@
#define __LINUX_BLK_TYPES_H
#include <linux/atomic.h>
#include <linux/backing-dev.h>
#include <linux/types.h>
#include <linux/bvec.h>
#include <linux/kobject.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
struct bio_set;
struct bio;
@ -62,6 +65,8 @@ struct block_device {
struct gendisk * bd_disk;
struct gendisk __bd_disk;
int bd_fd;
struct mutex bd_holder_lock;
};
#define bdev_kobj(_bdev) (&((_bdev)->kobj))

View File

@ -65,7 +65,10 @@ unsigned bdev_logical_block_size(struct block_device *bdev);
sector_t get_capacity(struct gendisk *disk);
struct blk_holder_ops {
void (*mark_dead)(struct block_device *bdev);
void (*mark_dead)(struct block_device *bdev, bool surprise);
void (*sync)(struct block_device *bdev);
int (*freeze)(struct block_device *bdev);
int (*thaw)(struct block_device *bdev);
};
static inline struct block_device *file_bdev(struct file *file)
@ -73,15 +76,19 @@ static inline struct block_device *file_bdev(struct file *file)
return container_of(file->f_inode, struct block_device, __bd_inode);
}
void fput(struct file *);
void bdev_fput(struct file *);
struct file *bdev_file_open_by_path(const char *, blk_mode_t, void *,
const struct blk_holder_ops *);
int lookup_bdev(const char *path, dev_t *);
struct super_block {
void *s_fs_info;
struct rw_semaphore s_umount;
};
static inline void evict_inodes(struct super_block *sb) {}
static inline int sync_filesystem(struct super_block *) { return 0; }
/*
* File types
*

View File

@ -159,6 +159,7 @@ struct closure {
#ifdef CONFIG_DEBUG_CLOSURES
#define CLOSURE_MAGIC_DEAD 0xc054dead
#define CLOSURE_MAGIC_ALIVE 0xc054a11e
#define CLOSURE_MAGIC_STACK 0xc05451cc
unsigned int magic;
struct list_head all;
@ -194,6 +195,18 @@ static inline void closure_sync(struct closure *cl)
__closure_sync(cl);
}
int __closure_sync_timeout(struct closure *cl, unsigned long timeout);
static inline int closure_sync_timeout(struct closure *cl, unsigned long timeout)
{
#ifdef CONFIG_DEBUG_CLOSURES
BUG_ON(closure_nr_remaining(cl) != 1 && !cl->closure_get_happened);
#endif
return cl->closure_get_happened
? __closure_sync_timeout(cl, timeout)
: 0;
}
#ifdef CONFIG_DEBUG_CLOSURES
void closure_debug_create(struct closure *cl);
@ -272,6 +285,21 @@ static inline void closure_get(struct closure *cl)
#endif
}
/**
* closure_get_not_zero
*/
static inline bool closure_get_not_zero(struct closure *cl)
{
unsigned old = atomic_read(&cl->remaining);
do {
if (!(old & CLOSURE_REMAINING_MASK))
return false;
} while (!atomic_try_cmpxchg_acquire(&cl->remaining, &old, old + 1));
return true;
}
/**
* closure_init - Initialize a closure, setting the refcount to 1
* @cl: closure to initialize
@ -296,6 +324,18 @@ static inline void closure_init_stack(struct closure *cl)
{
memset(cl, 0, sizeof(struct closure));
atomic_set(&cl->remaining, CLOSURE_REMAINING_INITIALIZER);
#ifdef CONFIG_DEBUG_CLOSURES
cl->magic = CLOSURE_MAGIC_STACK;
#endif
}
static inline void closure_init_stack_release(struct closure *cl)
{
memset(cl, 0, sizeof(struct closure));
atomic_set_release(&cl->remaining, CLOSURE_REMAINING_INITIALIZER);
#ifdef CONFIG_DEBUG_CLOSURES
cl->magic = CLOSURE_MAGIC_STACK;
#endif
}
/**
@ -343,6 +383,8 @@ do { \
*/
#define closure_return(_cl) continue_at((_cl), NULL, NULL)
void closure_return_sync(struct closure *cl);
/**
* continue_at_nobarrier - jump to another function without barrier
*
@ -412,4 +454,39 @@ do { \
__closure_wait_event(waitlist, _cond); \
} while (0)
#define __closure_wait_event_timeout(waitlist, _cond, _until) \
({ \
struct closure cl; \
long _t; \
\
closure_init_stack(&cl); \
\
while (1) { \
closure_wait(waitlist, &cl); \
if (_cond) { \
_t = max_t(long, 1L, _until - jiffies); \
break; \
} \
_t = max_t(long, 0L, _until - jiffies); \
if (!_t) \
break; \
closure_sync_timeout(&cl, _t); \
} \
closure_wake_up(waitlist); \
closure_sync(&cl); \
_t; \
})
/*
* Returns 0 if timeout expired, remaining time in jiffies (at least 1) if
* condition became true
*/
#define closure_wait_event_timeout(waitlist, _cond, _timeout) \
({ \
unsigned long _until = jiffies + _timeout; \
(_cond) \
? max_t(long, 1L, _until - jiffies) \
: __closure_wait_event_timeout(waitlist, _cond, _until);\
})
#endif /* _LINUX_CLOSURE_H */

View File

@ -67,6 +67,7 @@
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define fallthrough __attribute__((__fallthrough__))
#define __noreturn __attribute__((__noreturn__))
#define __no_kmsan_checks
#ifndef __counted_by
#define __counted_by(nr)

View File

@ -1,7 +1,8 @@
#ifndef _LINUX_CONSOLE_H_
#define _LINUX_CONSOLE_H_
#define console_lock()
#define console_unlock()
#define console_lock() do {} while (0)
#define console_trylock() true
#define console_unlock() do {} while (0)
#endif /* _LINUX_CONSOLE_H */

View File

@ -9,4 +9,9 @@ struct dentry {
struct inode *d_inode;
};
static inline void shrink_dcache_sb(struct super_block *) {}
#define QSTR_INIT(n,l) { { { .len = l } }, .name = n }
#define QSTR(n) (struct qstr)QSTR_INIT(n, strlen(n))
#endif /* __LINUX_DCACHE_H */

20
include/linux/fs_parser.h Normal file
View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Filesystem parameter description and parser
*
* Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _LINUX_FS_PARSER_H
#define _LINUX_FS_PARSER_H
struct constant_table {
const char *name;
int value;
};
extern int lookup_constant(const struct constant_table tbl[], const char *name, int not_found);
extern const struct constant_table bool_names[];
#endif /* _LINUX_FS_PARSER_H */

View File

@ -41,6 +41,7 @@
#include <linux/limits.h>
#include <linux/log2.h>
#include <linux/math.h>
#include <linux/slab.h>
#include <linux/types.h>
struct genradix_root;
@ -48,10 +49,63 @@ struct genradix_root;
#define GENRADIX_NODE_SHIFT 9
#define GENRADIX_NODE_SIZE (1U << GENRADIX_NODE_SHIFT)
#define GENRADIX_ARY (GENRADIX_NODE_SIZE / sizeof(struct genradix_node *))
#define GENRADIX_ARY_SHIFT ilog2(GENRADIX_ARY)
/* depth that's needed for a genradix that can address up to ULONG_MAX: */
#define GENRADIX_MAX_DEPTH \
DIV_ROUND_UP(BITS_PER_LONG - GENRADIX_NODE_SHIFT, GENRADIX_ARY_SHIFT)
#define GENRADIX_DEPTH_MASK \
((unsigned long) (roundup_pow_of_two(GENRADIX_MAX_DEPTH + 1) - 1))
static inline int genradix_depth_shift(unsigned depth)
{
return GENRADIX_NODE_SHIFT + GENRADIX_ARY_SHIFT * depth;
}
/*
* Returns size (of data, in bytes) that a tree of a given depth holds:
*/
static inline size_t genradix_depth_size(unsigned depth)
{
return 1UL << genradix_depth_shift(depth);
}
static inline unsigned genradix_root_to_depth(struct genradix_root *r)
{
return (unsigned long) r & GENRADIX_DEPTH_MASK;
}
static inline struct genradix_node *genradix_root_to_node(struct genradix_root *r)
{
return (void *) ((unsigned long) r & ~GENRADIX_DEPTH_MASK);
}
struct __genradix {
struct genradix_root *root;
};
struct genradix_node {
union {
/* Interior node: */
struct genradix_node *children[GENRADIX_ARY];
/* Leaf: */
u8 data[GENRADIX_NODE_SIZE];
};
};
static inline struct genradix_node *genradix_alloc_node(gfp_t gfp_mask)
{
return kzalloc(GENRADIX_NODE_SIZE, gfp_mask);
}
static inline void genradix_free_node(struct genradix_node *node)
{
kfree(node);
}
/*
* NOTE: currently, sizeof(_type) must not be larger than GENRADIX_NODE_SIZE:
*/
@ -128,6 +182,30 @@ static inline size_t __idx_to_offset(size_t idx, size_t obj_size)
#define __genradix_idx_to_offset(_radix, _idx) \
__idx_to_offset(_idx, __genradix_obj_size(_radix))
static inline void *__genradix_ptr_inlined(struct __genradix *radix, size_t offset)
{
struct genradix_root *r = READ_ONCE(radix->root);
struct genradix_node *n = genradix_root_to_node(r);
unsigned level = genradix_root_to_depth(r);
unsigned shift = genradix_depth_shift(level);
if (unlikely(ilog2(offset) >= genradix_depth_shift(level)))
return NULL;
while (n && shift > GENRADIX_NODE_SHIFT) {
shift -= GENRADIX_ARY_SHIFT;
n = n->children[offset >> shift];
offset &= (1UL << shift) - 1;
}
return n ? &n->data[offset] : NULL;
}
#define genradix_ptr_inlined(_radix, _idx) \
(__genradix_cast(_radix) \
__genradix_ptr_inlined(&(_radix)->tree, \
__genradix_idx_to_offset(_radix, _idx)))
void *__genradix_ptr(struct __genradix *, size_t);
/**
@ -142,7 +220,24 @@ void *__genradix_ptr(struct __genradix *, size_t);
__genradix_ptr(&(_radix)->tree, \
__genradix_idx_to_offset(_radix, _idx)))
void *__genradix_ptr_alloc(struct __genradix *, size_t, gfp_t);
void *__genradix_ptr_alloc(struct __genradix *, size_t,
struct genradix_node **, gfp_t);
#define genradix_ptr_alloc_inlined(_radix, _idx, _gfp) \
(__genradix_cast(_radix) \
(__genradix_ptr_inlined(&(_radix)->tree, \
__genradix_idx_to_offset(_radix, _idx)) ?: \
__genradix_ptr_alloc(&(_radix)->tree, \
__genradix_idx_to_offset(_radix, _idx), \
NULL, _gfp)))
#define genradix_ptr_alloc_preallocated_inlined(_radix, _idx, _new_node, _gfp)\
(__genradix_cast(_radix) \
(__genradix_ptr_inlined(&(_radix)->tree, \
__genradix_idx_to_offset(_radix, _idx)) ?: \
__genradix_ptr_alloc(&(_radix)->tree, \
__genradix_idx_to_offset(_radix, _idx), \
_new_node, _gfp)))
/**
* genradix_ptr_alloc - get a pointer to a genradix entry, allocating it
@ -157,7 +252,13 @@ void *__genradix_ptr_alloc(struct __genradix *, size_t, gfp_t);
(__genradix_cast(_radix) \
__genradix_ptr_alloc(&(_radix)->tree, \
__genradix_idx_to_offset(_radix, _idx), \
_gfp))
NULL, _gfp))
#define genradix_ptr_alloc_preallocated(_radix, _idx, _new_node, _gfp)\
(__genradix_cast(_radix) \
__genradix_ptr_alloc(&(_radix)->tree, \
__genradix_idx_to_offset(_radix, _idx), \
_new_node, _gfp))
struct genradix_iter {
size_t offset;

View File

@ -11,6 +11,8 @@
#include <linux/bug.h>
#include <linux/byteorder.h>
#include <linux/compiler.h>
#include <linux/dcache.h>
#include <linux/kmsan-checks.h>
#include <linux/math.h>
#include <linux/minmax.h>

View File

@ -26,6 +26,7 @@ extern void kmemleak_free_part(const void *ptr, size_t size) __ref;
extern void kmemleak_free_percpu(const void __percpu *ptr) __ref;
extern void kmemleak_update_trace(const void *ptr) __ref;
extern void kmemleak_not_leak(const void *ptr) __ref;
extern void kmemleak_transient_leak(const void *ptr) __ref;
extern void kmemleak_ignore(const void *ptr) __ref;
extern void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) __ref;
extern void kmemleak_no_scan(const void *ptr) __ref;
@ -93,6 +94,9 @@ static inline void kmemleak_update_trace(const void *ptr)
static inline void kmemleak_not_leak(const void *ptr)
{
}
static inline void kmemleak_transient_leak(const void *ptr)
{
}
static inline void kmemleak_ignore(const void *ptr)
{
}

View File

@ -0,0 +1,98 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KMSAN checks to be used for one-off annotations in subsystems.
*
* Copyright (C) 2017-2022 Google LLC
* Author: Alexander Potapenko <glider@google.com>
*
*/
#ifndef _LINUX_KMSAN_CHECKS_H
#define _LINUX_KMSAN_CHECKS_H
#include <linux/types.h>
#ifdef CONFIG_KMSAN
/**
* kmsan_poison_memory() - Mark the memory range as uninitialized.
* @address: address to start with.
* @size: size of buffer to poison.
* @flags: GFP flags for allocations done by this function.
*
* Until other data is written to this range, KMSAN will treat it as
* uninitialized. Error reports for this memory will reference the call site of
* kmsan_poison_memory() as origin.
*/
void kmsan_poison_memory(const void *address, size_t size, gfp_t flags);
/**
* kmsan_unpoison_memory() - Mark the memory range as initialized.
* @address: address to start with.
* @size: size of buffer to unpoison.
*
* Until other data is written to this range, KMSAN will treat it as
* initialized.
*/
void kmsan_unpoison_memory(const void *address, size_t size);
/**
* kmsan_check_memory() - Check the memory range for being initialized.
* @address: address to start with.
* @size: size of buffer to check.
*
* If any piece of the given range is marked as uninitialized, KMSAN will report
* an error.
*/
void kmsan_check_memory(const void *address, size_t size);
/**
* kmsan_copy_to_user() - Notify KMSAN about a data transfer to userspace.
* @to: destination address in the userspace.
* @from: source address in the kernel.
* @to_copy: number of bytes to copy.
* @left: number of bytes not copied.
*
* If this is a real userspace data transfer, KMSAN checks the bytes that were
* actually copied to ensure there was no information leak. If @to belongs to
* the kernel space (which is possible for compat syscalls), KMSAN just copies
* the metadata.
*/
void kmsan_copy_to_user(void __user *to, const void *from, size_t to_copy,
size_t left);
/**
* kmsan_memmove() - Notify KMSAN about a data copy within kernel.
* @to: destination address in the kernel.
* @from: source address in the kernel.
* @size: number of bytes to copy.
*
* Invoked after non-instrumented version (e.g. implemented using assembly
* code) of memmove()/memcpy() is called, in order to copy KMSAN's metadata.
*/
void kmsan_memmove(void *to, const void *from, size_t to_copy);
#else
static inline void kmsan_poison_memory(const void *address, size_t size,
gfp_t flags)
{
}
static inline void kmsan_unpoison_memory(const void *address, size_t size)
{
}
static inline void kmsan_check_memory(const void *address, size_t size)
{
}
static inline void kmsan_copy_to_user(void __user *to, const void *from,
size_t to_copy, size_t left)
{
}
static inline void kmsan_memmove(void *to, const void *from, size_t to_copy)
{
}
#endif
#endif /* _LINUX_KMSAN_CHECKS_H */

View File

@ -20,6 +20,7 @@
#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/workqueue.h>

View File

@ -5,6 +5,8 @@ struct lock_class_key {};
struct task_struct;
# define lock_acquire(l, s, t, r, c, n, i) do { } while (0)
# define lock_acquire_exclusive(...) do { } while (0)
# define lockdep_set_notrack_class(...) do { } while (0)
# define lock_release(l, i) do { } while (0)
# define lock_set_class(l, n, k, s, i) do { } while (0)
# define lock_set_subclass(l, s, i) do { } while (0)

View File

@ -82,4 +82,71 @@ static inline s64 div_s64(s64 dividend, s32 divisor)
return div_s64_rem(dividend, divisor, &remainder);
}
#ifndef mul_u32_u32
/*
* Many a GCC version messes this up and generates a 64x64 mult :-(
*/
static inline u64 mul_u32_u32(u32 a, u32 b)
{
return (u64)a * b;
}
#endif
#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
#ifndef mul_u64_u64_shr
static __always_inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
{
return (u64)(((unsigned __int128)a * mul) >> shift);
}
#endif /* mul_u64_u64_shr */
#else
#ifndef mul_u64_u64_shr
static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
{
union {
u64 ll;
struct {
#ifdef __BIG_ENDIAN
u32 high, low;
#else
u32 low, high;
#endif
} l;
} rl, rm, rn, rh, a0, b0;
u64 c;
a0.ll = a;
b0.ll = b;
rl.ll = mul_u32_u32(a0.l.low, b0.l.low);
rm.ll = mul_u32_u32(a0.l.low, b0.l.high);
rn.ll = mul_u32_u32(a0.l.high, b0.l.low);
rh.ll = mul_u32_u32(a0.l.high, b0.l.high);
/*
* Each of these lines computes a 64-bit intermediate result into "c",
* starting at bits 32-95. The low 32-bits go into the result of the
* multiplication, the high 32-bits are carried into the next step.
*/
rl.l.high = c = (u64)rl.l.high + rm.l.low + rn.l.low;
rh.l.low = c = (c >> 32) + rm.l.high + rn.l.high + rh.l.low;
rh.l.high = (c >> 32) + rh.l.high;
/*
* The 128-bit result of the multiplication is in rl.ll and rh.ll,
* shift it right and throw away the high part of the result.
*/
if (shift == 0)
return rl.ll;
if (shift < 64)
return (rl.ll >> shift) | (rh.ll << (64 - shift));
return rh.ll >> (shift & 63);
}
#endif /* mul_u64_u64_shr */
#endif
#endif /* _LINUX_MATH64_H */

457
include/linux/min_heap.h Normal file
View File

@ -0,0 +1,457 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_MIN_HEAP_H
#define _LINUX_MIN_HEAP_H
#include <linux/bug.h>
#include <linux/string.h>
#include <linux/types.h>
/**
* Data structure to hold a min-heap.
* @nr: Number of elements currently in the heap.
* @size: Maximum number of elements that can be held in current storage.
* @data: Pointer to the start of array holding the heap elements.
* @preallocated: Start of the static preallocated array holding the heap elements.
*/
#define MIN_HEAP_PREALLOCATED(_type, _name, _nr) \
struct _name { \
size_t nr; \
size_t size; \
_type *data; \
_type preallocated[_nr]; \
}
#define DEFINE_MIN_HEAP(_type, _name) MIN_HEAP_PREALLOCATED(_type, _name, 0)
typedef DEFINE_MIN_HEAP(char, min_heap_char) min_heap_char;
#define __minheap_cast(_heap) (typeof((_heap)->data[0]) *)
#define __minheap_obj_size(_heap) sizeof((_heap)->data[0])
/**
* struct min_heap_callbacks - Data/functions to customise the min_heap.
* @less: Partial order function for this heap.
* @swp: Swap elements function.
*/
struct min_heap_callbacks {
bool (*less)(const void *lhs, const void *rhs, void *args);
void (*swp)(void *lhs, void *rhs, void *args);
};
/**
* is_aligned - is this pointer & size okay for word-wide copying?
* @base: pointer to data
* @size: size of each element
* @align: required alignment (typically 4 or 8)
*
* Returns true if elements can be copied using word loads and stores.
* The size must be a multiple of the alignment, and the base address must
* be if we do not have CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS.
*
* For some reason, gcc doesn't know to optimize "if (a & mask || b & mask)"
* to "if ((a | b) & mask)", so we do that by hand.
*/
__attribute_const__ __always_inline
static bool is_aligned(const void *base, size_t size, unsigned char align)
{
unsigned char lsbits = (unsigned char)size;
(void)base;
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
lsbits |= (unsigned char)(uintptr_t)base;
#endif
return (lsbits & (align - 1)) == 0;
}
/**
* swap_words_32 - swap two elements in 32-bit chunks
* @a: pointer to the first element to swap
* @b: pointer to the second element to swap
* @n: element size (must be a multiple of 4)
*
* Exchange the two objects in memory. This exploits base+index addressing,
* which basically all CPUs have, to minimize loop overhead computations.
*
* For some reason, on x86 gcc 7.3.0 adds a redundant test of n at the
* bottom of the loop, even though the zero flag is still valid from the
* subtract (since the intervening mov instructions don't alter the flags).
* Gcc 8.1.0 doesn't have that problem.
*/
static __always_inline
void swap_words_32(void *a, void *b, size_t n)
{
do {
u32 t = *(u32 *)(a + (n -= 4));
*(u32 *)(a + n) = *(u32 *)(b + n);
*(u32 *)(b + n) = t;
} while (n);
}
/**
* swap_words_64 - swap two elements in 64-bit chunks
* @a: pointer to the first element to swap
* @b: pointer to the second element to swap
* @n: element size (must be a multiple of 8)
*
* Exchange the two objects in memory. This exploits base+index
* addressing, which basically all CPUs have, to minimize loop overhead
* computations.
*
* We'd like to use 64-bit loads if possible. If they're not, emulating
* one requires base+index+4 addressing which x86 has but most other
* processors do not. If CONFIG_64BIT, we definitely have 64-bit loads,
* but it's possible to have 64-bit loads without 64-bit pointers (e.g.
* x32 ABI). Are there any cases the kernel needs to worry about?
*/
static __always_inline
void swap_words_64(void *a, void *b, size_t n)
{
do {
#ifdef CONFIG_64BIT
u64 t = *(u64 *)(a + (n -= 8));
*(u64 *)(a + n) = *(u64 *)(b + n);
*(u64 *)(b + n) = t;
#else
/* Use two 32-bit transfers to avoid base+index+4 addressing */
u32 t = *(u32 *)(a + (n -= 4));
*(u32 *)(a + n) = *(u32 *)(b + n);
*(u32 *)(b + n) = t;
t = *(u32 *)(a + (n -= 4));
*(u32 *)(a + n) = *(u32 *)(b + n);
*(u32 *)(b + n) = t;
#endif
} while (n);
}
/**
* swap_bytes - swap two elements a byte at a time
* @a: pointer to the first element to swap
* @b: pointer to the second element to swap
* @n: element size
*
* This is the fallback if alignment doesn't allow using larger chunks.
*/
static __always_inline
void swap_bytes(void *a, void *b, size_t n)
{
do {
char t = ((char *)a)[--n];
((char *)a)[n] = ((char *)b)[n];
((char *)b)[n] = t;
} while (n);
}
/*
* The values are arbitrary as long as they can't be confused with
* a pointer, but small integers make for the smallest compare
* instructions.
*/
#define SWAP_WORDS_64 ((void (*)(void *, void *, void *))0)
#define SWAP_WORDS_32 ((void (*)(void *, void *, void *))1)
#define SWAP_BYTES ((void (*)(void *, void *, void *))2)
/*
* Selects the appropriate swap function based on the element size.
*/
static __always_inline
void *select_swap_func(const void *base, size_t size)
{
if (is_aligned(base, size, 8))
return SWAP_WORDS_64;
else if (is_aligned(base, size, 4))
return SWAP_WORDS_32;
else
return SWAP_BYTES;
}
static __always_inline
void do_swap(void *a, void *b, size_t size, void (*swap_func)(void *lhs, void *rhs, void *args),
void *priv)
{
if (swap_func == SWAP_WORDS_64)
swap_words_64(a, b, size);
else if (swap_func == SWAP_WORDS_32)
swap_words_32(a, b, size);
else if (swap_func == SWAP_BYTES)
swap_bytes(a, b, size);
else
swap_func(a, b, priv);
}
/**
* parent - given the offset of the child, find the offset of the parent.
* @i: the offset of the heap element whose parent is sought. Non-zero.
* @lsbit: a precomputed 1-bit mask, equal to "size & -size"
* @size: size of each element
*
* In terms of array indexes, the parent of element j = @i/@size is simply
* (j-1)/2. But when working in byte offsets, we can't use implicit
* truncation of integer divides.
*
* Fortunately, we only need one bit of the quotient, not the full divide.
* @size has a least significant bit. That bit will be clear if @i is
* an even multiple of @size, and set if it's an odd multiple.
*
* Logically, we're doing "if (i & lsbit) i -= size;", but since the
* branch is unpredictable, it's done with a bit of clever branch-free
* code instead.
*/
__attribute_const__ __always_inline
static size_t parent(size_t i, unsigned int lsbit, size_t size)
{
i -= size;
i -= size & -(i & lsbit);
return i / 2;
}
/* Initialize a min-heap. */
static __always_inline
void __min_heap_init_inline(min_heap_char *heap, void *data, int size)
{
heap->nr = 0;
heap->size = size;
if (data)
heap->data = data;
else
heap->data = heap->preallocated;
}
#define min_heap_init_inline(_heap, _data, _size) \
__min_heap_init_inline((min_heap_char *)_heap, _data, _size)
/* Get the minimum element from the heap. */
static __always_inline
void *__min_heap_peek_inline(struct min_heap_char *heap)
{
return heap->nr ? heap->data : NULL;
}
#define min_heap_peek_inline(_heap) \
(__minheap_cast(_heap) __min_heap_peek_inline((min_heap_char *)_heap))
/* Check if the heap is full. */
static __always_inline
bool __min_heap_full_inline(min_heap_char *heap)
{
return heap->nr == heap->size;
}
#define min_heap_full_inline(_heap) \
__min_heap_full_inline((min_heap_char *)_heap)
/* Sift the element at pos down the heap. */
static __always_inline
void __min_heap_sift_down_inline(min_heap_char *heap, int pos, size_t elem_size,
const struct min_heap_callbacks *func, void *args)
{
const unsigned long lsbit = elem_size & -elem_size;
void *data = heap->data;
void (*swp)(void *lhs, void *rhs, void *args) = func->swp;
/* pre-scale counters for performance */
size_t a = pos * elem_size;
size_t b, c, d;
size_t n = heap->nr * elem_size;
if (!swp)
swp = select_swap_func(data, elem_size);
/* Find the sift-down path all the way to the leaves. */
for (b = a; c = 2 * b + elem_size, (d = c + elem_size) < n;)
b = func->less(data + c, data + d, args) ? c : d;
/* Special case for the last leaf with no sibling. */
if (d == n)
b = c;
/* Backtrack to the correct location. */
while (b != a && func->less(data + a, data + b, args))
b = parent(b, lsbit, elem_size);
/* Shift the element into its correct place. */
c = b;
while (b != a) {
b = parent(b, lsbit, elem_size);
do_swap(data + b, data + c, elem_size, swp, args);
}
}
#define min_heap_sift_down_inline(_heap, _pos, _func, _args) \
__min_heap_sift_down_inline((min_heap_char *)_heap, _pos, __minheap_obj_size(_heap), \
_func, _args)
/* Sift up ith element from the heap, O(log2(nr)). */
static __always_inline
void __min_heap_sift_up_inline(min_heap_char *heap, size_t elem_size, size_t idx,
const struct min_heap_callbacks *func, void *args)
{
const unsigned long lsbit = elem_size & -elem_size;
void *data = heap->data;
void (*swp)(void *lhs, void *rhs, void *args) = func->swp;
/* pre-scale counters for performance */
size_t a = idx * elem_size, b;
if (!swp)
swp = select_swap_func(data, elem_size);
while (a) {
b = parent(a, lsbit, elem_size);
if (func->less(data + b, data + a, args))
break;
do_swap(data + a, data + b, elem_size, swp, args);
a = b;
}
}
#define min_heap_sift_up_inline(_heap, _idx, _func, _args) \
__min_heap_sift_up_inline((min_heap_char *)_heap, __minheap_obj_size(_heap), _idx, \
_func, _args)
/* Floyd's approach to heapification that is O(nr). */
static __always_inline
void __min_heapify_all_inline(min_heap_char *heap, size_t elem_size,
const struct min_heap_callbacks *func, void *args)
{
int i;
for (i = heap->nr / 2 - 1; i >= 0; i--)
__min_heap_sift_down_inline(heap, i, elem_size, func, args);
}
#define min_heapify_all_inline(_heap, _func, _args) \
__min_heapify_all_inline((min_heap_char *)_heap, __minheap_obj_size(_heap), _func, _args)
/* Remove minimum element from the heap, O(log2(nr)). */
static __always_inline
bool __min_heap_pop_inline(min_heap_char *heap, size_t elem_size,
const struct min_heap_callbacks *func, void *args)
{
void *data = heap->data;
if (WARN_ONCE(heap->nr <= 0, "Popping an empty heap"))
return false;
/* Place last element at the root (position 0) and then sift down. */
heap->nr--;
memcpy(data, data + (heap->nr * elem_size), elem_size);
__min_heap_sift_down_inline(heap, 0, elem_size, func, args);
return true;
}
#define min_heap_pop_inline(_heap, _func, _args) \
__min_heap_pop_inline((min_heap_char *)_heap, __minheap_obj_size(_heap), _func, _args)
/*
* Remove the minimum element and then push the given element. The
* implementation performs 1 sift (O(log2(nr))) and is therefore more
* efficient than a pop followed by a push that does 2.
*/
static __always_inline
void __min_heap_pop_push_inline(min_heap_char *heap, const void *element, size_t elem_size,
const struct min_heap_callbacks *func, void *args)
{
memcpy(heap->data, element, elem_size);
__min_heap_sift_down_inline(heap, 0, elem_size, func, args);
}
#define min_heap_pop_push_inline(_heap, _element, _func, _args) \
__min_heap_pop_push_inline((min_heap_char *)_heap, _element, __minheap_obj_size(_heap), \
_func, _args)
/* Push an element on to the heap, O(log2(nr)). */
static __always_inline
bool __min_heap_push_inline(min_heap_char *heap, const void *element, size_t elem_size,
const struct min_heap_callbacks *func, void *args)
{
void *data = heap->data;
int pos;
if (WARN_ONCE(heap->nr >= heap->size, "Pushing on a full heap"))
return false;
/* Place at the end of data. */
pos = heap->nr;
memcpy(data + (pos * elem_size), element, elem_size);
heap->nr++;
/* Sift child at pos up. */
__min_heap_sift_up_inline(heap, elem_size, pos, func, args);
return true;
}
#define min_heap_push_inline(_heap, _element, _func, _args) \
__min_heap_push_inline((min_heap_char *)_heap, _element, __minheap_obj_size(_heap), \
_func, _args)
/* Remove ith element from the heap, O(log2(nr)). */
static __always_inline
bool __min_heap_del_inline(min_heap_char *heap, size_t elem_size, size_t idx,
const struct min_heap_callbacks *func, void *args)
{
void *data = heap->data;
void (*swp)(void *lhs, void *rhs, void *args) = func->swp;
if (WARN_ONCE(heap->nr <= 0, "Popping an empty heap"))
return false;
if (!swp)
swp = select_swap_func(data, elem_size);
/* Place last element at the root (position 0) and then sift down. */
heap->nr--;
if (idx == heap->nr)
return true;
do_swap(data + (idx * elem_size), data + (heap->nr * elem_size), elem_size, swp, args);
__min_heap_sift_up_inline(heap, elem_size, idx, func, args);
__min_heap_sift_down_inline(heap, idx, elem_size, func, args);
return true;
}
#define min_heap_del_inline(_heap, _idx, _func, _args) \
__min_heap_del_inline((min_heap_char *)_heap, __minheap_obj_size(_heap), _idx, \
_func, _args)
void __min_heap_init(min_heap_char *heap, void *data, int size);
void *__min_heap_peek(struct min_heap_char *heap);
bool __min_heap_full(min_heap_char *heap);
void __min_heap_sift_down(min_heap_char *heap, int pos, size_t elem_size,
const struct min_heap_callbacks *func, void *args);
void __min_heap_sift_up(min_heap_char *heap, size_t elem_size, size_t idx,
const struct min_heap_callbacks *func, void *args);
void __min_heapify_all(min_heap_char *heap, size_t elem_size,
const struct min_heap_callbacks *func, void *args);
bool __min_heap_pop(min_heap_char *heap, size_t elem_size,
const struct min_heap_callbacks *func, void *args);
void __min_heap_pop_push(min_heap_char *heap, const void *element, size_t elem_size,
const struct min_heap_callbacks *func, void *args);
bool __min_heap_push(min_heap_char *heap, const void *element, size_t elem_size,
const struct min_heap_callbacks *func, void *args);
bool __min_heap_del(min_heap_char *heap, size_t elem_size, size_t idx,
const struct min_heap_callbacks *func, void *args);
#define min_heap_init(_heap, _data, _size) \
__min_heap_init((min_heap_char *)_heap, _data, _size)
#define min_heap_peek(_heap) \
(__minheap_cast(_heap) __min_heap_peek((min_heap_char *)_heap))
#define min_heap_full(_heap) \
__min_heap_full((min_heap_char *)_heap)
#define min_heap_sift_down(_heap, _pos, _func, _args) \
__min_heap_sift_down((min_heap_char *)_heap, _pos, __minheap_obj_size(_heap), _func, _args)
#define min_heap_sift_up(_heap, _idx, _func, _args) \
__min_heap_sift_up((min_heap_char *)_heap, __minheap_obj_size(_heap), _idx, _func, _args)
#define min_heapify_all(_heap, _func, _args) \
__min_heapify_all((min_heap_char *)_heap, __minheap_obj_size(_heap), _func, _args)
#define min_heap_pop(_heap, _func, _args) \
__min_heap_pop((min_heap_char *)_heap, __minheap_obj_size(_heap), _func, _args)
#define min_heap_pop_push(_heap, _element, _func, _args) \
__min_heap_pop_push((min_heap_char *)_heap, _element, __minheap_obj_size(_heap), \
_func, _args)
#define min_heap_push(_heap, _element, _func, _args) \
__min_heap_push((min_heap_char *)_heap, _element, __minheap_obj_size(_heap), _func, _args)
#define min_heap_del(_heap, _idx, _func, _args) \
__min_heap_del((min_heap_char *)_heap, __minheap_obj_size(_heap), _idx, _func, _args)
#endif /* _LINUX_MIN_HEAP_H */

View File

@ -3,6 +3,8 @@
#define _TOOLS_LINUX_MM_H
#include <sys/syscall.h>
#include <unistd.h>
#include <linux/bug.h>
#include <linux/types.h>
struct sysinfo {

View File

@ -38,11 +38,8 @@
* Magic nums for obj red zoning.
* Placed in the first word before and the first word after an obj.
*/
#define RED_INACTIVE 0x09F911029D74E35BULL /* when obj is inactive */
#define RED_ACTIVE 0xD84156C5635688C0ULL /* when obj is active */
#define SLUB_RED_INACTIVE 0xbb
#define SLUB_RED_ACTIVE 0xcc
#define SLUB_RED_INACTIVE 0xbb /* when obj is inactive */
#define SLUB_RED_ACTIVE 0xcc /* when obj is active */
/* ...and for poisoning */
#define POISON_INUSE 0x5a /* for use-uninitialised poisoning */
@ -52,12 +49,6 @@
/********** arch/$ARCH/mm/init.c **********/
#define POISON_FREE_INITMEM 0xcc
/********** arch/ia64/hp/common/sba_iommu.c **********/
/*
* arch/ia64/hp/common/sba_iommu.c uses a 16-byte poison string with a
* value of "SBAIOMMU POISON\0" for spill-over poisoning.
*/
/********** fs/jbd/journal.c **********/
#define JBD_POISON_FREE 0x5b
#define JBD2_POISON_FREE 0x5c

View File

@ -9,7 +9,9 @@
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/math64.h>
#ifdef SYS_getrandom
static inline int getrandom(void *buf, size_t buflen, unsigned int flags)
@ -67,4 +69,24 @@ static inline u32 get_random_u32_below(u32 ceil)
}
}
static inline u32 __get_random_u32_below(u32 ceil)
{
return get_random_u32_below(ceil);
}
static inline u64 get_random_u64_below(u64 ceil)
{
if (ceil <= 1)
return 0;
if (ceil <= U32_MAX)
return get_random_u32_below(ceil);
for (;;) {
u64 rand = get_random_u64();
u64 mult = ceil * rand;
if (likely(mult >= -ceil % ceil))
return mul_u64_u64_shr(ceil, rand, 64);
}
}
#endif /* _LINUX_RANDOM_H */

View File

@ -60,10 +60,13 @@
#define PF_FROZEN 0x00010000 /* frozen for system suspend */
#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
#define PF_KSWAPD 0x00040000 /* I am kswapd */
#define PF_MEMALLOC_NOFS 0x00040000 /* All allocations inherit GFP_NOFS. See memalloc_nfs_save() */
#define PF_MEMALLOC_NOIO 0x00080000 /* Allocating memory without IO involved */
#define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */
#define PF_KTHREAD 0x00200000 /* I am a kernel thread */
#define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */
#define PF_MEMALLOC_NORECLAIM 0x00800000 /* All allocation requests will clear __GFP_DIRECT_RECLAIM */
#define PF_MEMALLOC_NOWARN 0x01000000 /* All allocation requests will inherit __GFP_NOWARN */
#define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */
#define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */
#define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */
@ -94,6 +97,11 @@ struct task_struct {
struct signal_struct {
struct rw_semaphore exec_update_lock;
} *signal, _signal;
struct {
u64 sum_exec_runtime;
u64 exec_start;
} se;
};
extern __thread struct task_struct *current;
@ -176,6 +184,8 @@ static inline void ktime_get_coarse_real_ts64(struct timespec64 *ts)
#define current_kernel_time64() current_kernel_time()
#define CURRENT_TIME (current_kernel_time())
#define sched_annotate_sleep() do {} while (0)
static inline unsigned int stack_trace_save_tsk(struct task_struct *task,
unsigned long *store, unsigned int size,
unsigned int skipnr)

View File

@ -4,28 +4,123 @@
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_MEMALLOC_NOFS 0x00040000 /* All allocation requests will inherit GFP_NOFS */
/**
* memalloc_flags_save - Add a PF_* flag to current->flags, save old value
*
* This allows PF_* flags to be conveniently added, irrespective of current
* value, and then the old version restored with memalloc_flags_restore().
*/
static inline unsigned memalloc_flags_save(unsigned flags)
{
unsigned oldflags = ~current->flags & flags;
current->flags |= flags;
return oldflags;
}
static inline void memalloc_flags_restore(unsigned flags)
{
current->flags &= ~flags;
}
/**
* memalloc_noio_save - Marks implicit GFP_NOIO allocation scope.
*
* This functions marks the beginning of the GFP_NOIO allocation scope.
* All further allocations will implicitly drop __GFP_IO flag and so
* they are safe for the IO critical section from the allocation recursion
* point of view. Use memalloc_noio_restore to end the scope with flags
* returned by this function.
*
* Context: This function is safe to be used from any context.
* Return: The saved flags to be passed to memalloc_noio_restore.
*/
static inline unsigned int memalloc_noio_save(void)
{
return memalloc_flags_save(PF_MEMALLOC_NOIO);
}
/**
* memalloc_noio_restore - Ends the implicit GFP_NOIO scope.
* @flags: Flags to restore.
*
* Ends the implicit GFP_NOIO scope started by memalloc_noio_save function.
* Always make sure that the given flags is the return value from the
* pairing memalloc_noio_save call.
*/
static inline void memalloc_noio_restore(unsigned int flags)
{
memalloc_flags_restore(flags);
}
/**
* memalloc_nofs_save - Marks implicit GFP_NOFS allocation scope.
*
* This functions marks the beginning of the GFP_NOFS allocation scope.
* All further allocations will implicitly drop __GFP_FS flag and so
* they are safe for the FS critical section from the allocation recursion
* point of view. Use memalloc_nofs_restore to end the scope with flags
* returned by this function.
*
* Context: This function is safe to be used from any context.
* Return: The saved flags to be passed to memalloc_nofs_restore.
*/
static inline unsigned int memalloc_nofs_save(void)
{
unsigned int flags = current->flags & PF_MEMALLOC_NOFS;
current->flags |= PF_MEMALLOC_NOFS;
return flags;
return memalloc_flags_save(PF_MEMALLOC_NOFS);
}
/**
* memalloc_nofs_restore - Ends the implicit GFP_NOFS scope.
* @flags: Flags to restore.
*
* Ends the implicit GFP_NOFS scope started by memalloc_nofs_save function.
* Always make sure that the given flags is the return value from the
* pairing memalloc_nofs_save call.
*/
static inline void memalloc_nofs_restore(unsigned int flags)
{
current->flags = (current->flags & ~PF_MEMALLOC_NOFS) | flags;
memalloc_flags_restore(flags);
}
/**
* memalloc_noreclaim_save - Marks implicit __GFP_MEMALLOC scope.
*
* This function marks the beginning of the __GFP_MEMALLOC allocation scope.
* All further allocations will implicitly add the __GFP_MEMALLOC flag, which
* prevents entering reclaim and allows access to all memory reserves. This
* should only be used when the caller guarantees the allocation will allow more
* memory to be freed very shortly, i.e. it needs to allocate some memory in
* the process of freeing memory, and cannot reclaim due to potential recursion.
*
* Users of this scope have to be extremely careful to not deplete the reserves
* completely and implement a throttling mechanism which controls the
* consumption of the reserve based on the amount of freed memory. Usage of a
* pre-allocated pool (e.g. mempool) should be always considered before using
* this scope.
*
* Individual allocations under the scope can opt out using __GFP_NOMEMALLOC
*
* Context: This function should not be used in an interrupt context as that one
* does not give PF_MEMALLOC access to reserves.
* See __gfp_pfmemalloc_flags().
* Return: The saved flags to be passed to memalloc_noreclaim_restore.
*/
static inline unsigned int memalloc_noreclaim_save(void)
{
unsigned int flags = current->flags & PF_MEMALLOC;
current->flags |= PF_MEMALLOC;
return flags;
return memalloc_flags_save(PF_MEMALLOC);
}
/**
* memalloc_noreclaim_restore - Ends the implicit __GFP_MEMALLOC scope.
* @flags: Flags to restore.
*
* Ends the implicit __GFP_MEMALLOC scope started by memalloc_noreclaim_save
* function. Always make sure that the given flags is the return value from the
* pairing memalloc_noreclaim_save call.
*/
static inline void memalloc_noreclaim_restore(unsigned int flags)
{
current->flags = (current->flags & ~PF_MEMALLOC) | flags;
memalloc_flags_restore(flags);
}
#endif /* _LINUX_SCHED_MM_H */

View File

@ -0,0 +1,6 @@
#ifndef __TOOLS_LINUX_SCHED_SYSCTL_H
#define __TOOLS_LINUX_SCHED_SYSCTL_H
#define sysctl_hung_task_timeout_secs (HZ * 10)
#endif /* __TOOLS_LINUX_SCHED_SYSCTL_H */

View File

@ -18,8 +18,11 @@
#define alloc_hooks(_do, ...) _do
#define ARCH_KMALLOC_MINALIGN 16
#define ARCH_SLAB_MINALIGN 16
#define KMALLOC_MAX_SIZE SIZE_MAX
#define MAX_PAGE_ORDER 10
static inline size_t kmalloc_size_roundup(size_t s)
{
return roundup_pow_of_two(s);
@ -100,12 +103,17 @@ static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
((size) != 0 && (n) > SIZE_MAX / (size) \
? NULL : kmalloc((n) * (size), flags))
#define kvcalloc(n, size, flags) kvmalloc_array(n, size, flags|__GFP_ZERO)
#define kvmalloc_array_noprof(...) kvmalloc_array(__VA_ARGS__)
#define kcalloc(n, size, flags) kmalloc_array(n, size, flags|__GFP_ZERO)
#define kfree(p) free(p)
#define kzfree(p) free(p)
#define kfree(p) free((void *) p)
#define kzfree(p) free((void *) p)
#define kvmalloc(size, flags) kmalloc(size, flags)
#define kvmalloc_noprof(size, flags) kmalloc(size, flags)
#define kvzalloc(size, flags) kzalloc(size, flags)
#define kvfree(p) kfree(p)
@ -269,6 +277,8 @@ static inline void *vmalloc(unsigned long size)
return __vmalloc(size, GFP_KERNEL);
}
#define vmalloc_noprof(...) vmalloc(__VA_ARGS__)
static inline void *vzalloc(unsigned long size)
{
return __vmalloc(size, GFP_KERNEL|__GFP_ZERO);

View File

@ -1,6 +1,17 @@
#ifndef __TOOLS_LINUX_SRCU_H
#define __TOOLS_LINUX_SRCU_H
#include <linux/rcupdate.h>
#define NUM_ACTIVE_RCU_POLL_OLDSTATE 2
typedef void (*rcu_callback_t)(struct rcu_head *head);
static inline struct urcu_gp_poll_state get_state_synchronize_rcu()
{
return start_poll_synchronize_rcu();
}
struct srcu_struct {
};
@ -11,18 +22,33 @@ static inline int srcu_read_lock(struct srcu_struct *ssp)
return 0;
}
static inline bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)
static inline bool poll_state_synchronize_srcu(struct srcu_struct *ssp, struct urcu_gp_poll_state cookie)
{
return false;
return poll_state_synchronize_rcu(cookie);
}
static inline unsigned long start_poll_synchronize_srcu(struct srcu_struct *ssp)
static inline struct urcu_gp_poll_state start_poll_synchronize_srcu(struct srcu_struct *ssp)
{
return 0;
return start_poll_synchronize_rcu();
}
static inline struct urcu_gp_poll_state get_state_synchronize_srcu(struct srcu_struct *ssp)
{
return get_state_synchronize_rcu();
}
static inline void synchronize_srcu_expedited(struct srcu_struct *ssp) {}
static inline void srcu_barrier(struct srcu_struct *ssp) {}
static inline void cleanup_srcu_struct(struct srcu_struct *ssp) {}
static inline void call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
rcu_callback_t func)
{
call_rcu(rhp, func);
}
static inline int init_srcu_struct(struct srcu_struct *ssp)
{
return 0;

View File

@ -10,6 +10,7 @@ extern ssize_t strscpy(char *dest, const char *src, size_t count);
extern char *strim(char *);
extern void memzero_explicit(void *, size_t);
int match_string(const char * const *, size_t, const char *);
extern void * memscan(void *,int, size_t);
#define kstrndup(s, n, gfp) strndup(s, n)
#define kstrdup(s, gfp) strdup(s)

View File

@ -0,0 +1,85 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_STRING_CHOICES_H_
#define _LINUX_STRING_CHOICES_H_
/*
* Here provide a series of helpers in the str_$TRUE_$FALSE format (you can
* also expand some helpers as needed), where $TRUE and $FALSE are their
* corresponding literal strings. These helpers can be used in the printing
* and also in other places where constant strings are required. Using these
* helpers offers the following benefits:
* 1) Reducing the hardcoding of strings, which makes the code more elegant
* through these simple literal-meaning helpers.
* 2) Unifying the output, which prevents the same string from being printed
* in various forms, such as enable/disable, enabled/disabled, en/dis.
* 3) Deduping by the linker, which results in a smaller binary file.
*/
#include <linux/types.h>
static inline const char *str_enable_disable(bool v)
{
return v ? "enable" : "disable";
}
#define str_disable_enable(v) str_enable_disable(!(v))
static inline const char *str_enabled_disabled(bool v)
{
return v ? "enabled" : "disabled";
}
#define str_disabled_enabled(v) str_enabled_disabled(!(v))
static inline const char *str_hi_lo(bool v)
{
return v ? "hi" : "lo";
}
#define str_lo_hi(v) str_hi_lo(!(v))
static inline const char *str_high_low(bool v)
{
return v ? "high" : "low";
}
#define str_low_high(v) str_high_low(!(v))
static inline const char *str_read_write(bool v)
{
return v ? "read" : "write";
}
#define str_write_read(v) str_read_write(!(v))
static inline const char *str_on_off(bool v)
{
return v ? "on" : "off";
}
#define str_off_on(v) str_on_off(!(v))
static inline const char *str_yes_no(bool v)
{
return v ? "yes" : "no";
}
#define str_no_yes(v) str_yes_no(!(v))
static inline const char *str_up_down(bool v)
{
return v ? "up" : "down";
}
#define str_down_up(v) str_up_down(!(v))
static inline const char *str_true_false(bool v)
{
return v ? "true" : "false";
}
#define str_false_true(v) str_true_false(!(v))
/**
* str_plural - Return the simple pluralization based on English counts
* @num: Number used for deciding pluralization
*
* If @num is 1, returns empty string, otherwise returns "s".
*/
static inline const char *str_plural(size_t num)
{
return num == 1 ? "" : "s";
}
#endif

7
include/linux/swap.h Normal file
View File

@ -0,0 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_SWAP_H
#define _LINUX_SWAP_H
static inline void mm_account_reclaimed_pages(unsigned long pages) {}
#endif /* _LINUX_SWAP_H */

View File

@ -44,6 +44,20 @@ static inline struct timespec timespec_trunc(struct timespec t, unsigned gran)
return t;
}
static inline void set_normalized_timespec64(struct timespec64 *ts, time64_t sec, s64 nsec)
{
while (nsec >= NSEC_PER_SEC) {
nsec -= NSEC_PER_SEC;
++sec;
}
while (nsec < 0) {
nsec += NSEC_PER_SEC;
--sec;
}
ts->tv_sec = sec;
ts->tv_nsec = nsec;
}
#define ns_to_timespec64 ns_to_timespec
#define timespec64_to_ns timespec_to_ns
#define timespec64_trunc timespec_trunc

View File

@ -37,6 +37,8 @@ typedef unsigned gfp_t;
#define __GFP_NOWARN 0
#define __GFP_NORETRY 0
#define __GFP_NOFAIL 0
#define __GFP_ACCOUNT 0
#define __GFP_RECLAIMABLE 0
#define __GFP_ZERO 1
#define GFP_KERNEL 2

View File

@ -0,0 +1 @@
#include <asm/unaligned.h>

View File

@ -96,6 +96,7 @@ do { \
#define wait_event_freezable(wq, condition) ({wait_event(wq, condition); 0; })
#define wait_event_killable(wq, condition) ({wait_event(wq, condition); 0; })
#define wait_event_interruptible(wq, condition) ({wait_event(wq, condition); 0; })
#define wait_event_state(wq, condition, state) ({wait_event(wq, condition); 0; })
#define __wait_event_timeout(wq, condition, timeout) \
___wait_event(wq, ___wait_cond_timeout(condition), \

Some files were not shown because too many files have changed in this diff Show More