mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-12-08 00:00:12 +03:00
Update bcachefs sources to b31b8a82b13e bcachefs: fix ctime update on unlink
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
36191ce280
commit
145ffa823b
@ -1 +1 @@
|
||||
508dc7f614e7ea505f16063ab34fdb316d8b2668
|
||||
b31b8a82b13ecb7c36320704d37dc26419ccf5c3
|
||||
|
||||
15
Makefile
15
Makefile
@ -39,7 +39,7 @@ CFLAGS+=-std=gnu11 -O2 -g -MMD -Wall -fPIC \
|
||||
-Wno-deprecated-declarations \
|
||||
-fno-strict-aliasing \
|
||||
-fno-delete-null-pointer-checks \
|
||||
-I. -Ic_src -Iinclude -Iraid \
|
||||
-I. -Ic_src -Ilibbcachefs -Iinclude -Iraid \
|
||||
-D_FILE_OFFSET_BITS=64 \
|
||||
-D_GNU_SOURCE \
|
||||
-D_LGPL_SOURCE \
|
||||
@ -192,10 +192,9 @@ install_dkms: dkms/dkms.conf
|
||||
$(INSTALL) -m0644 -D dkms/Makefile -t $(DESTDIR)$(DKMSDIR)
|
||||
$(INSTALL) -m0644 -D dkms/dkms.conf -t $(DESTDIR)$(DKMSDIR)
|
||||
$(INSTALL) -m0644 -D libbcachefs/Makefile -t $(DESTDIR)$(DKMSDIR)/src/fs/bcachefs
|
||||
$(INSTALL) -m0644 -D libbcachefs/*.[ch] -t $(DESTDIR)$(DKMSDIR)/src/fs/bcachefs
|
||||
$(INSTALL) -m0644 -D libbcachefs/vendor/*.[ch] -t $(DESTDIR)$(DKMSDIR)/src/fs/bcachefs/vendor
|
||||
(cd libbcachefs; find -name '*.[ch]' -exec install -m0644 -D {} $(DESTDIR)$(DKMSDIR)/src/fs/bcachefs/{} \; )
|
||||
sed -i "s|^#define TRACE_INCLUDE_PATH \\.\\./\\.\\./fs/bcachefs$$|#define TRACE_INCLUDE_PATH .|" \
|
||||
$(DESTDIR)$(DKMSDIR)/src/fs/bcachefs/trace.h
|
||||
$(DESTDIR)$(DKMSDIR)/src/fs/bcachefs/debug/trace.h
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@ -227,13 +226,11 @@ cargo-update-msrv:
|
||||
update-bcachefs-sources:
|
||||
git rm -rf --ignore-unmatch libbcachefs
|
||||
mkdir -p libbcachefs/vendor
|
||||
cp $(LINUX_DIR)/fs/bcachefs/*.[ch] libbcachefs/
|
||||
cp $(LINUX_DIR)/fs/bcachefs/vendor/*.[ch] libbcachefs/vendor/
|
||||
cp $(LINUX_DIR)/fs/bcachefs/Makefile libbcachefs/
|
||||
cp -r $(LINUX_DIR)/fs/bcachefs/* libbcachefs/
|
||||
git add libbcachefs/*.[ch]
|
||||
git add libbcachefs/vendor/*.[ch]
|
||||
git add libbcachefs/*/*.[ch]
|
||||
git add libbcachefs/Makefile
|
||||
git rm -f libbcachefs/mean_and_variance_test.c
|
||||
git rm -f libbcachefs/util/mean_and_variance_test.c
|
||||
cp $(LINUX_DIR)/include/linux/xxhash.h include/linux/
|
||||
git add include/linux/xxhash.h
|
||||
cp $(LINUX_DIR)/lib/xxhash.c linux/
|
||||
|
||||
@ -34,6 +34,7 @@ fn main() {
|
||||
.map(|p| format!("-I{}", p.display())),
|
||||
)
|
||||
.clang_arg("-I..")
|
||||
.clang_arg("-I../libbcachefs")
|
||||
.clang_arg("-I../c_src")
|
||||
.clang_arg("-I../include")
|
||||
.clang_arg("-DZSTD_STATIC_LINKING_ONLY")
|
||||
|
||||
@ -1,20 +1,24 @@
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "libbcachefs/checksum.h"
|
||||
#include "libbcachefs/bcachefs_format.h"
|
||||
#include "libbcachefs/btree_cache.h"
|
||||
#include "libbcachefs/btree_iter.h"
|
||||
#include "libbcachefs/debug.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/error.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "crypto.h"
|
||||
#include "include/linux/bio.h"
|
||||
#include "include/linux/blkdev.h"
|
||||
#include "bcachefs_format.h"
|
||||
#include "errcode.h"
|
||||
#include "opts.h"
|
||||
|
||||
#include "btree/cache.h"
|
||||
#include "btree/iter.h"
|
||||
#include "data/checksum.h"
|
||||
#include "debug/debug.h"
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
#include "sb/io.h"
|
||||
|
||||
#include "cmds.h"
|
||||
#include "crypto.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "raid/raid.h"
|
||||
#include "src/rust_to_c.h"
|
||||
|
||||
#include "include/linux/bio.h"
|
||||
#include "include/linux/blkdev.h"
|
||||
|
||||
/* Fix753 is a workaround for https://github.com/rust-lang/rust-bindgen/issues/753
|
||||
* Functional macro are not expanded with bindgen, e.g. ioctl are automatically ignored
|
||||
* from the generation
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "sb/io.h"
|
||||
|
||||
static void reset_counters_usage(void)
|
||||
{
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "libbcachefs/bcachefs_ioctl.h"
|
||||
#include "libbcachefs/btree_cache.h"
|
||||
#include "libbcachefs/move.h"
|
||||
#include "bcachefs_ioctl.h"
|
||||
#include "btree/cache.h"
|
||||
#include "data/move.h"
|
||||
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs.h"
|
||||
|
||||
@ -14,17 +14,22 @@
|
||||
|
||||
#include <blkid.h>
|
||||
|
||||
#include "libbcachefs/bcachefs.h"
|
||||
#include "libbcachefs/bcachefs_ioctl.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/journal.h"
|
||||
#include "libbcachefs/sb-members.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "bcachefs_ioctl.h"
|
||||
|
||||
#include "init/dev.h"
|
||||
#include "init/fs.h"
|
||||
|
||||
#include "journal/init.h"
|
||||
|
||||
#include "sb/members.h"
|
||||
#include "sb/io.h"
|
||||
|
||||
static void device_add_usage(void)
|
||||
{
|
||||
puts("bcachefs device add - add a device to an existing filesystem\n"
|
||||
|
||||
@ -8,15 +8,15 @@
|
||||
#include "libbcachefs.h"
|
||||
#include "qcow2.h"
|
||||
|
||||
#include "libbcachefs/bcachefs.h"
|
||||
#include "libbcachefs/btree_cache.h"
|
||||
#include "libbcachefs/btree_io.h"
|
||||
#include "libbcachefs/btree_iter.h"
|
||||
#include "libbcachefs/error.h"
|
||||
#include "libbcachefs/extents.h"
|
||||
#include "libbcachefs/journal_io.h"
|
||||
#include "libbcachefs/sb-members.h"
|
||||
#include "libbcachefs/super.h"
|
||||
#include "bcachefs.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/io.h"
|
||||
#include "btree/iter.h"
|
||||
#include "data/extents.h"
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
#include "journal/io.h"
|
||||
#include "sb/members.h"
|
||||
|
||||
struct dump_dev {
|
||||
ranges sb, journal, btree;
|
||||
|
||||
@ -26,12 +26,13 @@
|
||||
#include "posix_to_bcachefs.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "crypto.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "libbcachefs/util.h"
|
||||
|
||||
#include "libbcachefs/darray.h"
|
||||
#include "errcode.h"
|
||||
#include "opts.h"
|
||||
#include "init/fs.h"
|
||||
#include "sb/io.h"
|
||||
#include "util/util.h"
|
||||
#include "util/darray.h"
|
||||
|
||||
#define OPTS \
|
||||
x(0, replicas, required_argument) \
|
||||
|
||||
@ -7,17 +7,16 @@
|
||||
#include "linux/sort.h"
|
||||
#include "linux/rcupdate.h"
|
||||
|
||||
#include "libbcachefs/bcachefs_ioctl.h"
|
||||
#include "libbcachefs/buckets.h"
|
||||
#include "libbcachefs/disk_accounting.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "bcachefs_ioctl.h"
|
||||
#include "opts.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/accounting.h"
|
||||
#include "sb/io.h"
|
||||
#include "util/darray.h"
|
||||
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs.h"
|
||||
|
||||
#include "libbcachefs/darray.h"
|
||||
|
||||
#define FS_USAGE_FIELDS() \
|
||||
x(replicas) \
|
||||
x(btree) \
|
||||
|
||||
@ -3,14 +3,16 @@
|
||||
#include <getopt.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs/error.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "libbcachefs/recovery_passes.h"
|
||||
#include "libbcachefs/super.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
#include "init/passes.h"
|
||||
#include "sb/io.h"
|
||||
|
||||
static void setnonblocking(int fd)
|
||||
{
|
||||
int flags = fcntl(fd, F_GETFL);
|
||||
|
||||
@ -12,23 +12,23 @@
|
||||
#include "libbcachefs.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
#include "libbcachefs/bcachefs.h"
|
||||
#include "libbcachefs/alloc_foreground.h"
|
||||
#include "libbcachefs/btree_iter.h"
|
||||
#include "libbcachefs/buckets.h"
|
||||
#include "libbcachefs/dirent.h"
|
||||
#include "libbcachefs/disk_accounting.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/error.h"
|
||||
#include "libbcachefs/namei.h"
|
||||
#include "libbcachefs/inode.h"
|
||||
#include "libbcachefs/io_read.h"
|
||||
#include "libbcachefs/io_write.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/super.h"
|
||||
#include "bcachefs.h"
|
||||
|
||||
/* mode_to_type(): */
|
||||
#include "libbcachefs/fs.h"
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/foreground.h"
|
||||
|
||||
#include "btree/iter.h"
|
||||
|
||||
#include "data/read.h"
|
||||
#include "data/write.h"
|
||||
|
||||
#include "fs/dirent.h"
|
||||
#include "fs/namei.h"
|
||||
#include "fs/inode.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
|
||||
#include <linux/dcache.h>
|
||||
|
||||
|
||||
@ -24,19 +24,27 @@
|
||||
#include "posix_to_bcachefs.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "crypto.h"
|
||||
#include "libbcachefs/alloc_background.h"
|
||||
#include "libbcachefs/alloc_foreground.h"
|
||||
#include "libbcachefs/btree_update.h"
|
||||
#include "libbcachefs/data_update.h"
|
||||
#include "libbcachefs/disk_accounting.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/journal_reclaim.h"
|
||||
#include "libbcachefs/move.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "libbcachefs/util.h"
|
||||
|
||||
#include "libbcachefs/darray.h"
|
||||
#include "bcachefs.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/background.h"
|
||||
#include "alloc/foreground.h"
|
||||
|
||||
#include "btree/update.h"
|
||||
|
||||
#include "data/move.h"
|
||||
#include "data/update.h"
|
||||
|
||||
#include "init/dev.h"
|
||||
#include "init/fs.h"
|
||||
|
||||
#include "journal/reclaim.h"
|
||||
|
||||
#include "sb/io.h"
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/darray.h"
|
||||
|
||||
static u64 count_input_size(int dirfd)
|
||||
{
|
||||
|
||||
@ -5,11 +5,13 @@
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs/checksum.h"
|
||||
#include "crypto.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
#include "data/checksum.h"
|
||||
#include "init/fs.h"
|
||||
|
||||
static void unlock_usage(void)
|
||||
{
|
||||
puts("bcachefs unlock - unlock an encrypted filesystem so it can be mounted\n"
|
||||
|
||||
@ -8,12 +8,11 @@
|
||||
#include "libbcachefs.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
#include "libbcachefs/bcachefs.h"
|
||||
#include "libbcachefs/btree_iter.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/error.h"
|
||||
#include "libbcachefs/sb-members.h"
|
||||
#include "libbcachefs/super.h"
|
||||
#include "bcachefs.h"
|
||||
#include "btree/iter.h"
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
#include "sb/members.h"
|
||||
|
||||
static void kill_btree_node_usage(void)
|
||||
{
|
||||
|
||||
@ -9,13 +9,14 @@
|
||||
#include "libbcachefs.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
#include "libbcachefs/bcachefs.h"
|
||||
#include "libbcachefs/btree_iter.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/error.h"
|
||||
#include "libbcachefs/journal_io.h"
|
||||
#include "libbcachefs/journal_seq_blacklist.h"
|
||||
#include "libbcachefs/super.h"
|
||||
#include "bcachefs.h"
|
||||
#include "btree/iter.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
|
||||
#include "journal/io.h"
|
||||
#include "journal/seq_blacklist.h"
|
||||
|
||||
#include <linux/fs_parser.h>
|
||||
|
||||
|
||||
@ -22,14 +22,14 @@
|
||||
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/generic-radix-tree.h>
|
||||
#include "libbcachefs/bcachefs.h"
|
||||
#include "libbcachefs/btree_update.h"
|
||||
#include "libbcachefs/buckets.h"
|
||||
#include "libbcachefs/dirent.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/inode.h"
|
||||
#include "libbcachefs/replicas.h"
|
||||
#include "libbcachefs/super.h"
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/replicas.h"
|
||||
#include "btree/update.h"
|
||||
#include "fs/dirent.h"
|
||||
#include "fs/inode.h"
|
||||
#include "init/fs.h"
|
||||
|
||||
static char *dev_t_to_path(dev_t dev)
|
||||
{
|
||||
|
||||
@ -20,9 +20,11 @@
|
||||
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
|
||||
#include "errcode.h"
|
||||
#include "opts.h"
|
||||
#include "init/fs.h"
|
||||
#include "sb/io.h"
|
||||
|
||||
static void set_option_usage(void)
|
||||
{
|
||||
|
||||
@ -21,14 +21,15 @@
|
||||
|
||||
#include "cmds.h"
|
||||
#include "cmd_strip_alloc.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/journal.h"
|
||||
#include "libbcachefs/sb-clean.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "libbcachefs/util.h"
|
||||
|
||||
#include "libbcachefs/darray.h"
|
||||
#include "errcode.h"
|
||||
#include "opts.h"
|
||||
#include "init/fs.h"
|
||||
#include "journal/journal.h"
|
||||
#include "sb/clean.h"
|
||||
#include "sb/io.h"
|
||||
#include "util/util.h"
|
||||
#include "util/darray.h"
|
||||
|
||||
void strip_fs_alloc(struct bch_fs *c)
|
||||
{
|
||||
|
||||
@ -23,11 +23,14 @@
|
||||
#include "cmds.h"
|
||||
#include "cmd_super.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "libbcachefs/util.h"
|
||||
|
||||
#include "libbcachefs/darray.h"
|
||||
#include "bcachefs.h"
|
||||
|
||||
#include "sb/io.h"
|
||||
#include "sb/members.h"
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/darray.h"
|
||||
|
||||
#include "src/rust_to_c.h"
|
||||
|
||||
@ -190,9 +193,6 @@ int cmd_show_super(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "libbcachefs/sb-members.h"
|
||||
|
||||
typedef DARRAY(struct bch_sb *) probed_sb_list;
|
||||
|
||||
struct recover_super_args {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#ifndef _TOOLS_CMD_SHOW_SUPER_H
|
||||
#define _TOOLS_CMD_SHOW_SUPER_H
|
||||
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "sb/io.h"
|
||||
|
||||
void bch2_sb_to_text_with_names(struct printbuf *, struct bch_sb *, bool, unsigned, int);
|
||||
|
||||
|
||||
@ -7,7 +7,8 @@
|
||||
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "libbcachefs/sb-counters.h"
|
||||
|
||||
#include "sb/counters.h"
|
||||
|
||||
static const u8 counters_to_stable_map[] = {
|
||||
#define x(n, id, ...) [BCH_COUNTER_##n] = BCH_COUNTER_STABLE_##n,
|
||||
|
||||
@ -15,9 +15,10 @@
|
||||
#include <sodium/crypto_pwhash_scryptsalsa208sha256.h>
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include "libbcachefs/checksum.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#include "data/checksum.h"
|
||||
|
||||
char *read_passphrase(const char *prompt)
|
||||
{
|
||||
char *buf = NULL;
|
||||
|
||||
@ -21,17 +21,21 @@
|
||||
|
||||
#include "libbcachefs.h"
|
||||
#include "crypto.h"
|
||||
#include "libbcachefs/bcachefs_format.h"
|
||||
#include "libbcachefs/btree_cache.h"
|
||||
#include "libbcachefs/buckets.h"
|
||||
#include "libbcachefs/checksum.h"
|
||||
#include "libbcachefs/disk_groups.h"
|
||||
#include "libbcachefs/journal_seq_blacklist.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/replicas.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
#include "bcachefs.h"
|
||||
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/disk_groups.h"
|
||||
#include "alloc/replicas.h"
|
||||
#include "btree/cache.h"
|
||||
|
||||
#include "data/checksum.h"
|
||||
|
||||
#include "journal/seq_blacklist.h"
|
||||
|
||||
#include "sb/io.h"
|
||||
|
||||
#define NSEC_PER_SEC 1000000000L
|
||||
|
||||
void bch2_sb_layout_init(struct bch_sb_layout *l,
|
||||
|
||||
@ -4,12 +4,12 @@
|
||||
#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 "bcachefs.h"
|
||||
#include "bcachefs_format.h"
|
||||
#include "bcachefs_ioctl.h"
|
||||
#include "fs/inode.h"
|
||||
#include "util/vstructs.h"
|
||||
|
||||
#include "tools-util.h"
|
||||
|
||||
/* option parsing */
|
||||
|
||||
@ -5,14 +5,17 @@
|
||||
#include <linux/xattr.h>
|
||||
|
||||
#include "posix_to_bcachefs.h"
|
||||
#include "libbcachefs/alloc_foreground.h"
|
||||
#include "libbcachefs/buckets.h"
|
||||
#include "libbcachefs/io_misc.h"
|
||||
#include "libbcachefs/io_read.h"
|
||||
#include "libbcachefs/io_write.h"
|
||||
#include "libbcachefs/namei.h"
|
||||
#include "libbcachefs/str_hash.h"
|
||||
#include "libbcachefs/xattr.h"
|
||||
|
||||
#include "alloc/foreground.h"
|
||||
#include "alloc/buckets.h"
|
||||
|
||||
#include "data/io_misc.h"
|
||||
#include "data/read.h"
|
||||
#include "data/write.h"
|
||||
|
||||
#include "fs/namei.h"
|
||||
#include "fs/str_hash.h"
|
||||
#include "fs/xattr.h"
|
||||
|
||||
struct hardlink {
|
||||
struct rhash_head hash;
|
||||
|
||||
@ -17,11 +17,12 @@
|
||||
#include <blkid.h>
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include "bcachefs_ioctl.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include "libbcachefs.h"
|
||||
#include "libbcachefs/bcachefs_ioctl.h"
|
||||
#include "linux/sort.h"
|
||||
#include "tools-util.h"
|
||||
#include "libbcachefs/util.h"
|
||||
#include "src/rust_to_c.h"
|
||||
|
||||
void die(const char *fmt, ...)
|
||||
|
||||
@ -18,9 +18,10 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uuid.h>
|
||||
#include "libbcachefs/bcachefs.h"
|
||||
#include "libbcachefs/bbpos.h"
|
||||
#include "libbcachefs/darray.h"
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "btree/bbpos.h"
|
||||
#include "util/darray.h"
|
||||
|
||||
#define noreturn __attribute__((noreturn))
|
||||
|
||||
|
||||
@ -6,109 +6,116 @@ endif
|
||||
|
||||
obj-$(CONFIG_BCACHEFS_FS) += bcachefs.o
|
||||
|
||||
bcachefs-y := \
|
||||
acl.o \
|
||||
alloc_background.o \
|
||||
alloc_foreground.o \
|
||||
async_objs.o \
|
||||
backpointers.o \
|
||||
bkey.o \
|
||||
bkey_methods.o \
|
||||
bkey_sort.o \
|
||||
bset.o \
|
||||
btree_cache.o \
|
||||
btree_gc.o \
|
||||
btree_io.o \
|
||||
btree_iter.o \
|
||||
btree_journal_iter.o \
|
||||
btree_key_cache.o \
|
||||
btree_locking.o \
|
||||
btree_node_scan.o \
|
||||
btree_trans_commit.o \
|
||||
btree_update.o \
|
||||
btree_update_interior.o \
|
||||
btree_write_buffer.o \
|
||||
buckets.o \
|
||||
buckets_waiting_for_journal.o \
|
||||
chardev.o \
|
||||
checksum.o \
|
||||
clock.o \
|
||||
compress.o \
|
||||
darray.o \
|
||||
data_update.o \
|
||||
debug.o \
|
||||
dirent.o \
|
||||
disk_accounting.o \
|
||||
disk_groups.o \
|
||||
ec.o \
|
||||
enumerated_ref.o \
|
||||
errcode.o \
|
||||
error.o \
|
||||
extents.o \
|
||||
extent_update.o \
|
||||
eytzinger.o \
|
||||
fast_list.o \
|
||||
fs.o \
|
||||
fs-ioctl.o \
|
||||
fs-io.o \
|
||||
fs-io-buffered.o \
|
||||
fs-io-direct.o \
|
||||
fs-io-pagecache.o \
|
||||
fsck.o \
|
||||
inode.o \
|
||||
io_read.o \
|
||||
io_misc.o \
|
||||
io_write.o \
|
||||
journal.o \
|
||||
journal_io.o \
|
||||
journal_reclaim.o \
|
||||
journal_sb.o \
|
||||
journal_seq_blacklist.o \
|
||||
keylist.o \
|
||||
logged_ops.o \
|
||||
lru.o \
|
||||
mean_and_variance.o \
|
||||
migrate.o \
|
||||
move.o \
|
||||
movinggc.o \
|
||||
namei.o \
|
||||
nocow_locking.o \
|
||||
opts.o \
|
||||
printbuf.o \
|
||||
progress.o \
|
||||
quota.o \
|
||||
rebalance.o \
|
||||
rcu_pending.o \
|
||||
recovery.o \
|
||||
recovery_passes.o \
|
||||
reflink.o \
|
||||
replicas.o \
|
||||
sb-clean.o \
|
||||
sb-counters.o \
|
||||
sb-downgrade.o \
|
||||
sb-errors.o \
|
||||
sb-members.o \
|
||||
siphash.o \
|
||||
six.o \
|
||||
snapshot.o \
|
||||
str_hash.o \
|
||||
subvolume.o \
|
||||
super.o \
|
||||
super-io.o \
|
||||
sysfs.o \
|
||||
tests.o \
|
||||
time_stats.o \
|
||||
thread_with_file.o \
|
||||
trace.o \
|
||||
two_state_shared_lock.o \
|
||||
util.o \
|
||||
varint.o \
|
||||
xattr.o \
|
||||
vendor/closure.o \
|
||||
vendor/min_heap.o
|
||||
bcachefs-y := \
|
||||
alloc/accounting.o \
|
||||
alloc/background.o \
|
||||
alloc/backpointers.o \
|
||||
alloc/buckets.o \
|
||||
alloc/buckets_waiting_for_journal.o \
|
||||
alloc/check.o \
|
||||
alloc/disk_groups.o \
|
||||
alloc/foreground.o \
|
||||
alloc/lru.o \
|
||||
alloc/replicas.o \
|
||||
btree/bkey.o \
|
||||
btree/bkey_methods.o \
|
||||
btree/bkey_sort.o \
|
||||
btree/bset.o \
|
||||
btree/cache.o \
|
||||
btree/check.o \
|
||||
btree/io.o \
|
||||
btree/iter.o \
|
||||
btree/journal_overlay.o \
|
||||
btree/key_cache.o \
|
||||
btree/locking.o \
|
||||
btree/node_scan.o \
|
||||
btree/commit.o \
|
||||
btree/update.o \
|
||||
btree/interior.o \
|
||||
btree/write_buffer.o \
|
||||
data/checksum.o \
|
||||
data/compress.o \
|
||||
data/copygc.o \
|
||||
data/ec.o \
|
||||
data/extents.o \
|
||||
data/extent_update.o \
|
||||
data/io_misc.o \
|
||||
data/keylist.o \
|
||||
data/migrate.o \
|
||||
data/move.o \
|
||||
data/nocow_locking.o \
|
||||
data/read.o \
|
||||
data/rebalance.o \
|
||||
data/reflink.o \
|
||||
data/update.o \
|
||||
data/write.o \
|
||||
debug/async_objs.o \
|
||||
debug/debug.o \
|
||||
debug/sysfs.o \
|
||||
debug/tests.o \
|
||||
debug/trace.o \
|
||||
errcode.o \
|
||||
fs/acl.o \
|
||||
fs/check.o \
|
||||
fs/check_dir_structure.o \
|
||||
fs/check_extents.o \
|
||||
fs/check_nlinks.o \
|
||||
fs/dirent.o \
|
||||
fs/inode.o \
|
||||
fs/logged_ops.o \
|
||||
fs/namei.o \
|
||||
fs/quota.o \
|
||||
fs/str_hash.o \
|
||||
fs/xattr.o \
|
||||
init/chardev.o \
|
||||
init/dev.o \
|
||||
init/error.o \
|
||||
init/fs.o \
|
||||
init/progress.o \
|
||||
init/recovery.o \
|
||||
init/passes.o \
|
||||
journal/init.o \
|
||||
journal/io.o \
|
||||
journal/journal.o \
|
||||
journal/reclaim.o \
|
||||
journal/sb.o \
|
||||
journal/seq_blacklist.o \
|
||||
opts.o \
|
||||
sb/clean.o \
|
||||
sb/counters.o \
|
||||
sb/downgrade.o \
|
||||
sb/errors.o \
|
||||
sb/io.o \
|
||||
sb/members.o \
|
||||
snapshots/check_snapshots.o \
|
||||
snapshots/snapshot.o \
|
||||
snapshots/subvolume.o \
|
||||
util/clock.o \
|
||||
util/darray.o \
|
||||
util/enumerated_ref.o \
|
||||
util/eytzinger.o \
|
||||
util/fast_list.o \
|
||||
util/mean_and_variance.o \
|
||||
util/printbuf.o \
|
||||
util/rcu_pending.o \
|
||||
util/siphash.o \
|
||||
util/six.o \
|
||||
util/time_stats.o \
|
||||
util/thread_with_file.o \
|
||||
util/two_state_shared_lock.o \
|
||||
util/util.o \
|
||||
util/varint.o \
|
||||
vendor/closure.o \
|
||||
vendor/min_heap.o \
|
||||
vfs/fs.o \
|
||||
vfs/ioctl.o \
|
||||
vfs/io.o \
|
||||
vfs/buffered.o \
|
||||
vfs/direct.o \
|
||||
vfs/pagecache.o
|
||||
|
||||
ifndef BCACHEFS_DKMS
|
||||
obj-$(CONFIG_MEAN_AND_VARIANCE_UNIT_TEST) += mean_and_variance_test.o
|
||||
obj-$(CONFIG_MEAN_AND_VARIANCE_UNIT_TEST) += util/mean_and_variance_test.o
|
||||
endif
|
||||
|
||||
# Silence "note: xyz changed in GCC X.X" messages
|
||||
|
||||
@ -2,17 +2,22 @@
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "bcachefs_ioctl.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_journal_iter.h"
|
||||
#include "btree_update.h"
|
||||
#include "btree_write_buffer.h"
|
||||
#include "buckets.h"
|
||||
#include "compress.h"
|
||||
#include "disk_accounting.h"
|
||||
#include "error.h"
|
||||
#include "journal_io.h"
|
||||
#include "recovery_passes.h"
|
||||
#include "replicas.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/replicas.h"
|
||||
|
||||
#include "btree/cache.h"
|
||||
#include "btree/journal_overlay.h"
|
||||
#include "btree/update.h"
|
||||
#include "btree/write_buffer.h"
|
||||
|
||||
#include "data/compress.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/passes.h"
|
||||
|
||||
#include "journal/io.h"
|
||||
|
||||
/*
|
||||
* Notes on disk accounting:
|
||||
@ -126,10 +131,7 @@ int bch2_disk_accounting_mod(struct btree_trans *trans,
|
||||
}
|
||||
#endif
|
||||
unsigned u64s = sizeof(*a) / sizeof(u64) + nr;
|
||||
a = bch2_trans_subbuf_alloc(trans, &trans->accounting, u64s);
|
||||
int ret = PTR_ERR_OR_ZERO(a);
|
||||
if (ret)
|
||||
return ret;
|
||||
a = errptr_try(bch2_trans_subbuf_alloc(trans, &trans->accounting, u64s));
|
||||
|
||||
__accounting_key_init(&a->k_i, pos, d, nr);
|
||||
return 0;
|
||||
@ -343,11 +345,8 @@ int bch2_accounting_update_sb(struct btree_trans *trans)
|
||||
{
|
||||
for (struct bkey_i *i = btree_trans_subbuf_base(trans, &trans->accounting);
|
||||
i != btree_trans_subbuf_top(trans, &trans->accounting);
|
||||
i = bkey_next(i)) {
|
||||
int ret = bch2_accounting_update_sb_one(trans->c, i->k.p);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
i = bkey_next(i))
|
||||
try(bch2_accounting_update_sb_one(trans->c, i->k.p));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2,9 +2,9 @@
|
||||
#ifndef _BCACHEFS_DISK_ACCOUNTING_H
|
||||
#define _BCACHEFS_DISK_ACCOUNTING_H
|
||||
|
||||
#include "btree_update.h"
|
||||
#include "eytzinger.h"
|
||||
#include "sb-members.h"
|
||||
#include "btree/update.h"
|
||||
#include "sb/members.h"
|
||||
#include "util/eytzinger.h"
|
||||
|
||||
static inline void bch2_u64s_neg(u64 *v, unsigned nr)
|
||||
{
|
||||
@ -2,7 +2,7 @@
|
||||
#ifndef _BCACHEFS_DISK_ACCOUNTING_TYPES_H
|
||||
#define _BCACHEFS_DISK_ACCOUNTING_TYPES_H
|
||||
|
||||
#include "darray.h"
|
||||
#include "util/darray.h"
|
||||
|
||||
struct accounting_mem_entry {
|
||||
struct bpos pos;
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,10 +3,8 @@
|
||||
#define _BCACHEFS_ALLOC_BACKGROUND_H
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "alloc_types.h"
|
||||
#include "buckets.h"
|
||||
#include "debug.h"
|
||||
#include "super.h"
|
||||
#include "alloc/types.h"
|
||||
#include "alloc/buckets.h"
|
||||
|
||||
/* How out of date a pointer gen is allowed to be: */
|
||||
#define BUCKET_GC_GEN_MAX 96U
|
||||
@ -212,6 +210,28 @@ static inline void set_alloc_v4_u64s(struct bkey_i_alloc_v4 *a)
|
||||
set_bkey_val_u64s(&a->k, alloc_v4_u64s(&a->v));
|
||||
}
|
||||
|
||||
static inline struct bpos alloc_gens_pos(struct bpos pos, unsigned *offset)
|
||||
{
|
||||
*offset = pos.offset & KEY_TYPE_BUCKET_GENS_MASK;
|
||||
|
||||
pos.offset >>= KEY_TYPE_BUCKET_GENS_BITS;
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline struct bpos bucket_gens_pos_to_alloc(struct bpos pos, unsigned offset)
|
||||
{
|
||||
pos.offset <<= KEY_TYPE_BUCKET_GENS_BITS;
|
||||
pos.offset += offset;
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline unsigned alloc_gen(struct bkey_s_c k, unsigned offset)
|
||||
{
|
||||
return k.k->type == KEY_TYPE_bucket_gens
|
||||
? bkey_s_c_to_bucket_gens(k).v->gens[offset]
|
||||
: 0;
|
||||
}
|
||||
|
||||
struct bkey_i_alloc_v4 *
|
||||
bch2_trans_start_alloc_update_noupdate(struct btree_trans *, struct btree_iter *, struct bpos);
|
||||
struct bkey_i_alloc_v4 *
|
||||
@ -302,6 +322,9 @@ static inline bool bkey_is_alloc(const struct bkey *k)
|
||||
|
||||
int bch2_alloc_read(struct bch_fs *);
|
||||
|
||||
int bch2_bucket_do_index(struct btree_trans *, struct bch_dev *,
|
||||
struct bkey_s_c, const struct bch_alloc_v4 *, bool);
|
||||
|
||||
int bch2_alloc_key_to_dev_counters(struct btree_trans *, struct bch_dev *,
|
||||
const struct bch_alloc_v4 *,
|
||||
const struct bch_alloc_v4 *, unsigned);
|
||||
@ -309,16 +332,6 @@ int bch2_trigger_alloc(struct btree_trans *, enum btree_id, unsigned,
|
||||
struct bkey_s_c, struct bkey_s,
|
||||
enum btree_iter_update_trigger_flags);
|
||||
|
||||
int __bch2_check_discard_freespace_key(struct btree_trans *, struct btree_iter *, u8 *,
|
||||
enum bch_fsck_flags);
|
||||
|
||||
static inline int bch2_check_discard_freespace_key_async(struct btree_trans *trans, struct btree_iter *iter, u8 *gen)
|
||||
{
|
||||
return __bch2_check_discard_freespace_key(trans, iter, gen, FSCK_ERR_NO_LOG);
|
||||
}
|
||||
|
||||
int bch2_check_alloc_info(struct bch_fs *);
|
||||
int bch2_check_alloc_to_lru_refs(struct bch_fs *);
|
||||
void bch2_dev_do_discards(struct bch_dev *);
|
||||
void bch2_do_discards_going_ro(struct bch_fs *);
|
||||
void bch2_do_discards(struct bch_fs *);
|
||||
@ -350,8 +363,6 @@ static inline const struct bch_backpointer *alloc_v4_backpointers_c(const struct
|
||||
return (void *) ((u64 *) &a->v + BCH_ALLOC_V4_BACKPOINTERS_START(a));
|
||||
}
|
||||
|
||||
int bch2_dev_freespace_init(struct bch_fs *, struct bch_dev *, u64, u64);
|
||||
int bch2_fs_freespace_init(struct bch_fs *);
|
||||
int bch2_dev_remove_alloc(struct bch_fs *, struct bch_dev *);
|
||||
|
||||
void bch2_recalc_capacity(struct bch_fs *);
|
||||
@ -1,18 +1,22 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "bcachefs.h"
|
||||
#include "bbpos.h"
|
||||
#include "alloc_background.h"
|
||||
#include "backpointers.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_update.h"
|
||||
#include "btree_update_interior.h"
|
||||
#include "btree_write_buffer.h"
|
||||
#include "checksum.h"
|
||||
#include "disk_accounting.h"
|
||||
#include "error.h"
|
||||
#include "progress.h"
|
||||
#include "recovery_passes.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/background.h"
|
||||
#include "alloc/backpointers.h"
|
||||
|
||||
#include "btree/bbpos.h"
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/update.h"
|
||||
#include "btree/interior.h"
|
||||
#include "btree/write_buffer.h"
|
||||
|
||||
#include "data/checksum.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/progress.h"
|
||||
#include "init/passes.h"
|
||||
|
||||
#include <linux/mm.h>
|
||||
|
||||
@ -157,19 +161,13 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
|
||||
CLASS(btree_iter, bp_iter)(trans, BTREE_ID_backpointers, bp->k.p,
|
||||
BTREE_ITER_intent|
|
||||
BTREE_ITER_with_updates);
|
||||
struct bkey_s_c k = bch2_btree_iter_peek_slot(&bp_iter);
|
||||
int ret = bkey_err(k);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_s_c k = bkey_try(bch2_btree_iter_peek_slot(&bp_iter));
|
||||
|
||||
if (insert
|
||||
? k.k->type
|
||||
: (k.k->type != KEY_TYPE_backpointer ||
|
||||
memcmp(bkey_s_c_to_backpointer(k).v, &bp->v, sizeof(bp->v)))) {
|
||||
ret = backpointer_mod_err(trans, orig_k, bp, k, insert);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
memcmp(bkey_s_c_to_backpointer(k).v, &bp->v, sizeof(bp->v))))
|
||||
try(backpointer_mod_err(trans, orig_k, bp, k, insert));
|
||||
|
||||
if (!insert) {
|
||||
bp->k.type = KEY_TYPE_deleted;
|
||||
@ -211,11 +209,9 @@ static int backpointer_target_not_found(struct btree_trans *trans,
|
||||
* looking at may have already been deleted - failure to find what it
|
||||
* pointed to is not an error:
|
||||
*/
|
||||
ret = last_flushed
|
||||
? bch2_backpointers_maybe_flush(trans, bp.s_c, last_flushed)
|
||||
: 0;
|
||||
if (ret)
|
||||
return ret;
|
||||
try(last_flushed
|
||||
? bch2_backpointers_maybe_flush(trans, bp.s_c, last_flushed)
|
||||
: 0);
|
||||
|
||||
prt_printf(&buf, "backpointer doesn't match %s it points to:\n",
|
||||
bp.v->level ? "btree node" : "extent");
|
||||
@ -237,9 +233,7 @@ static int backpointer_target_not_found(struct btree_trans *trans,
|
||||
|
||||
if (fsck_err(trans, backpointer_to_missing_ptr,
|
||||
"%s", buf.buf)) {
|
||||
ret = bch2_backpointer_del(trans, bp.k->p);
|
||||
if (ret || !commit)
|
||||
return ret;
|
||||
try(bch2_backpointer_del(trans, bp.k->p));
|
||||
|
||||
/*
|
||||
* Normally, on transaction commit from inside a transaction,
|
||||
@ -255,7 +249,9 @@ static int backpointer_target_not_found(struct btree_trans *trans,
|
||||
* next backpointer and starting a new transaction immediately
|
||||
* after backpointer_get_key() returns NULL:
|
||||
*/
|
||||
ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
|
||||
try(commit
|
||||
? bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc)
|
||||
: 0);
|
||||
}
|
||||
fsck_err:
|
||||
return ret;
|
||||
@ -395,9 +391,7 @@ static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, st
|
||||
|
||||
struct bpos bucket;
|
||||
if (!bp_pos_to_bucket_nodev_noerror(c, k.k->p, &bucket)) {
|
||||
ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_backpointers_maybe_flush(trans, k, last_flushed));
|
||||
|
||||
if (fsck_err(trans, backpointer_to_missing_device,
|
||||
"backpointer for missing device:\n%s",
|
||||
@ -408,15 +402,10 @@ static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, st
|
||||
|
||||
{
|
||||
CLASS(btree_iter, alloc_iter)(trans, BTREE_ID_alloc, bucket, 0);
|
||||
struct bkey_s_c alloc_k = bch2_btree_iter_peek_slot(&alloc_iter);
|
||||
ret = bkey_err(alloc_k);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_s_c alloc_k = bkey_try(bch2_btree_iter_peek_slot(&alloc_iter));
|
||||
|
||||
if (alloc_k.k->type != KEY_TYPE_alloc_v4) {
|
||||
ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_backpointers_maybe_flush(trans, k, last_flushed));
|
||||
|
||||
if (fsck_err(trans, backpointer_to_missing_alloc,
|
||||
"backpointer for nonexistent alloc key: %llu:%llu:0\n%s",
|
||||
@ -461,10 +450,7 @@ struct extents_to_bp_state {
|
||||
static int drop_dev_and_update(struct btree_trans *trans, enum btree_id btree,
|
||||
struct bkey_s_c extent, unsigned dev)
|
||||
{
|
||||
struct bkey_i *n = bch2_bkey_make_mut_noupdate(trans, extent);
|
||||
int ret = PTR_ERR_OR_ZERO(n);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_i *n = errptr_try(bch2_bkey_make_mut_noupdate(trans, extent));
|
||||
|
||||
bch2_bkey_drop_device(bkey_i_to_s(n), dev);
|
||||
return bch2_btree_insert_trans(trans, btree, n, 0);
|
||||
@ -548,19 +534,14 @@ static int check_bp_exists(struct btree_trans *trans,
|
||||
struct bch_fs *c = trans->c;
|
||||
struct btree_iter other_extent_iter = {};
|
||||
CLASS(printbuf, buf)();
|
||||
int ret = 0;
|
||||
|
||||
CLASS(btree_iter, bp_iter)(trans, BTREE_ID_backpointers, bp->k.p, 0);
|
||||
struct bkey_s_c bp_k = bch2_btree_iter_peek_slot(&bp_iter);
|
||||
int ret = bkey_err(bp_k);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_s_c bp_k = bkey_try(bch2_btree_iter_peek_slot(&bp_iter));
|
||||
|
||||
if (bp_k.k->type != KEY_TYPE_backpointer ||
|
||||
memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp->v, sizeof(bp->v))) {
|
||||
ret = bch2_btree_write_buffer_maybe_flush(trans, orig_k, &s->last_flushed);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
try(bch2_btree_write_buffer_maybe_flush(trans, orig_k, &s->last_flushed));
|
||||
goto check_existing_bp;
|
||||
}
|
||||
out:
|
||||
@ -707,11 +688,9 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
|
||||
bpos_gt(bp.k.p, s->bp_end))
|
||||
continue;
|
||||
|
||||
int ret = !empty
|
||||
? check_bp_exists(trans, s, &bp, k)
|
||||
: bch2_bucket_backpointer_mod(trans, k, &bp, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(!empty
|
||||
? check_bp_exists(trans, s, &bp, k)
|
||||
: bch2_bucket_backpointer_mod(trans, k, &bp, true));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -830,11 +809,9 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
|
||||
btree_id++) {
|
||||
int level, depth = btree_type_has_data_ptrs(btree_id) ? 0 : 1;
|
||||
|
||||
ret = commit_do(trans, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc,
|
||||
check_btree_root_to_backpointers(trans, s, btree_id, &level));
|
||||
if (ret)
|
||||
return ret;
|
||||
try(commit_do(trans, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc,
|
||||
check_btree_root_to_backpointers(trans, s, btree_id, &level)));
|
||||
|
||||
while (level >= depth) {
|
||||
struct btree_iter iter;
|
||||
@ -927,9 +904,7 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
|
||||
if (c->sb.version_upgrade_complete < bcachefs_metadata_version_backpointer_bucket_gen &&
|
||||
(bp.v->bucket_gen != a->gen ||
|
||||
bp.v->pad)) {
|
||||
ret = bch2_backpointer_del(trans, bp_k.k->p);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_backpointer_del(trans, bp_k.k->p));
|
||||
|
||||
need_commit = true;
|
||||
continue;
|
||||
@ -947,11 +922,8 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (need_commit) {
|
||||
ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (need_commit)
|
||||
try(bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc));
|
||||
|
||||
if (sectors[ALLOC_dirty] > a->dirty_sectors ||
|
||||
sectors[ALLOC_cached] > a->cached_sectors ||
|
||||
@ -1004,11 +976,8 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
|
||||
* Pre upgrade, we expect all the buckets to be wrong, a write
|
||||
* buffer flush is pointless:
|
||||
*/
|
||||
if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_backpointer_bucket_gen) {
|
||||
ret = bch2_backpointers_maybe_flush(trans, alloc_k, last_flushed);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_backpointer_bucket_gen)
|
||||
try(bch2_backpointers_maybe_flush(trans, alloc_k, last_flushed));
|
||||
|
||||
bool empty = (sectors[ALLOC_dirty] +
|
||||
sectors[ALLOC_stripe] +
|
||||
@ -1247,10 +1216,7 @@ static int check_bucket_backpointer_pos_mismatch(struct btree_trans *trans,
|
||||
struct bkey_buf *last_flushed)
|
||||
{
|
||||
CLASS(btree_iter, alloc_iter)(trans, BTREE_ID_alloc, bucket, BTREE_ITER_cached);
|
||||
struct bkey_s_c k = bch2_btree_iter_peek_slot(&alloc_iter);
|
||||
int ret = bkey_err(k);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_s_c k = bkey_try(bch2_btree_iter_peek_slot(&alloc_iter));
|
||||
|
||||
struct bpos last_pos = POS_MIN;
|
||||
unsigned nr_iters = 0;
|
||||
@ -2,12 +2,11 @@
|
||||
#ifndef _BCACHEFS_BACKPOINTERS_H
|
||||
#define _BCACHEFS_BACKPOINTERS_H
|
||||
|
||||
#include "btree_cache.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_update.h"
|
||||
#include "buckets.h"
|
||||
#include "error.h"
|
||||
#include "super.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/iter.h"
|
||||
#include "btree/update.h"
|
||||
#include "init/error.h"
|
||||
|
||||
static inline u64 swab40(u64 x)
|
||||
{
|
||||
@ -6,25 +6,30 @@
|
||||
*/
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "alloc_background.h"
|
||||
#include "backpointers.h"
|
||||
#include "bset.h"
|
||||
#include "btree_gc.h"
|
||||
#include "btree_update.h"
|
||||
#include "buckets.h"
|
||||
#include "buckets_waiting_for_journal.h"
|
||||
#include "disk_accounting.h"
|
||||
#include "ec.h"
|
||||
#include "error.h"
|
||||
#include "inode.h"
|
||||
#include "movinggc.h"
|
||||
#include "rebalance.h"
|
||||
#include "recovery.h"
|
||||
#include "recovery_passes.h"
|
||||
#include "reflink.h"
|
||||
#include "replicas.h"
|
||||
#include "subvolume.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/background.h"
|
||||
#include "alloc/backpointers.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/buckets_waiting_for_journal.h"
|
||||
#include "alloc/replicas.h"
|
||||
|
||||
#include "btree/bset.h"
|
||||
#include "btree/check.h"
|
||||
#include "btree/update.h"
|
||||
|
||||
#include "data/copygc.h"
|
||||
#include "data/ec.h"
|
||||
#include "data/rebalance.h"
|
||||
#include "data/reflink.h"
|
||||
|
||||
#include "fs/inode.h"
|
||||
|
||||
#include "journal/init.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/recovery.h"
|
||||
#include "init/passes.h"
|
||||
|
||||
#include <linux/preempt.h>
|
||||
|
||||
@ -288,11 +293,8 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
|
||||
/* We don't yet do btree key updates correctly for when we're RW */
|
||||
BUG_ON(test_bit(BCH_FS_rw, &c->flags));
|
||||
|
||||
bkey_for_each_ptr_decode(k.k, ptrs_c, p, entry_c) {
|
||||
ret = bch2_check_fix_ptr(trans, k, p, entry_c, &do_update);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
bkey_for_each_ptr_decode(k.k, ptrs_c, p, entry_c)
|
||||
try(bch2_check_fix_ptr(trans, k, p, entry_c, &do_update));
|
||||
|
||||
if (do_update) {
|
||||
struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, k);
|
||||
@ -602,11 +604,9 @@ static int __mark_pointer(struct btree_trans *trans, struct bch_dev *ca,
|
||||
u32 *dst_sectors = p->has_ec ? &a->stripe_sectors :
|
||||
!p->ptr.cached ? &a->dirty_sectors :
|
||||
&a->cached_sectors;
|
||||
int ret = bch2_bucket_ref_update(trans, ca, k, &p->ptr, sectors, ptr_data_type,
|
||||
a->gen, a->data_type, dst_sectors);
|
||||
try(bch2_bucket_ref_update(trans, ca, k, &p->ptr, sectors, ptr_data_type,
|
||||
a->gen, a->data_type, dst_sectors));
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (insert)
|
||||
alloc_data_type_set(a, ptr_data_type);
|
||||
return 0;
|
||||
@ -746,9 +746,7 @@ static int bch2_trigger_stripe_ptr(struct btree_trans *trans,
|
||||
gc_stripe_unlock(m);
|
||||
|
||||
acc.replicas.data_type = data_type;
|
||||
int ret = bch2_disk_accounting_mod(trans, &acc, §ors, 1, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_disk_accounting_mod(trans, &acc, §ors, 1, true));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -767,7 +765,6 @@ static int __trigger_extent(struct btree_trans *trans,
|
||||
enum bch_data_type data_type = bkey_is_btree_ptr(k.k)
|
||||
? BCH_DATA_btree
|
||||
: BCH_DATA_user;
|
||||
int ret = 0;
|
||||
|
||||
s64 replicas_sectors = 0;
|
||||
|
||||
@ -783,7 +780,7 @@ static int __trigger_extent(struct btree_trans *trans,
|
||||
|
||||
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
|
||||
s64 disk_sectors = 0;
|
||||
ret = bch2_trigger_pointer(trans, btree_id, level, k, p, entry, &disk_sectors, flags);
|
||||
int ret = bch2_trigger_pointer(trans, btree_id, level, k, p, entry, &disk_sectors, flags);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -793,16 +790,12 @@ static int __trigger_extent(struct btree_trans *trans,
|
||||
continue;
|
||||
|
||||
if (p.ptr.cached) {
|
||||
ret = bch2_mod_dev_cached_sectors(trans, p.ptr.dev, disk_sectors, gc);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_mod_dev_cached_sectors(trans, p.ptr.dev, disk_sectors, gc));
|
||||
} else if (!p.has_ec) {
|
||||
replicas_sectors += disk_sectors;
|
||||
replicas_entry_add_dev(&acc_replicas_key.replicas, p.ptr.dev);
|
||||
} else {
|
||||
ret = bch2_trigger_stripe_ptr(trans, k, p, data_type, disk_sectors, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_trigger_stripe_ptr(trans, k, p, data_type, disk_sectors, flags));
|
||||
|
||||
/*
|
||||
* There may be other dirty pointers in this extent, but
|
||||
@ -817,10 +810,8 @@ static int __trigger_extent(struct btree_trans *trans,
|
||||
if (!insert)
|
||||
bch2_u64s_neg(compression_acct, ARRAY_SIZE(compression_acct));
|
||||
|
||||
ret = bch2_disk_accounting_mod2(trans, gc, compression_acct,
|
||||
compression, cur_compression_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_disk_accounting_mod2(trans, gc, compression_acct,
|
||||
compression, cur_compression_type));
|
||||
|
||||
compression_acct[0] = 1;
|
||||
compression_acct[1] = 0;
|
||||
@ -834,26 +825,18 @@ static int __trigger_extent(struct btree_trans *trans,
|
||||
}
|
||||
}
|
||||
|
||||
if (acc_replicas_key.replicas.nr_devs) {
|
||||
ret = bch2_disk_accounting_mod(trans, &acc_replicas_key, &replicas_sectors, 1, gc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (acc_replicas_key.replicas.nr_devs)
|
||||
try(bch2_disk_accounting_mod(trans, &acc_replicas_key, &replicas_sectors, 1, gc));
|
||||
|
||||
if (acc_replicas_key.replicas.nr_devs && !level && k.k->p.snapshot) {
|
||||
ret = bch2_disk_accounting_mod2_nr(trans, gc, &replicas_sectors, 1, snapshot, k.k->p.snapshot);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (acc_replicas_key.replicas.nr_devs && !level && k.k->p.snapshot)
|
||||
try(bch2_disk_accounting_mod2_nr(trans, gc, &replicas_sectors, 1, snapshot, k.k->p.snapshot));
|
||||
|
||||
if (cur_compression_type) {
|
||||
if (!insert)
|
||||
bch2_u64s_neg(compression_acct, ARRAY_SIZE(compression_acct));
|
||||
|
||||
ret = bch2_disk_accounting_mod2(trans, gc, compression_acct,
|
||||
compression, cur_compression_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_disk_accounting_mod2(trans, gc, compression_acct,
|
||||
compression, cur_compression_type));
|
||||
}
|
||||
|
||||
if (level) {
|
||||
@ -864,18 +847,14 @@ static int __trigger_extent(struct btree_trans *trans,
|
||||
!leaf_node ? (insert ? 1 : -1) : 0,
|
||||
};
|
||||
|
||||
ret = bch2_disk_accounting_mod2(trans, gc, v, btree, btree_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_disk_accounting_mod2(trans, gc, v, btree, btree_id));
|
||||
} else {
|
||||
s64 v[3] = {
|
||||
insert ? 1 : -1,
|
||||
insert ? k.k->size : -((s64) k.k->size),
|
||||
replicas_sectors,
|
||||
};
|
||||
ret = bch2_disk_accounting_mod2(trans, gc, v, inum, k.k->p.inode);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_disk_accounting_mod2(trans, gc, v, inum, k.k->p.inode));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -902,23 +881,15 @@ int bch2_trigger_extent(struct btree_trans *trans,
|
||||
return 0;
|
||||
|
||||
if (flags & (BTREE_TRIGGER_transactional|BTREE_TRIGGER_gc)) {
|
||||
if (old.k->type) {
|
||||
int ret = __trigger_extent(trans, btree, level, old,
|
||||
flags & ~BTREE_TRIGGER_insert);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (old.k->type)
|
||||
try(__trigger_extent(trans, btree, level, old,
|
||||
flags & ~BTREE_TRIGGER_insert));
|
||||
|
||||
if (new.k->type) {
|
||||
int ret = __trigger_extent(trans, btree, level, new.s_c,
|
||||
flags & ~BTREE_TRIGGER_overwrite);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (new.k->type)
|
||||
try(__trigger_extent(trans, btree, level, new.s_c,
|
||||
flags & ~BTREE_TRIGGER_overwrite));
|
||||
|
||||
int ret = bch2_trigger_extent_rebalance(trans, old, new.s_c, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_trigger_extent_rebalance(trans, old, new.s_c, flags));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1074,10 +1045,8 @@ static int bch2_trans_mark_metadata_sectors(struct btree_trans *trans,
|
||||
min_t(u64, bucket_to_sector(ca, b + 1), end) - start;
|
||||
|
||||
if (b != *bucket && *bucket_sectors) {
|
||||
int ret = bch2_trans_mark_metadata_bucket(trans, ca, *bucket,
|
||||
type, *bucket_sectors, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_trans_mark_metadata_bucket(trans, ca, *bucket,
|
||||
type, *bucket_sectors, flags));
|
||||
|
||||
*bucket_sectors = 0;
|
||||
}
|
||||
@ -1101,40 +1070,28 @@ static int __bch2_trans_mark_dev_sb(struct btree_trans *trans, struct bch_dev *c
|
||||
|
||||
u64 bucket = 0;
|
||||
unsigned i, bucket_sectors = 0;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < layout.nr_superblocks; i++) {
|
||||
u64 offset = le64_to_cpu(layout.sb_offset[i]);
|
||||
|
||||
if (offset == BCH_SB_SECTOR) {
|
||||
ret = bch2_trans_mark_metadata_sectors(trans, ca,
|
||||
if (offset == BCH_SB_SECTOR)
|
||||
try(bch2_trans_mark_metadata_sectors(trans, ca,
|
||||
0, BCH_SB_SECTOR,
|
||||
BCH_DATA_sb, &bucket, &bucket_sectors, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
BCH_DATA_sb, &bucket, &bucket_sectors, flags));
|
||||
|
||||
ret = bch2_trans_mark_metadata_sectors(trans, ca, offset,
|
||||
try(bch2_trans_mark_metadata_sectors(trans, ca, offset,
|
||||
offset + (1 << layout.sb_max_size_bits),
|
||||
BCH_DATA_sb, &bucket, &bucket_sectors, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
BCH_DATA_sb, &bucket, &bucket_sectors, flags));
|
||||
}
|
||||
|
||||
if (bucket_sectors) {
|
||||
ret = bch2_trans_mark_metadata_bucket(trans, ca,
|
||||
bucket, BCH_DATA_sb, bucket_sectors, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (bucket_sectors)
|
||||
try(bch2_trans_mark_metadata_bucket(trans, ca,
|
||||
bucket, BCH_DATA_sb, bucket_sectors, flags));
|
||||
|
||||
for (i = 0; i < ca->journal.nr; i++) {
|
||||
ret = bch2_trans_mark_metadata_bucket(trans, ca,
|
||||
for (i = 0; i < ca->journal.nr; i++)
|
||||
try(bch2_trans_mark_metadata_bucket(trans, ca,
|
||||
ca->journal.buckets[i],
|
||||
BCH_DATA_journal, ca->mi.bucket_size, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
BCH_DATA_journal, ca->mi.bucket_size, flags));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -8,9 +8,9 @@
|
||||
#ifndef _BUCKETS_H
|
||||
#define _BUCKETS_H
|
||||
|
||||
#include "buckets_types.h"
|
||||
#include "extents.h"
|
||||
#include "sb-members.h"
|
||||
#include "alloc/buckets_types.h"
|
||||
#include "data/extents.h"
|
||||
#include "sb/members.h"
|
||||
|
||||
static inline u64 sector_to_bucket(const struct bch_dev *ca, sector_t s)
|
||||
{
|
||||
@ -3,7 +3,7 @@
|
||||
#define _BUCKETS_TYPES_H
|
||||
|
||||
#include "bcachefs_format.h"
|
||||
#include "util.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#define BUCKET_JOURNAL_SEQ_BITS 16
|
||||
|
||||
828
libbcachefs/alloc/check.c
Normal file
828
libbcachefs/alloc/check.c
Normal file
@ -0,0 +1,828 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "bcachefs.h"
|
||||
|
||||
#include "alloc/background.h"
|
||||
#include "alloc/check.h"
|
||||
#include "alloc/lru.h"
|
||||
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/update.h"
|
||||
|
||||
#include "data/ec.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/progress.h"
|
||||
|
||||
/*
|
||||
* This synthesizes deleted extents for holes, similar to BTREE_ITER_slots for
|
||||
* extents style btrees, but works on non-extents btrees:
|
||||
*/
|
||||
static struct bkey_s_c bch2_get_key_or_hole(struct btree_iter *iter, struct bpos end, struct bkey *hole)
|
||||
{
|
||||
struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
|
||||
|
||||
if (bkey_err(k))
|
||||
return k;
|
||||
|
||||
if (k.k->type) {
|
||||
return k;
|
||||
} else {
|
||||
struct btree_iter iter2;
|
||||
struct bpos next;
|
||||
|
||||
bch2_trans_copy_iter(&iter2, iter);
|
||||
|
||||
struct btree_path *path = btree_iter_path(iter->trans, iter);
|
||||
if (!bpos_eq(path->l[0].b->key.k.p, SPOS_MAX))
|
||||
end = bkey_min(end, bpos_nosnap_successor(path->l[0].b->key.k.p));
|
||||
|
||||
end = bkey_min(end, POS(iter->pos.inode, iter->pos.offset + U32_MAX - 1));
|
||||
|
||||
/*
|
||||
* btree node min/max is a closed interval, upto takes a half
|
||||
* open interval:
|
||||
*/
|
||||
k = bch2_btree_iter_peek_max(&iter2, end);
|
||||
next = iter2.pos;
|
||||
bch2_trans_iter_exit(&iter2);
|
||||
|
||||
BUG_ON(next.offset >= iter->pos.offset + U32_MAX);
|
||||
|
||||
if (bkey_err(k))
|
||||
return k;
|
||||
|
||||
bkey_init(hole);
|
||||
hole->p = iter->pos;
|
||||
|
||||
bch2_key_resize(hole, next.offset - iter->pos.offset);
|
||||
return (struct bkey_s_c) { hole, NULL };
|
||||
}
|
||||
}
|
||||
|
||||
static bool next_bucket(struct bch_fs *c, struct bch_dev **ca, struct bpos *bucket)
|
||||
{
|
||||
if (*ca) {
|
||||
if (bucket->offset < (*ca)->mi.first_bucket)
|
||||
bucket->offset = (*ca)->mi.first_bucket;
|
||||
|
||||
if (bucket->offset < (*ca)->mi.nbuckets)
|
||||
return true;
|
||||
|
||||
bch2_dev_put(*ca);
|
||||
*ca = NULL;
|
||||
bucket->inode++;
|
||||
bucket->offset = 0;
|
||||
}
|
||||
|
||||
guard(rcu)();
|
||||
*ca = __bch2_next_dev_idx(c, bucket->inode, NULL);
|
||||
if (*ca) {
|
||||
*bucket = POS((*ca)->dev_idx, (*ca)->mi.first_bucket);
|
||||
bch2_dev_get(*ca);
|
||||
}
|
||||
|
||||
return *ca != NULL;
|
||||
}
|
||||
|
||||
static struct bkey_s_c bch2_get_key_or_real_bucket_hole(struct btree_iter *iter,
|
||||
struct bch_dev **ca, struct bkey *hole)
|
||||
{
|
||||
struct bch_fs *c = iter->trans->c;
|
||||
struct bkey_s_c k;
|
||||
again:
|
||||
k = bch2_get_key_or_hole(iter, POS_MAX, hole);
|
||||
if (bkey_err(k))
|
||||
return k;
|
||||
|
||||
*ca = bch2_dev_iterate_noerror(c, *ca, k.k->p.inode);
|
||||
|
||||
if (!k.k->type) {
|
||||
struct bpos hole_start = bkey_start_pos(k.k);
|
||||
|
||||
if (!*ca || !bucket_valid(*ca, hole_start.offset)) {
|
||||
if (!next_bucket(c, ca, &hole_start))
|
||||
return bkey_s_c_null;
|
||||
|
||||
bch2_btree_iter_set_pos(iter, hole_start);
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (k.k->p.offset > (*ca)->mi.nbuckets)
|
||||
bch2_key_resize(hole, (*ca)->mi.nbuckets - hole_start.offset);
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
int bch2_need_discard_or_freespace_err(struct btree_trans *trans,
|
||||
struct bkey_s_c alloc_k,
|
||||
bool set, bool discard, bool repair)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
enum bch_fsck_flags flags = FSCK_CAN_IGNORE|(repair ? FSCK_CAN_FIX : 0);
|
||||
enum bch_sb_error_id err_id = discard
|
||||
? BCH_FSCK_ERR_need_discard_key_wrong
|
||||
: BCH_FSCK_ERR_freespace_key_wrong;
|
||||
enum btree_id btree = discard ? BTREE_ID_need_discard : BTREE_ID_freespace;
|
||||
CLASS(printbuf, buf)();
|
||||
|
||||
bch2_bkey_val_to_text(&buf, c, alloc_k);
|
||||
|
||||
int ret = __bch2_fsck_err(NULL, trans, flags, err_id,
|
||||
"bucket incorrectly %sset in %s btree\n%s",
|
||||
set ? "" : "un",
|
||||
bch2_btree_id_str(btree),
|
||||
buf.buf);
|
||||
if (bch2_err_matches(ret, BCH_ERR_fsck_ignore) ||
|
||||
bch2_err_matches(ret, BCH_ERR_fsck_errors_not_fixed))
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline_for_stack
|
||||
int bch2_check_alloc_key(struct btree_trans *trans,
|
||||
struct bkey_s_c alloc_k,
|
||||
struct btree_iter *alloc_iter,
|
||||
struct btree_iter *discard_iter,
|
||||
struct btree_iter *freespace_iter,
|
||||
struct btree_iter *bucket_gens_iter)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bch_alloc_v4 a_convert;
|
||||
const struct bch_alloc_v4 *a;
|
||||
unsigned gens_offset;
|
||||
struct bkey_s_c k;
|
||||
CLASS(printbuf, buf)();
|
||||
int ret = 0;
|
||||
|
||||
CLASS(bch2_dev_bucket_tryget_noerror, ca)(c, alloc_k.k->p);
|
||||
if (fsck_err_on(!ca,
|
||||
trans, alloc_key_to_missing_dev_bucket,
|
||||
"alloc key for invalid device:bucket %llu:%llu",
|
||||
alloc_k.k->p.inode, alloc_k.k->p.offset))
|
||||
ret = bch2_btree_delete_at(trans, alloc_iter, 0);
|
||||
if (!ca)
|
||||
return ret;
|
||||
|
||||
if (!ca->mi.freespace_initialized)
|
||||
return 0;
|
||||
|
||||
a = bch2_alloc_to_v4(alloc_k, &a_convert);
|
||||
|
||||
bch2_btree_iter_set_pos(discard_iter, alloc_k.k->p);
|
||||
k = bkey_try(bch2_btree_iter_peek_slot(discard_iter));
|
||||
|
||||
bool is_discarded = a->data_type == BCH_DATA_need_discard;
|
||||
if (need_discard_or_freespace_err_on(!!k.k->type != is_discarded,
|
||||
trans, alloc_k, !is_discarded, true, true))
|
||||
try(bch2_btree_bit_mod_iter(trans, discard_iter, is_discarded));
|
||||
|
||||
bch2_btree_iter_set_pos(freespace_iter, alloc_freespace_pos(alloc_k.k->p, *a));
|
||||
k = bkey_try(bch2_btree_iter_peek_slot(freespace_iter));
|
||||
|
||||
bool is_free = a->data_type == BCH_DATA_free;
|
||||
if (need_discard_or_freespace_err_on(!!k.k->type != is_free,
|
||||
trans, alloc_k, !is_free, false, true))
|
||||
try(bch2_btree_bit_mod_iter(trans, freespace_iter, is_free));
|
||||
|
||||
bch2_btree_iter_set_pos(bucket_gens_iter, alloc_gens_pos(alloc_k.k->p, &gens_offset));
|
||||
k = bkey_try(bch2_btree_iter_peek_slot(bucket_gens_iter));
|
||||
|
||||
if (fsck_err_on(a->gen != alloc_gen(k, gens_offset),
|
||||
trans, bucket_gens_key_wrong,
|
||||
"incorrect gen in bucket_gens btree (got %u should be %u)\n%s",
|
||||
alloc_gen(k, gens_offset), a->gen,
|
||||
(printbuf_reset(&buf),
|
||||
bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
|
||||
struct bkey_i_bucket_gens *g =
|
||||
errptr_try(bch2_trans_kmalloc(trans, sizeof(*g)));
|
||||
|
||||
if (k.k->type == KEY_TYPE_bucket_gens) {
|
||||
bkey_reassemble(&g->k_i, k);
|
||||
} else {
|
||||
bkey_bucket_gens_init(&g->k_i);
|
||||
g->k.p = alloc_gens_pos(alloc_k.k->p, &gens_offset);
|
||||
}
|
||||
|
||||
g->v.gens[gens_offset] = a->gen;
|
||||
|
||||
try(bch2_trans_update(trans, bucket_gens_iter, &g->k_i, 0));
|
||||
}
|
||||
fsck_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline_for_stack
|
||||
int bch2_check_alloc_hole_freespace(struct btree_trans *trans,
|
||||
struct bch_dev *ca,
|
||||
struct bpos start,
|
||||
struct bpos *end,
|
||||
struct btree_iter *freespace_iter)
|
||||
{
|
||||
CLASS(printbuf, buf)();
|
||||
int ret = 0;
|
||||
|
||||
if (!ca->mi.freespace_initialized)
|
||||
return 0;
|
||||
|
||||
bch2_btree_iter_set_pos(freespace_iter, start);
|
||||
|
||||
struct bkey_s_c k = bkey_try(bch2_btree_iter_peek_slot(freespace_iter));
|
||||
|
||||
*end = bkey_min(k.k->p, *end);
|
||||
|
||||
if (fsck_err_on(k.k->type != KEY_TYPE_set,
|
||||
trans, freespace_hole_missing,
|
||||
"hole in alloc btree missing in freespace btree\n"
|
||||
"device %llu buckets %llu-%llu",
|
||||
freespace_iter->pos.inode,
|
||||
freespace_iter->pos.offset,
|
||||
end->offset)) {
|
||||
struct bkey_i *update =
|
||||
errptr_try(bch2_trans_kmalloc(trans, sizeof(*update)));
|
||||
|
||||
bkey_init(&update->k);
|
||||
update->k.type = KEY_TYPE_set;
|
||||
update->k.p = freespace_iter->pos;
|
||||
bch2_key_resize(&update->k,
|
||||
min_t(u64, U32_MAX, end->offset -
|
||||
freespace_iter->pos.offset));
|
||||
|
||||
try(bch2_trans_update(trans, freespace_iter, update, 0));
|
||||
}
|
||||
fsck_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline_for_stack
|
||||
int bch2_check_alloc_hole_bucket_gens(struct btree_trans *trans,
|
||||
struct bpos start,
|
||||
struct bpos *end,
|
||||
struct btree_iter *bucket_gens_iter)
|
||||
{
|
||||
CLASS(printbuf, buf)();
|
||||
unsigned gens_offset, gens_end_offset;
|
||||
int ret = 0;
|
||||
|
||||
bch2_btree_iter_set_pos(bucket_gens_iter, alloc_gens_pos(start, &gens_offset));
|
||||
|
||||
struct bkey_s_c k = bkey_try(bch2_btree_iter_peek_slot(bucket_gens_iter));
|
||||
|
||||
if (bkey_cmp(alloc_gens_pos(start, &gens_offset),
|
||||
alloc_gens_pos(*end, &gens_end_offset)))
|
||||
gens_end_offset = KEY_TYPE_BUCKET_GENS_NR;
|
||||
|
||||
if (k.k->type == KEY_TYPE_bucket_gens) {
|
||||
struct bkey_i_bucket_gens g;
|
||||
bool need_update = false;
|
||||
|
||||
bkey_reassemble(&g.k_i, k);
|
||||
|
||||
for (unsigned i = gens_offset; i < gens_end_offset; i++) {
|
||||
if (fsck_err_on(g.v.gens[i], trans,
|
||||
bucket_gens_hole_wrong,
|
||||
"hole in alloc btree at %llu:%llu with nonzero gen in bucket_gens btree (%u)",
|
||||
bucket_gens_pos_to_alloc(k.k->p, i).inode,
|
||||
bucket_gens_pos_to_alloc(k.k->p, i).offset,
|
||||
g.v.gens[i])) {
|
||||
g.v.gens[i] = 0;
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_update) {
|
||||
struct bkey_i *u = errptr_try(bch2_trans_kmalloc(trans, sizeof(g)));
|
||||
|
||||
memcpy(u, &g, sizeof(g));
|
||||
|
||||
try(bch2_trans_update(trans, bucket_gens_iter, u, 0));
|
||||
}
|
||||
}
|
||||
|
||||
*end = bkey_min(*end, bucket_gens_pos_to_alloc(bpos_nosnap_successor(k.k->p), 0));
|
||||
fsck_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct check_discard_freespace_key_async {
|
||||
struct work_struct work;
|
||||
struct bch_fs *c;
|
||||
struct bbpos pos;
|
||||
};
|
||||
|
||||
static int bch2_recheck_discard_freespace_key(struct btree_trans *trans, struct bbpos pos)
|
||||
{
|
||||
CLASS(btree_iter, iter)(trans, pos.btree, pos.pos, 0);
|
||||
struct bkey_s_c k = bkey_try(bch2_btree_iter_peek_slot(&iter));
|
||||
|
||||
u8 gen;
|
||||
return k.k->type != KEY_TYPE_set
|
||||
? __bch2_check_discard_freespace_key(trans, &iter, &gen, FSCK_ERR_SILENT)
|
||||
: 0;
|
||||
}
|
||||
|
||||
static void check_discard_freespace_key_work(struct work_struct *work)
|
||||
{
|
||||
struct check_discard_freespace_key_async *w =
|
||||
container_of(work, struct check_discard_freespace_key_async, work);
|
||||
|
||||
bch2_trans_do(w->c, bch2_recheck_discard_freespace_key(trans, w->pos));
|
||||
enumerated_ref_put(&w->c->writes, BCH_WRITE_REF_check_discard_freespace_key);
|
||||
kfree(w);
|
||||
}
|
||||
|
||||
int __bch2_check_discard_freespace_key(struct btree_trans *trans, struct btree_iter *iter, u8 *gen,
|
||||
enum bch_fsck_flags fsck_flags)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
enum bch_data_type state = iter->btree_id == BTREE_ID_need_discard
|
||||
? BCH_DATA_need_discard
|
||||
: BCH_DATA_free;
|
||||
CLASS(printbuf, buf)();
|
||||
int ret = 0;
|
||||
|
||||
bool async_repair = fsck_flags & FSCK_ERR_NO_LOG;
|
||||
fsck_flags |= FSCK_CAN_FIX|FSCK_CAN_IGNORE;
|
||||
|
||||
struct bpos bucket = iter->pos;
|
||||
bucket.offset &= ~(~0ULL << 56);
|
||||
u64 genbits = iter->pos.offset & (~0ULL << 56);
|
||||
|
||||
struct btree_iter alloc_iter;
|
||||
struct bkey_s_c alloc_k = bkey_try(bch2_bkey_get_iter(trans, &alloc_iter,
|
||||
BTREE_ID_alloc, bucket,
|
||||
async_repair ? BTREE_ITER_cached : 0));
|
||||
|
||||
if (!bch2_dev_bucket_exists(c, bucket)) {
|
||||
if (__fsck_err(trans, fsck_flags,
|
||||
need_discard_freespace_key_to_invalid_dev_bucket,
|
||||
"entry in %s btree for nonexistant dev:bucket %llu:%llu",
|
||||
bch2_btree_id_str(iter->btree_id), bucket.inode, bucket.offset))
|
||||
goto delete;
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct bch_alloc_v4 a_convert;
|
||||
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(alloc_k, &a_convert);
|
||||
|
||||
if (a->data_type != state ||
|
||||
(state == BCH_DATA_free &&
|
||||
genbits != alloc_freespace_genbits(*a))) {
|
||||
if (__fsck_err(trans, fsck_flags,
|
||||
need_discard_freespace_key_bad,
|
||||
"%s\nincorrectly set at %s:%llu:%llu:0 (free %u, genbits %llu should be %llu)",
|
||||
(bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf),
|
||||
bch2_btree_id_str(iter->btree_id),
|
||||
iter->pos.inode,
|
||||
iter->pos.offset,
|
||||
a->data_type == state,
|
||||
genbits >> 56, alloc_freespace_genbits(*a) >> 56))
|
||||
goto delete;
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*gen = a->gen;
|
||||
out:
|
||||
fsck_err:
|
||||
bch2_set_btree_iter_dontneed(&alloc_iter);
|
||||
bch2_trans_iter_exit(&alloc_iter);
|
||||
return ret;
|
||||
delete:
|
||||
if (!async_repair) {
|
||||
ret = bch2_btree_bit_mod_iter(trans, iter, false) ?:
|
||||
bch2_trans_commit(trans, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc) ?:
|
||||
bch_err_throw(c, transaction_restart_commit);
|
||||
goto out;
|
||||
} else {
|
||||
/*
|
||||
* We can't repair here when called from the allocator path: the
|
||||
* commit will recurse back into the allocator
|
||||
*/
|
||||
struct check_discard_freespace_key_async *w =
|
||||
kzalloc(sizeof(*w), GFP_KERNEL);
|
||||
if (!w)
|
||||
goto out;
|
||||
|
||||
if (!enumerated_ref_tryget(&c->writes, BCH_WRITE_REF_check_discard_freespace_key)) {
|
||||
kfree(w);
|
||||
goto out;
|
||||
}
|
||||
|
||||
INIT_WORK(&w->work, check_discard_freespace_key_work);
|
||||
w->c = c;
|
||||
w->pos = BBPOS(iter->btree_id, iter->pos);
|
||||
queue_work(c->write_ref_wq, &w->work);
|
||||
|
||||
ret = 1; /* don't allocate from this bucket */
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
static int bch2_check_discard_freespace_key(struct btree_trans *trans, struct btree_iter *iter)
|
||||
{
|
||||
u8 gen;
|
||||
int ret = __bch2_check_discard_freespace_key(trans, iter, &gen, 0);
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've already checked that generation numbers in the bucket_gens btree are
|
||||
* valid for buckets that exist; this just checks for keys for nonexistent
|
||||
* buckets.
|
||||
*/
|
||||
static noinline_for_stack
|
||||
int bch2_check_bucket_gens_key(struct btree_trans *trans,
|
||||
struct btree_iter *iter,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bkey_i_bucket_gens g;
|
||||
u64 start = bucket_gens_pos_to_alloc(k.k->p, 0).offset;
|
||||
u64 end = bucket_gens_pos_to_alloc(bpos_nosnap_successor(k.k->p), 0).offset;
|
||||
u64 b;
|
||||
bool need_update = false;
|
||||
CLASS(printbuf, buf)();
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(k.k->type != KEY_TYPE_bucket_gens);
|
||||
bkey_reassemble(&g.k_i, k);
|
||||
|
||||
CLASS(bch2_dev_tryget_noerror, ca)(c, k.k->p.inode);
|
||||
if (!ca) {
|
||||
if (fsck_err(trans, bucket_gens_to_invalid_dev,
|
||||
"bucket_gens key for invalid device:\n%s",
|
||||
(bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
|
||||
return bch2_btree_delete_at(trans, iter, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fsck_err_on(end <= ca->mi.first_bucket ||
|
||||
start >= ca->mi.nbuckets,
|
||||
trans, bucket_gens_to_invalid_buckets,
|
||||
"bucket_gens key for invalid buckets:\n%s",
|
||||
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
|
||||
return bch2_btree_delete_at(trans, iter, 0);
|
||||
}
|
||||
|
||||
for (b = start; b < ca->mi.first_bucket; b++)
|
||||
if (fsck_err_on(g.v.gens[b & KEY_TYPE_BUCKET_GENS_MASK],
|
||||
trans, bucket_gens_nonzero_for_invalid_buckets,
|
||||
"bucket_gens key has nonzero gen for invalid bucket")) {
|
||||
g.v.gens[b & KEY_TYPE_BUCKET_GENS_MASK] = 0;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
for (b = ca->mi.nbuckets; b < end; b++)
|
||||
if (fsck_err_on(g.v.gens[b & KEY_TYPE_BUCKET_GENS_MASK],
|
||||
trans, bucket_gens_nonzero_for_invalid_buckets,
|
||||
"bucket_gens key has nonzero gen for invalid bucket")) {
|
||||
g.v.gens[b & KEY_TYPE_BUCKET_GENS_MASK] = 0;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
if (need_update) {
|
||||
struct bkey_i *u = errptr_try(bch2_trans_kmalloc(trans, sizeof(g)));
|
||||
|
||||
memcpy(u, &g, sizeof(g));
|
||||
return bch2_trans_update(trans, iter, u, 0);
|
||||
}
|
||||
fsck_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_check_alloc_info(struct bch_fs *c)
|
||||
{
|
||||
struct btree_iter iter, discard_iter, freespace_iter, bucket_gens_iter;
|
||||
struct bch_dev *ca = NULL;
|
||||
struct bkey hole;
|
||||
struct bkey_s_c k;
|
||||
int ret = 0;
|
||||
|
||||
struct progress_indicator_state progress;
|
||||
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_alloc));
|
||||
|
||||
CLASS(btree_trans, trans)(c);
|
||||
bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, POS_MIN,
|
||||
BTREE_ITER_prefetch);
|
||||
bch2_trans_iter_init(trans, &discard_iter, BTREE_ID_need_discard, POS_MIN,
|
||||
BTREE_ITER_prefetch);
|
||||
bch2_trans_iter_init(trans, &freespace_iter, BTREE_ID_freespace, POS_MIN,
|
||||
BTREE_ITER_prefetch);
|
||||
bch2_trans_iter_init(trans, &bucket_gens_iter, BTREE_ID_bucket_gens, POS_MIN,
|
||||
BTREE_ITER_prefetch);
|
||||
|
||||
while (1) {
|
||||
struct bpos next;
|
||||
|
||||
bch2_trans_begin(trans);
|
||||
|
||||
k = bch2_get_key_or_real_bucket_hole(&iter, &ca, &hole);
|
||||
ret = bkey_err(k);
|
||||
if (ret)
|
||||
goto bkey_err;
|
||||
|
||||
if (!k.k)
|
||||
break;
|
||||
|
||||
progress_update_iter(trans, &progress, &iter);
|
||||
|
||||
if (k.k->type) {
|
||||
next = bpos_nosnap_successor(k.k->p);
|
||||
|
||||
ret = bch2_check_alloc_key(trans,
|
||||
k, &iter,
|
||||
&discard_iter,
|
||||
&freespace_iter,
|
||||
&bucket_gens_iter);
|
||||
BUG_ON(ret > 0);
|
||||
if (ret)
|
||||
goto bkey_err;
|
||||
} else {
|
||||
next = k.k->p;
|
||||
|
||||
ret = bch2_check_alloc_hole_freespace(trans, ca,
|
||||
bkey_start_pos(k.k),
|
||||
&next,
|
||||
&freespace_iter) ?:
|
||||
bch2_check_alloc_hole_bucket_gens(trans,
|
||||
bkey_start_pos(k.k),
|
||||
&next,
|
||||
&bucket_gens_iter);
|
||||
BUG_ON(ret > 0);
|
||||
if (ret)
|
||||
goto bkey_err;
|
||||
}
|
||||
|
||||
ret = bch2_trans_commit(trans, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc);
|
||||
if (ret)
|
||||
goto bkey_err;
|
||||
|
||||
bch2_btree_iter_set_pos(&iter, next);
|
||||
bkey_err:
|
||||
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
|
||||
continue;
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
bch2_trans_iter_exit(&bucket_gens_iter);
|
||||
bch2_trans_iter_exit(&freespace_iter);
|
||||
bch2_trans_iter_exit(&discard_iter);
|
||||
bch2_trans_iter_exit(&iter);
|
||||
bch2_dev_put(ca);
|
||||
ca = NULL;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
try(for_each_btree_key(trans, iter,
|
||||
BTREE_ID_need_discard, POS_MIN,
|
||||
BTREE_ITER_prefetch, k,
|
||||
bch2_check_discard_freespace_key(trans, &iter)));
|
||||
|
||||
bch2_trans_iter_init(trans, &iter, BTREE_ID_freespace, POS_MIN,
|
||||
BTREE_ITER_prefetch);
|
||||
while (1) {
|
||||
bch2_trans_begin(trans);
|
||||
k = bch2_btree_iter_peek(&iter);
|
||||
if (!k.k)
|
||||
break;
|
||||
|
||||
ret = bkey_err(k) ?:
|
||||
bch2_check_discard_freespace_key(trans, &iter);
|
||||
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
|
||||
ret = 0;
|
||||
continue;
|
||||
}
|
||||
if (ret) {
|
||||
CLASS(printbuf, buf)();
|
||||
bch2_bkey_val_to_text(&buf, c, k);
|
||||
bch_err(c, "while checking %s", buf.buf);
|
||||
break;
|
||||
}
|
||||
|
||||
bch2_btree_iter_set_pos(&iter, bpos_nosnap_successor(iter.pos));
|
||||
}
|
||||
bch2_trans_iter_exit(&iter);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = for_each_btree_key_commit(trans, iter,
|
||||
BTREE_ID_bucket_gens, POS_MIN,
|
||||
BTREE_ITER_prefetch, k,
|
||||
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
|
||||
bch2_check_bucket_gens_key(trans, &iter, k));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
|
||||
struct btree_iter *alloc_iter,
|
||||
struct bkey_buf *last_flushed)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bch_alloc_v4 a_convert;
|
||||
const struct bch_alloc_v4 *a;
|
||||
CLASS(printbuf, buf)();
|
||||
int ret = 0;
|
||||
|
||||
struct bkey_s_c alloc_k = bkey_try(bch2_btree_iter_peek(alloc_iter));
|
||||
if (!alloc_k.k)
|
||||
return 0;
|
||||
|
||||
CLASS(bch2_dev_tryget_noerror, ca)(c, alloc_k.k->p.inode);
|
||||
if (!ca)
|
||||
return 0;
|
||||
|
||||
a = bch2_alloc_to_v4(alloc_k, &a_convert);
|
||||
|
||||
u64 lru_idx = alloc_lru_idx_fragmentation(*a, ca);
|
||||
if (lru_idx)
|
||||
try(bch2_lru_check_set(trans, BCH_LRU_BUCKET_FRAGMENTATION,
|
||||
bucket_to_u64(alloc_k.k->p),
|
||||
lru_idx, alloc_k, last_flushed));
|
||||
|
||||
if (a->data_type == BCH_DATA_cached) {
|
||||
if (fsck_err_on(!a->io_time[READ],
|
||||
trans, alloc_key_cached_but_read_time_zero,
|
||||
"cached bucket with read_time 0\n%s",
|
||||
(printbuf_reset(&buf),
|
||||
bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
|
||||
struct bkey_i_alloc_v4 *a_mut =
|
||||
errptr_try(bch2_alloc_to_v4_mut(trans, alloc_k));
|
||||
|
||||
a_mut->v.io_time[READ] = bch2_current_io_time(c, READ);
|
||||
try(bch2_trans_update(trans, alloc_iter,
|
||||
&a_mut->k_i, BTREE_TRIGGER_norun));
|
||||
|
||||
a = &a_mut->v;
|
||||
}
|
||||
|
||||
ret = bch2_lru_check_set(trans, alloc_k.k->p.inode,
|
||||
bucket_to_u64(alloc_k.k->p),
|
||||
a->io_time[READ],
|
||||
alloc_k, last_flushed);
|
||||
}
|
||||
fsck_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
|
||||
{
|
||||
struct bkey_buf last_flushed;
|
||||
bch2_bkey_buf_init(&last_flushed);
|
||||
bkey_init(&last_flushed.k->k);
|
||||
|
||||
struct progress_indicator_state progress;
|
||||
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_alloc));
|
||||
|
||||
CLASS(btree_trans, trans)(c);
|
||||
int ret = for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
|
||||
POS_MIN, BTREE_ITER_prefetch, k,
|
||||
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
|
||||
progress_update_iter(trans, &progress, &iter);
|
||||
bch2_check_alloc_to_lru_ref(trans, &iter, &last_flushed);
|
||||
}))?: bch2_check_stripe_to_lru_refs(trans);
|
||||
|
||||
bch2_bkey_buf_exit(&last_flushed, c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
|
||||
u64 bucket_start, u64 bucket_end)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
struct bkey_s_c k;
|
||||
struct bkey hole;
|
||||
struct bpos end = POS(ca->dev_idx, bucket_end);
|
||||
unsigned long last_updated = jiffies;
|
||||
int ret;
|
||||
|
||||
BUG_ON(bucket_start > bucket_end);
|
||||
BUG_ON(bucket_end > ca->mi.nbuckets);
|
||||
|
||||
CLASS(btree_trans, trans)(c);
|
||||
bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc,
|
||||
POS(ca->dev_idx, max_t(u64, ca->mi.first_bucket, bucket_start)),
|
||||
BTREE_ITER_prefetch);
|
||||
/*
|
||||
* Scan the alloc btree for every bucket on @ca, and add buckets to the
|
||||
* freespace/need_discard/need_gc_gens btrees as needed:
|
||||
*/
|
||||
while (1) {
|
||||
if (time_after(jiffies, last_updated + HZ * 10)) {
|
||||
bch_info(ca, "%s: currently at %llu/%llu",
|
||||
__func__, iter.pos.offset, ca->mi.nbuckets);
|
||||
last_updated = jiffies;
|
||||
}
|
||||
|
||||
bch2_trans_begin(trans);
|
||||
|
||||
if (bkey_ge(iter.pos, end)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
k = bch2_get_key_or_hole(&iter, end, &hole);
|
||||
ret = bkey_err(k);
|
||||
if (ret)
|
||||
goto bkey_err;
|
||||
|
||||
if (k.k->type) {
|
||||
/*
|
||||
* We process live keys in the alloc btree one at a
|
||||
* time:
|
||||
*/
|
||||
struct bch_alloc_v4 a_convert;
|
||||
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &a_convert);
|
||||
|
||||
ret = bch2_bucket_do_index(trans, ca, k, a, true) ?:
|
||||
bch2_trans_commit(trans, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc);
|
||||
if (ret)
|
||||
goto bkey_err;
|
||||
|
||||
bch2_btree_iter_advance(&iter);
|
||||
} else {
|
||||
struct bkey_i *freespace;
|
||||
|
||||
freespace = bch2_trans_kmalloc(trans, sizeof(*freespace));
|
||||
ret = PTR_ERR_OR_ZERO(freespace);
|
||||
if (ret)
|
||||
goto bkey_err;
|
||||
|
||||
bkey_init(&freespace->k);
|
||||
freespace->k.type = KEY_TYPE_set;
|
||||
freespace->k.p = k.k->p;
|
||||
freespace->k.size = k.k->size;
|
||||
|
||||
ret = bch2_btree_insert_trans(trans, BTREE_ID_freespace, freespace, 0) ?:
|
||||
bch2_trans_commit(trans, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc);
|
||||
if (ret)
|
||||
goto bkey_err;
|
||||
|
||||
bch2_btree_iter_set_pos(&iter, k.k->p);
|
||||
}
|
||||
bkey_err:
|
||||
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
|
||||
continue;
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
bch2_trans_iter_exit(&iter);
|
||||
|
||||
if (ret < 0) {
|
||||
bch_err_msg(ca, ret, "initializing free space");
|
||||
return ret;
|
||||
}
|
||||
|
||||
scoped_guard(mutex, &c->sb_lock) {
|
||||
struct bch_member *m = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx);
|
||||
SET_BCH_MEMBER_FREESPACE_INITIALIZED(m, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bch2_fs_freespace_init(struct bch_fs *c)
|
||||
{
|
||||
if (c->sb.features & BIT_ULL(BCH_FEATURE_small_image))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We can crash during the device add path, so we need to check this on
|
||||
* every mount:
|
||||
*/
|
||||
|
||||
bool doing_init = false;
|
||||
for_each_member_device(c, ca) {
|
||||
if (ca->mi.freespace_initialized)
|
||||
continue;
|
||||
|
||||
if (!doing_init) {
|
||||
bch_info(c, "initializing freespace");
|
||||
doing_init = true;
|
||||
}
|
||||
|
||||
int ret = bch2_dev_freespace_init(c, ca, 0, ca->mi.nbuckets);
|
||||
if (ret) {
|
||||
bch2_dev_put(ca);
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (doing_init) {
|
||||
guard(mutex)(&c->sb_lock);
|
||||
bch2_write_super(c);
|
||||
bch_verbose(c, "done initializing freespace");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
28
libbcachefs/alloc/check.h
Normal file
28
libbcachefs/alloc/check.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _BCACHEFS_ALLOC_CHECK_H
|
||||
#define _BCACHEFS_ALLOC_CHECK_H
|
||||
|
||||
int bch2_need_discard_or_freespace_err(struct btree_trans *, struct bkey_s_c, bool, bool, bool);
|
||||
|
||||
#define need_discard_or_freespace_err(...) \
|
||||
fsck_err_wrap(bch2_need_discard_or_freespace_err(__VA_ARGS__))
|
||||
|
||||
#define need_discard_or_freespace_err_on(cond, ...) \
|
||||
(unlikely(cond) ? need_discard_or_freespace_err(__VA_ARGS__) : false)
|
||||
|
||||
int __bch2_check_discard_freespace_key(struct btree_trans *, struct btree_iter *, u8 *,
|
||||
enum bch_fsck_flags);
|
||||
|
||||
static inline int bch2_check_discard_freespace_key_async(struct btree_trans *trans, struct btree_iter *iter, u8 *gen)
|
||||
{
|
||||
return __bch2_check_discard_freespace_key(trans, iter, gen, FSCK_ERR_NO_LOG);
|
||||
}
|
||||
|
||||
int bch2_check_alloc_info(struct bch_fs *);
|
||||
int bch2_check_alloc_to_lru_refs(struct bch_fs *);
|
||||
|
||||
int bch2_dev_freespace_init(struct bch_fs *, struct bch_dev *, u64, u64);
|
||||
int bch2_fs_freespace_init(struct bch_fs *);
|
||||
|
||||
#endif /* _BCACHEFS_ALLOC_CHECK_H */
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "bcachefs.h"
|
||||
#include "disk_groups.h"
|
||||
#include "sb-members.h"
|
||||
#include "super-io.h"
|
||||
|
||||
#include "alloc/disk_groups.h"
|
||||
|
||||
#include "init/dev.h"
|
||||
|
||||
#include "sb/members.h"
|
||||
#include "sb/io.h"
|
||||
|
||||
#include <linux/sort.h>
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#ifndef _BCACHEFS_DISK_GROUPS_TYPES_H
|
||||
#define _BCACHEFS_DISK_GROUPS_TYPES_H
|
||||
|
||||
#include "init/dev_types.h"
|
||||
|
||||
struct bch_disk_group_cpu {
|
||||
bool deleted;
|
||||
u16 parent;
|
||||
@ -12,24 +12,27 @@
|
||||
*/
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "alloc_background.h"
|
||||
#include "alloc_foreground.h"
|
||||
#include "backpointers.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_update.h"
|
||||
#include "btree_gc.h"
|
||||
#include "buckets.h"
|
||||
#include "buckets_waiting_for_journal.h"
|
||||
#include "clock.h"
|
||||
#include "debug.h"
|
||||
#include "disk_groups.h"
|
||||
#include "ec.h"
|
||||
#include "error.h"
|
||||
#include "io_write.h"
|
||||
#include "journal.h"
|
||||
#include "movinggc.h"
|
||||
#include "nocow_locking.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "alloc/background.h"
|
||||
#include "alloc/backpointers.h"
|
||||
#include "alloc/buckets_waiting_for_journal.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/check.h"
|
||||
#include "alloc/disk_groups.h"
|
||||
#include "alloc/foreground.h"
|
||||
|
||||
#include "btree/iter.h"
|
||||
#include "btree/update.h"
|
||||
#include "btree/check.h"
|
||||
|
||||
#include "data/copygc.h"
|
||||
#include "data/ec.h"
|
||||
#include "data/nocow_locking.h"
|
||||
#include "data/write.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "journal/journal.h"
|
||||
#include "util/clock.h"
|
||||
|
||||
#include <linux/math64.h>
|
||||
#include <linux/rculist.h>
|
||||
@ -863,9 +866,7 @@ static int bucket_alloc_set_partial(struct bch_fs *c,
|
||||
scoped_guard(rcu)
|
||||
bch2_dev_rcu(c, ob->dev)->nr_partial_buckets--;
|
||||
|
||||
int ret = add_new_bucket(c, req, ob);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(add_new_bucket(c, req, ob));
|
||||
}
|
||||
}
|
||||
|
||||
@ -891,13 +892,9 @@ static int __open_bucket_add_buckets(struct btree_trans *trans,
|
||||
open_bucket_for_each(c, &req->ptrs, ob, i)
|
||||
__clear_bit(ob->dev, req->devs_may_alloc.d);
|
||||
|
||||
ret = bucket_alloc_set_writepoint(c, req);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bucket_alloc_set_writepoint(c, req));
|
||||
|
||||
ret = bucket_alloc_set_partial(c, req);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bucket_alloc_set_partial(c, req));
|
||||
|
||||
if (req->ec) {
|
||||
ret = bucket_alloc_from_stripe(trans, req, _cl);
|
||||
@ -1219,10 +1216,7 @@ int bch2_alloc_sectors_start_trans(struct btree_trans *trans,
|
||||
unsigned write_points_nr;
|
||||
int i;
|
||||
|
||||
struct alloc_request *req = bch2_trans_kmalloc_nomemzero(trans, sizeof(*req));
|
||||
int ret = PTR_ERR_OR_ZERO(req);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
struct alloc_request *req = errptr_try(bch2_trans_kmalloc_nomemzero(trans, sizeof(*req)));
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BCACHEFS_ERASURE_CODING))
|
||||
erasure_code = false;
|
||||
@ -1245,7 +1239,7 @@ retry:
|
||||
|
||||
req->data_type = req->wp->data_type;
|
||||
|
||||
ret = bch2_trans_relock(trans);
|
||||
int ret = bch2_trans_relock(trans);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
#define _BCACHEFS_ALLOC_FOREGROUND_H
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "buckets.h"
|
||||
#include "alloc_types.h"
|
||||
#include "extents.h"
|
||||
#include "io_write_types.h"
|
||||
#include "sb-members.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/types.h"
|
||||
#include "data/extents.h"
|
||||
#include "data/write_types.h"
|
||||
#include "sb/members.h"
|
||||
|
||||
#include <linux/hash.h>
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "alloc_background.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_update.h"
|
||||
#include "btree_write_buffer.h"
|
||||
#include "ec.h"
|
||||
#include "error.h"
|
||||
#include "lru.h"
|
||||
#include "progress.h"
|
||||
#include "recovery.h"
|
||||
|
||||
#include "alloc/background.h"
|
||||
#include "alloc/lru.h"
|
||||
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/iter.h"
|
||||
#include "btree/update.h"
|
||||
#include "btree/write_buffer.h"
|
||||
|
||||
#include "data/ec.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/progress.h"
|
||||
#include "init/recovery.h"
|
||||
|
||||
/* KEY_TYPE_lru is obsolete: */
|
||||
int bch2_lru_validate(struct bch_fs *c, struct bkey_s_c k,
|
||||
@ -79,16 +83,13 @@ int bch2_lru_check_set(struct btree_trans *trans,
|
||||
struct bkey_buf *last_flushed)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
int ret = 0;
|
||||
|
||||
CLASS(btree_iter, lru_iter)(trans, BTREE_ID_lru, lru_pos(lru_id, dev_bucket, time), 0);
|
||||
struct bkey_s_c lru_k = bch2_btree_iter_peek_slot(&lru_iter);
|
||||
int ret = bkey_err(lru_k);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_s_c lru_k = bkey_try(bch2_btree_iter_peek_slot(&lru_iter));
|
||||
|
||||
if (lru_k.k->type != KEY_TYPE_set) {
|
||||
ret = bch2_btree_write_buffer_maybe_flush(trans, referring_k, last_flushed);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_write_buffer_maybe_flush(trans, referring_k, last_flushed));
|
||||
|
||||
CLASS(printbuf, buf)();
|
||||
prt_printf(&buf, "missing %s lru entry at pos ", bch2_lru_types[lru_type(lru_k)]);
|
||||
@ -96,11 +97,8 @@ int bch2_lru_check_set(struct btree_trans *trans,
|
||||
prt_newline(&buf);
|
||||
bch2_bkey_val_to_text(&buf, c, referring_k);
|
||||
|
||||
if (fsck_err(trans, alloc_key_to_missing_lru_entry, "%s", buf.buf)) {
|
||||
ret = bch2_lru_set(trans, lru_id, dev_bucket, time);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (fsck_err(trans, alloc_key_to_missing_lru_entry, "%s", buf.buf))
|
||||
try(bch2_lru_set(trans, lru_id, dev_bucket, time));
|
||||
}
|
||||
fsck_err:
|
||||
return ret;
|
||||
@ -175,22 +173,18 @@ static int bch2_check_lru_key(struct btree_trans *trans,
|
||||
struct bch_fs *c = trans->c;
|
||||
CLASS(printbuf, buf1)();
|
||||
CLASS(printbuf, buf2)();
|
||||
int ret = 0;
|
||||
|
||||
struct bbpos bp = lru_pos_to_bp(lru_k);
|
||||
|
||||
CLASS(btree_iter, iter)(trans, bp.btree, bp.pos, 0);
|
||||
struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter);
|
||||
int ret = bkey_err(k);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_s_c k = bkey_try(bch2_btree_iter_peek_slot(&iter));
|
||||
|
||||
enum bch_lru_type type = lru_type(lru_k);
|
||||
u64 idx = bkey_lru_type_idx(c, type, k);
|
||||
|
||||
if (lru_pos_time(lru_k.k->p) != idx) {
|
||||
ret = bch2_btree_write_buffer_maybe_flush(trans, lru_k, last_flushed);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_write_buffer_maybe_flush(trans, lru_k, last_flushed));
|
||||
|
||||
if (fsck_err(trans, lru_entry_bad,
|
||||
"incorrect lru entry: lru %s time %llu\n"
|
||||
@ -1,11 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "buckets.h"
|
||||
#include "disk_accounting.h"
|
||||
#include "journal.h"
|
||||
#include "replicas.h"
|
||||
#include "super-io.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/replicas.h"
|
||||
|
||||
#include "journal/journal.h"
|
||||
|
||||
#include "sb/io.h"
|
||||
|
||||
#include <linux/sort.h>
|
||||
|
||||
@ -565,14 +568,11 @@ int bch2_sb_replicas_to_cpu_replicas(struct bch_fs *c)
|
||||
struct bch_sb_field_replicas *sb_v1;
|
||||
struct bch_sb_field_replicas_v0 *sb_v0;
|
||||
struct bch_replicas_cpu new_r = { 0, 0, NULL };
|
||||
int ret = 0;
|
||||
|
||||
if ((sb_v1 = bch2_sb_field_get(c->disk_sb.sb, replicas)))
|
||||
ret = __bch2_sb_replicas_to_cpu_replicas(sb_v1, &new_r);
|
||||
try(__bch2_sb_replicas_to_cpu_replicas(sb_v1, &new_r));
|
||||
else if ((sb_v0 = bch2_sb_field_get(c->disk_sb.sb, replicas_v0)))
|
||||
ret = __bch2_sb_replicas_v0_to_cpu_replicas(sb_v0, &new_r);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(__bch2_sb_replicas_v0_to_cpu_replicas(sb_v0, &new_r));
|
||||
|
||||
bch2_cpu_replicas_sort(&new_r);
|
||||
|
||||
@ -682,9 +682,7 @@ static int bch2_cpu_replicas_validate(struct bch_replicas_cpu *cpu_r,
|
||||
struct bch_replicas_entry_v1 *e =
|
||||
cpu_replicas_entry(cpu_r, i);
|
||||
|
||||
int ret = bch2_replicas_entry_sb_validate(e, sb, err);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_replicas_entry_sb_validate(e, sb, err));
|
||||
|
||||
if (i + 1 < cpu_r->nr) {
|
||||
struct bch_replicas_entry_v1 *n =
|
||||
@ -707,14 +705,11 @@ static int bch2_sb_replicas_validate(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
enum bch_validate_flags flags, struct printbuf *err)
|
||||
{
|
||||
struct bch_sb_field_replicas *sb_r = field_to_type(f, replicas);
|
||||
|
||||
struct bch_replicas_cpu cpu_r;
|
||||
int ret;
|
||||
try(__bch2_sb_replicas_to_cpu_replicas(sb_r, &cpu_r));
|
||||
|
||||
ret = __bch2_sb_replicas_to_cpu_replicas(sb_r, &cpu_r);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bch2_cpu_replicas_validate(&cpu_r, sb, err);
|
||||
int ret = bch2_cpu_replicas_validate(&cpu_r, sb, err);
|
||||
kfree(cpu_r.entries);
|
||||
return ret;
|
||||
}
|
||||
@ -746,14 +741,11 @@ static int bch2_sb_replicas_v0_validate(struct bch_sb *sb, struct bch_sb_field *
|
||||
enum bch_validate_flags flags, struct printbuf *err)
|
||||
{
|
||||
struct bch_sb_field_replicas_v0 *sb_r = field_to_type(f, replicas_v0);
|
||||
|
||||
struct bch_replicas_cpu cpu_r;
|
||||
int ret;
|
||||
try(__bch2_sb_replicas_v0_to_cpu_replicas(sb_r, &cpu_r));
|
||||
|
||||
ret = __bch2_sb_replicas_v0_to_cpu_replicas(sb_r, &cpu_r);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bch2_cpu_replicas_validate(&cpu_r, sb, err);
|
||||
int ret = bch2_cpu_replicas_validate(&cpu_r, sb, err);
|
||||
kfree(cpu_r.entries);
|
||||
return ret;
|
||||
}
|
||||
@ -2,9 +2,9 @@
|
||||
#ifndef _BCACHEFS_REPLICAS_H
|
||||
#define _BCACHEFS_REPLICAS_H
|
||||
|
||||
#include "bkey.h"
|
||||
#include "eytzinger.h"
|
||||
#include "replicas_types.h"
|
||||
#include "btree/bkey.h"
|
||||
#include "alloc/replicas_types.h"
|
||||
#include "util/eytzinger.h"
|
||||
|
||||
void bch2_replicas_entry_sort(struct bch_replicas_entry_v1 *);
|
||||
void bch2_replicas_entry_to_text(struct printbuf *,
|
||||
@ -5,8 +5,8 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "clock_types.h"
|
||||
#include "fifo.h"
|
||||
#include "util/clock_types.h"
|
||||
#include "util/fifo.h"
|
||||
|
||||
#define BCH_WATERMARKS() \
|
||||
x(stripe) \
|
||||
@ -215,44 +215,53 @@
|
||||
#include <linux/unicode.h>
|
||||
|
||||
#include "bcachefs_format.h"
|
||||
#include "btree_journal_iter_types.h"
|
||||
#include "closure.h"
|
||||
#include "disk_accounting_types.h"
|
||||
#include "errcode.h"
|
||||
#include "fast_list.h"
|
||||
#include "fifo.h"
|
||||
#include "nocow_locking_types.h"
|
||||
#include "opts.h"
|
||||
#include "sb-errors_types.h"
|
||||
#include "seqmutex.h"
|
||||
#include "snapshot_types.h"
|
||||
#include "time_stats.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "alloc_types.h"
|
||||
#include "async_objs_types.h"
|
||||
#include "btree_gc_types.h"
|
||||
#include "btree_types.h"
|
||||
#include "btree_node_scan_types.h"
|
||||
#include "btree_write_buffer_types.h"
|
||||
#include "buckets_types.h"
|
||||
#include "buckets_waiting_for_journal_types.h"
|
||||
#include "clock_types.h"
|
||||
#include "disk_groups_types.h"
|
||||
#include "ec_types.h"
|
||||
#include "enumerated_ref_types.h"
|
||||
#include "journal_types.h"
|
||||
#include "keylist_types.h"
|
||||
#include "quota_types.h"
|
||||
#include "rebalance_types.h"
|
||||
#include "recovery_passes_types.h"
|
||||
#include "replicas_types.h"
|
||||
#include "sb-members_types.h"
|
||||
#include "subvolume_types.h"
|
||||
#include "super_types.h"
|
||||
#include "thread_with_file_types.h"
|
||||
#include "closure.h"
|
||||
|
||||
#include "trace.h"
|
||||
#include "util/clock_types.h"
|
||||
#include "util/enumerated_ref_types.h"
|
||||
#include "util/fast_list.h"
|
||||
#include "util/fifo.h"
|
||||
#include "util/seqmutex.h"
|
||||
#include "util/time_stats.h"
|
||||
#include "util/thread_with_file_types.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include "alloc/accounting_types.h"
|
||||
#include "alloc/buckets_types.h"
|
||||
#include "alloc/buckets_waiting_for_journal_types.h"
|
||||
#include "alloc/disk_groups_types.h"
|
||||
#include "alloc/replicas_types.h"
|
||||
#include "alloc/types.h"
|
||||
|
||||
#include "btree/check_types.h"
|
||||
#include "btree/journal_overlay_types.h"
|
||||
#include "btree/types.h"
|
||||
#include "btree/node_scan_types.h"
|
||||
#include "btree/write_buffer_types.h"
|
||||
|
||||
#include "data/ec_types.h"
|
||||
#include "data/keylist_types.h"
|
||||
#include "data/nocow_locking_types.h"
|
||||
#include "data/rebalance_types.h"
|
||||
|
||||
#include "debug/async_objs_types.h"
|
||||
#include "debug/trace.h"
|
||||
|
||||
#include "fs/quota_types.h"
|
||||
|
||||
#include "init/passes_types.h"
|
||||
#include "init/dev_types.h"
|
||||
|
||||
#include "journal/types.h"
|
||||
|
||||
#include "sb/errors_types.h"
|
||||
#include "sb/members_types.h"
|
||||
|
||||
#include "snapshots/snapshot_types.h"
|
||||
#include "snapshots/subvolume_types.h"
|
||||
|
||||
#define count_event(_c, _name) this_cpu_inc((_c)->counters[BCH_COUNTER_##_name])
|
||||
|
||||
@ -1156,8 +1165,6 @@ static inline int __bch2_err_trace(struct bch_fs *c, int err)
|
||||
|
||||
#define bch_err_throw(_c, _err) __bch2_err_trace(_c, -BCH_ERR_##_err)
|
||||
|
||||
extern struct wait_queue_head bch2_read_only_wait;
|
||||
|
||||
static inline bool bch2_ro_ref_tryget(struct bch_fs *c)
|
||||
{
|
||||
if (test_bit(BCH_FS_stopping, &c->flags))
|
||||
|
||||
@ -77,7 +77,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/uuid.h>
|
||||
#include <uapi/linux/magic.h>
|
||||
#include "vstructs.h"
|
||||
|
||||
#include "util/vstructs.h"
|
||||
|
||||
#ifdef __KERNEL__
|
||||
typedef uuid_t __uuid_t;
|
||||
@ -505,27 +506,27 @@ struct bch_sb_field {
|
||||
x(downgrade, 14) \
|
||||
x(recovery_passes, 15)
|
||||
|
||||
#include "alloc_background_format.h"
|
||||
#include "dirent_format.h"
|
||||
#include "disk_accounting_format.h"
|
||||
#include "disk_groups_format.h"
|
||||
#include "extents_format.h"
|
||||
#include "ec_format.h"
|
||||
#include "inode_format.h"
|
||||
#include "journal_seq_blacklist_format.h"
|
||||
#include "logged_ops_format.h"
|
||||
#include "lru_format.h"
|
||||
#include "quota_format.h"
|
||||
#include "recovery_passes_format.h"
|
||||
#include "reflink_format.h"
|
||||
#include "replicas_format.h"
|
||||
#include "snapshot_format.h"
|
||||
#include "subvolume_format.h"
|
||||
#include "sb-counters_format.h"
|
||||
#include "sb-downgrade_format.h"
|
||||
#include "sb-errors_format.h"
|
||||
#include "sb-members_format.h"
|
||||
#include "xattr_format.h"
|
||||
#include "alloc/accounting_format.h"
|
||||
#include "alloc/disk_groups_format.h"
|
||||
#include "alloc/lru_format.h"
|
||||
#include "alloc/replicas_format.h"
|
||||
#include "alloc/format.h"
|
||||
#include "data/ec_format.h"
|
||||
#include "data/extents_format.h"
|
||||
#include "data/reflink_format.h"
|
||||
#include "fs/dirent_format.h"
|
||||
#include "fs/inode_format.h"
|
||||
#include "fs/logged_ops_format.h"
|
||||
#include "fs/quota_format.h"
|
||||
#include "fs/xattr_format.h"
|
||||
#include "init/passes_format.h"
|
||||
#include "journal/seq_blacklist_format.h"
|
||||
#include "sb/counters_format.h"
|
||||
#include "sb/downgrade_format.h"
|
||||
#include "sb/errors_format.h"
|
||||
#include "sb/members_format.h"
|
||||
#include "snapshots/snapshot_format.h"
|
||||
#include "snapshots/subvolume_format.h"
|
||||
|
||||
enum bch_sb_field_type {
|
||||
#define x(f, nr) BCH_SB_FIELD_##f = nr,
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <linux/uuid.h>
|
||||
#include <asm/ioctl.h>
|
||||
#include "bcachefs_format.h"
|
||||
#include "bkey_types.h"
|
||||
#include "btree/bkey_types.h"
|
||||
|
||||
/*
|
||||
* Flags common to multiple ioctls:
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
#ifndef _BCACHEFS_BBPOS_H
|
||||
#define _BCACHEFS_BBPOS_H
|
||||
|
||||
#include "bbpos_types.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree/bbpos_types.h"
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/cache.h"
|
||||
|
||||
static inline int bbpos_cmp(struct bbpos l, struct bbpos r)
|
||||
{
|
||||
@ -1,11 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "bkey.h"
|
||||
#include "bkey_cmp.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "bset.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "btree/bkey.h"
|
||||
#include "btree/bkey_cmp.h"
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/bset.h"
|
||||
|
||||
#include "util/util.h"
|
||||
|
||||
const struct bkey_format bch2_bkey_format_current = BKEY_FORMAT_CURRENT;
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include "bcachefs_format.h"
|
||||
#include "bkey_types.h"
|
||||
#include "btree_types.h"
|
||||
#include "util.h"
|
||||
#include "vstructs.h"
|
||||
#include "btree/bkey_types.h"
|
||||
#include "btree/types.h"
|
||||
#include "util/util.h"
|
||||
#include "util/vstructs.h"
|
||||
|
||||
#if 0
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <linux/mempool.h>
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "bkey.h"
|
||||
#include "btree/bkey.h"
|
||||
|
||||
struct bkey_buf {
|
||||
struct bkey_i *k;
|
||||
@ -2,7 +2,7 @@
|
||||
#ifndef _BCACHEFS_BKEY_CMP_H
|
||||
#define _BCACHEFS_BKEY_CMP_H
|
||||
|
||||
#include "bkey.h"
|
||||
#include "btree/bkey.h"
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
static inline int __bkey_cmp_bits(const u64 *l, const u64 *r,
|
||||
@ -1,24 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "backpointers.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_types.h"
|
||||
#include "alloc_background.h"
|
||||
#include "dirent.h"
|
||||
#include "disk_accounting.h"
|
||||
#include "ec.h"
|
||||
#include "error.h"
|
||||
#include "extents.h"
|
||||
#include "inode.h"
|
||||
#include "io_misc.h"
|
||||
#include "lru.h"
|
||||
#include "quota.h"
|
||||
#include "reflink.h"
|
||||
#include "snapshot.h"
|
||||
#include "subvolume.h"
|
||||
#include "xattr.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/background.h"
|
||||
#include "alloc/backpointers.h"
|
||||
#include "alloc/lru.h"
|
||||
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/cache.h"
|
||||
|
||||
#include "data/ec.h"
|
||||
#include "data/extents.h"
|
||||
#include "data/io_misc.h"
|
||||
#include "data/reflink.h"
|
||||
|
||||
#include "fs/dirent.h"
|
||||
#include "fs/inode.h"
|
||||
#include "fs/quota.h"
|
||||
#include "fs/xattr.h"
|
||||
|
||||
#include "init/error.h"
|
||||
|
||||
#include "snapshots/snapshot.h"
|
||||
#include "snapshots/subvolume.h"
|
||||
|
||||
const char * const bch2_bkey_types[] = {
|
||||
#define x(name, nr, ...) #name,
|
||||
@ -2,7 +2,7 @@
|
||||
#ifndef _BCACHEFS_BKEY_METHODS_H
|
||||
#define _BCACHEFS_BKEY_METHODS_H
|
||||
|
||||
#include "bkey.h"
|
||||
#include "btree/bkey.h"
|
||||
|
||||
struct bch_fs;
|
||||
struct btree;
|
||||
@ -1,10 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "bcachefs.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "bkey_cmp.h"
|
||||
#include "bkey_sort.h"
|
||||
#include "bset.h"
|
||||
#include "extents.h"
|
||||
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/bkey_cmp.h"
|
||||
#include "btree/bkey_sort.h"
|
||||
#include "btree/bset.h"
|
||||
|
||||
#include "data/extents.h"
|
||||
|
||||
typedef int (*sort_cmp_fn)(const struct btree *,
|
||||
const struct bkey_packed *,
|
||||
@ -163,7 +165,7 @@ static inline int keep_unwritten_whiteouts_cmp(const struct btree *b,
|
||||
(long) l - (long) r;
|
||||
}
|
||||
|
||||
#include "btree_update_interior.h"
|
||||
#include "btree/interior.h"
|
||||
|
||||
/*
|
||||
* For sorting in the btree node write path: whiteouts not in the unwritten
|
||||
@ -7,11 +7,11 @@
|
||||
*/
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "btree_cache.h"
|
||||
#include "bset.h"
|
||||
#include "eytzinger.h"
|
||||
#include "trace.h"
|
||||
#include "util.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/bset.h"
|
||||
|
||||
#include "util/eytzinger.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <linux/unaligned.h>
|
||||
#include <linux/console.h>
|
||||
@ -6,11 +6,11 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "bkey.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "btree_types.h"
|
||||
#include "util.h" /* for time_stats */
|
||||
#include "vstructs.h"
|
||||
#include "btree/bkey.h"
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/types.h"
|
||||
#include "util/util.h" /* for time_stats */
|
||||
#include "util/vstructs.h"
|
||||
|
||||
/*
|
||||
* BKEYS:
|
||||
@ -1,17 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "bbpos.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_io.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_locking.h"
|
||||
#include "debug.h"
|
||||
#include "errcode.h"
|
||||
#include "error.h"
|
||||
#include "journal.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "btree/bbpos.h"
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/io.h"
|
||||
#include "btree/iter.h"
|
||||
#include "btree/locking.h"
|
||||
|
||||
#include "debug/debug.h"
|
||||
|
||||
#include "init/error.h"
|
||||
|
||||
#include "journal/journal.h"
|
||||
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/sched/mm.h>
|
||||
@ -269,10 +271,7 @@ int __bch2_btree_node_hash_insert(struct btree_cache *bc, struct btree *b)
|
||||
BUG_ON(b->hash_val);
|
||||
|
||||
b->hash_val = btree_ptr_hash_val(&b->key);
|
||||
int ret = rhashtable_lookup_insert_fast(&bc->table, &b->hash,
|
||||
bch_btree_cache_params);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(rhashtable_lookup_insert_fast(&bc->table, &b->hash, bch_btree_cache_params));
|
||||
|
||||
if (b->c.btree_id < BTREE_ID_NR)
|
||||
bc->nr_by_btree[b->c.btree_id]++;
|
||||
@ -406,9 +405,7 @@ static int __btree_node_reclaim(struct bch_fs *c, struct btree *b, bool flush)
|
||||
|
||||
lockdep_assert_held(&bc->lock);
|
||||
retry_unlocked:
|
||||
ret = __btree_node_reclaim_checks(c, b, flush, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(__btree_node_reclaim_checks(c, b, flush, false));
|
||||
|
||||
if (!six_trylock_intent(&b->c.lock)) {
|
||||
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_lock_intent]++;
|
||||
@ -1321,11 +1318,8 @@ int bch2_btree_node_prefetch(struct btree_trans *trans,
|
||||
if (b)
|
||||
return 0;
|
||||
|
||||
b = bch2_btree_node_fill(trans, path, k, btree_id,
|
||||
level, SIX_LOCK_read, false);
|
||||
int ret = PTR_ERR_OR_ZERO(b);
|
||||
if (ret)
|
||||
return ret;
|
||||
b = errptr_try(bch2_btree_node_fill(trans, path, k, btree_id,
|
||||
level, SIX_LOCK_read, false));
|
||||
if (b)
|
||||
six_unlock_read(&b->c.lock);
|
||||
return 0;
|
||||
@ -3,8 +3,8 @@
|
||||
#define _BCACHEFS_BTREE_CACHE_H
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "btree_types.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "btree/types.h"
|
||||
#include "btree/bkey_methods.h"
|
||||
|
||||
extern const char * const bch2_btree_node_flags[];
|
||||
|
||||
@ -5,36 +5,40 @@
|
||||
*/
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "alloc_background.h"
|
||||
#include "alloc_foreground.h"
|
||||
#include "backpointers.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "btree_journal_iter.h"
|
||||
#include "btree_key_cache.h"
|
||||
#include "btree_locking.h"
|
||||
#include "btree_node_scan.h"
|
||||
#include "btree_update_interior.h"
|
||||
#include "btree_io.h"
|
||||
#include "btree_gc.h"
|
||||
#include "buckets.h"
|
||||
#include "clock.h"
|
||||
#include "debug.h"
|
||||
#include "disk_accounting.h"
|
||||
#include "ec.h"
|
||||
#include "enumerated_ref.h"
|
||||
#include "error.h"
|
||||
#include "extents.h"
|
||||
#include "journal.h"
|
||||
#include "keylist.h"
|
||||
#include "move.h"
|
||||
#include "progress.h"
|
||||
#include "recovery_passes.h"
|
||||
#include "reflink.h"
|
||||
#include "recovery.h"
|
||||
#include "replicas.h"
|
||||
#include "super-io.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/background.h"
|
||||
#include "alloc/backpointers.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/foreground.h"
|
||||
#include "alloc/replicas.h"
|
||||
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/check.h"
|
||||
#include "btree/key_cache.h"
|
||||
#include "btree/locking.h"
|
||||
#include "btree/node_scan.h"
|
||||
#include "btree/interior.h"
|
||||
#include "btree/io.h"
|
||||
#include "btree/journal_overlay.h"
|
||||
|
||||
#include "data/ec.h"
|
||||
#include "data/extents.h"
|
||||
#include "data/keylist.h"
|
||||
#include "data/move.h"
|
||||
#include "data/reflink.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/progress.h"
|
||||
#include "init/passes.h"
|
||||
#include "init/recovery.h"
|
||||
|
||||
#include "journal/journal.h"
|
||||
|
||||
#include "sb/io.h"
|
||||
|
||||
#include "util/enumerated_ref.h"
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bitops.h>
|
||||
@ -144,7 +148,6 @@ static int set_node_min(struct bch_fs *c, struct btree *b, struct bpos new_min)
|
||||
static int set_node_max(struct bch_fs *c, struct btree *b, struct bpos new_max)
|
||||
{
|
||||
struct bkey_i_btree_ptr_v2 *new;
|
||||
int ret;
|
||||
|
||||
if (c->opts.verbose) {
|
||||
CLASS(printbuf, buf)();
|
||||
@ -156,9 +159,7 @@ static int set_node_max(struct bch_fs *c, struct btree *b, struct bpos new_max)
|
||||
bch_info(c, "%s(): %s", __func__, buf.buf);
|
||||
}
|
||||
|
||||
ret = bch2_journal_key_delete(c, b->c.btree_id, b->c.level + 1, b->key.k.p);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_journal_key_delete(c, b->c.btree_id, b->c.level + 1, b->key.k.p));
|
||||
|
||||
new = kmalloc_array(BKEY_BTREE_PTR_U64s_MAX, sizeof(u64), GFP_KERNEL);
|
||||
if (!new)
|
||||
@ -169,7 +170,7 @@ static int set_node_max(struct bch_fs *c, struct btree *b, struct bpos new_max)
|
||||
new->k.p = new_max;
|
||||
SET_BTREE_PTR_RANGE_UPDATED(&new->v, true);
|
||||
|
||||
ret = bch2_journal_key_insert_take(c, b->c.btree_id, b->c.level + 1, &new->k_i);
|
||||
int ret = bch2_journal_key_insert_take(c, b->c.btree_id, b->c.level + 1, &new->k_i);
|
||||
if (ret) {
|
||||
kfree(new);
|
||||
return ret;
|
||||
@ -220,11 +221,9 @@ static int btree_check_node_boundaries(struct btree_trans *trans, struct btree *
|
||||
if (bpos_lt(expected_start, cur->data->min_key)) { /* gap */
|
||||
if (b->c.level == 1 &&
|
||||
bpos_lt(*pulled_from_scan, cur->data->min_key)) {
|
||||
ret = bch2_get_scanned_nodes(c, b->c.btree_id, 0,
|
||||
expected_start,
|
||||
bpos_predecessor(cur->data->min_key));
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_get_scanned_nodes(c, b->c.btree_id, 0,
|
||||
expected_start,
|
||||
bpos_predecessor(cur->data->min_key)));
|
||||
|
||||
*pulled_from_scan = cur->data->min_key;
|
||||
ret = bch_err_throw(c, topology_repair_did_fill_from_scan);
|
||||
@ -318,10 +317,8 @@ static int btree_repair_node_end(struct btree_trans *trans, struct btree *b,
|
||||
"btree node with incorrect max_key%s", buf.buf)) {
|
||||
if (b->c.level == 1 &&
|
||||
bpos_lt(*pulled_from_scan, b->key.k.p)) {
|
||||
ret = bch2_get_scanned_nodes(c, b->c.btree_id, 0,
|
||||
bpos_successor(child->key.k.p), b->key.k.p);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_get_scanned_nodes(c, b->c.btree_id, 0,
|
||||
bpos_successor(child->key.k.p), b->key.k.p));
|
||||
|
||||
*pulled_from_scan = b->key.k.p;
|
||||
ret = bch_err_throw(c, topology_repair_did_fill_from_scan);
|
||||
@ -579,9 +576,7 @@ static int bch2_topology_check_root(struct btree_trans *trans, enum btree_id btr
|
||||
bch2_btree_root_alloc_fake_trans(trans, btree, 1);
|
||||
|
||||
bch2_shoot_down_journal_keys(c, btree, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX);
|
||||
ret = bch2_get_scanned_nodes(c, btree, 0, POS_MIN, SPOS_MAX);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_get_scanned_nodes(c, btree, 0, POS_MIN, SPOS_MAX));
|
||||
}
|
||||
out:
|
||||
*reconstructed_root = true;
|
||||
@ -650,11 +645,8 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
|
||||
struct btree_path *path = btree_iter_path(trans, iter);
|
||||
struct btree *b = path_l(path)->b;
|
||||
|
||||
if (*prev != b) {
|
||||
int ret = bch2_btree_node_check_topology(trans, b);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (*prev != b)
|
||||
try(bch2_btree_node_check_topology(trans, b));
|
||||
*prev = b;
|
||||
}
|
||||
|
||||
@ -894,9 +886,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
|
||||
alloc_data_type_set(&gc, gc.data_type);
|
||||
if (gc.data_type != old_gc.data_type ||
|
||||
gc.dirty_sectors != old_gc.dirty_sectors) {
|
||||
ret = bch2_alloc_key_to_dev_counters(trans, ca, &old_gc, &gc, BTREE_TRIGGER_gc);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_alloc_key_to_dev_counters(trans, ca, &old_gc, &gc, BTREE_TRIGGER_gc));
|
||||
|
||||
/*
|
||||
* Ugly: alloc_key_to_dev_counters(..., BTREE_TRIGGER_gc) is not
|
||||
@ -940,10 +930,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
|
||||
if (!bch2_alloc_v4_cmp(*old, new))
|
||||
return 0;
|
||||
|
||||
a = bch2_alloc_to_v4_mut(trans, k);
|
||||
ret = PTR_ERR_OR_ZERO(a);
|
||||
if (ret)
|
||||
return ret;
|
||||
a = errptr_try(bch2_alloc_to_v4_mut(trans, k));
|
||||
|
||||
a->v = new;
|
||||
|
||||
@ -1033,12 +1020,8 @@ static int bch2_gc_write_stripes_key(struct btree_trans *trans,
|
||||
if (fsck_err_on(bad,
|
||||
trans, stripe_sector_count_wrong,
|
||||
"%s", buf.buf)) {
|
||||
struct bkey_i_stripe *new;
|
||||
|
||||
new = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
|
||||
ret = PTR_ERR_OR_ZERO(new);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_i_stripe *new =
|
||||
errptr_try(bch2_trans_kmalloc(trans, bkey_bytes(k.k)));
|
||||
|
||||
bkey_reassemble(&new->k_i, k);
|
||||
|
||||
@ -1152,16 +1135,11 @@ static int bch2_alloc_write_oldest_gen(struct btree_trans *trans, struct bch_dev
|
||||
{
|
||||
struct bch_alloc_v4 a_convert;
|
||||
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &a_convert);
|
||||
struct bkey_i_alloc_v4 *a_mut;
|
||||
int ret;
|
||||
|
||||
if (a->oldest_gen == ca->oldest_gen[iter->pos.offset])
|
||||
return 0;
|
||||
|
||||
a_mut = bch2_alloc_to_v4_mut(trans, k);
|
||||
ret = PTR_ERR_OR_ZERO(a_mut);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_i_alloc_v4 *a_mut = errptr_try(bch2_alloc_to_v4_mut(trans, k));
|
||||
|
||||
a_mut->v.oldest_gen = ca->oldest_gen[iter->pos.offset];
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
#ifndef _BCACHEFS_BTREE_GC_H
|
||||
#define _BCACHEFS_BTREE_GC_H
|
||||
|
||||
#include "bkey.h"
|
||||
#include "btree_gc_types.h"
|
||||
#include "btree_types.h"
|
||||
#include "btree/bkey.h"
|
||||
#include "btree/check_types.h"
|
||||
#include "btree/types.h"
|
||||
|
||||
int bch2_check_topology(struct bch_fs *);
|
||||
int bch2_check_allocations(struct bch_fs *);
|
||||
@ -1,24 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "alloc_foreground.h"
|
||||
#include "btree_gc.h"
|
||||
#include "btree_io.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_journal_iter.h"
|
||||
#include "btree_key_cache.h"
|
||||
#include "btree_update_interior.h"
|
||||
#include "btree_write_buffer.h"
|
||||
#include "buckets.h"
|
||||
#include "disk_accounting.h"
|
||||
#include "enumerated_ref.h"
|
||||
#include "errcode.h"
|
||||
#include "error.h"
|
||||
#include "journal.h"
|
||||
#include "journal_io.h"
|
||||
#include "journal_reclaim.h"
|
||||
#include "replicas.h"
|
||||
#include "snapshot.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/foreground.h"
|
||||
#include "alloc/replicas.h"
|
||||
|
||||
#include "btree/check.h"
|
||||
#include "btree/io.h"
|
||||
#include "btree/iter.h"
|
||||
#include "btree/journal_overlay.h"
|
||||
#include "btree/interior.h"
|
||||
#include "btree/key_cache.h"
|
||||
#include "btree/write_buffer.h"
|
||||
|
||||
#include "journal/journal.h"
|
||||
#include "journal/io.h"
|
||||
#include "journal/reclaim.h"
|
||||
|
||||
#include "init/error.h"
|
||||
|
||||
#include "snapshots/snapshot.h"
|
||||
|
||||
#include "util/enumerated_ref.h"
|
||||
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/string_helpers.h>
|
||||
@ -99,7 +104,7 @@ inline void bch2_btree_node_prep_for_write(struct btree_trans *trans,
|
||||
bch2_trans_node_reinit_iter(trans, b);
|
||||
|
||||
/*
|
||||
* If the last bset has been written, or if it's gotten too big - start
|
||||
* If the last btree/bset.has been written, or if it's gotten too big - start
|
||||
* a new bset to insert into:
|
||||
*/
|
||||
if (want_new_bset(c, b))
|
||||
@ -579,11 +584,8 @@ static noinline int bch2_trans_commit_run_gc_triggers(struct btree_trans *trans)
|
||||
{
|
||||
trans_for_each_update(trans, i)
|
||||
if (btree_node_type_has_triggers(i->bkey_type) &&
|
||||
gc_visited(trans->c, gc_pos_btree(i->btree_id, i->level, i->k->k.p))) {
|
||||
int ret = run_one_mem_trigger(trans, i, i->flags|BTREE_TRIGGER_gc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
gc_visited(trans->c, gc_pos_btree(i->btree_id, i->level, i->k->k.p)))
|
||||
try(run_one_mem_trigger(trans, i, i->flags|BTREE_TRIGGER_gc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -637,11 +639,9 @@ bch2_trans_commit_write_locked(struct btree_trans *trans,
|
||||
* succeed:
|
||||
*/
|
||||
if (likely(!(flags & BCH_TRANS_COMMIT_no_journal_res))) {
|
||||
ret = bch2_trans_journal_res_get(trans,
|
||||
try(bch2_trans_journal_res_get(trans,
|
||||
(flags & BCH_WATERMARK_MASK)|
|
||||
JOURNAL_RES_GET_NONBLOCK);
|
||||
if (ret)
|
||||
return ret;
|
||||
JOURNAL_RES_GET_NONBLOCK));
|
||||
|
||||
if (unlikely(trans->journal_transaction_names))
|
||||
journal_transaction_name(trans);
|
||||
@ -664,9 +664,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans,
|
||||
|
||||
h = trans->hooks;
|
||||
while (h) {
|
||||
ret = h->fn(trans, h);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(h->fn(trans, h));
|
||||
h = h->next;
|
||||
}
|
||||
|
||||
@ -1,32 +1,39 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "alloc_foreground.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_gc.h"
|
||||
#include "btree_journal_iter.h"
|
||||
#include "btree_update.h"
|
||||
#include "btree_update_interior.h"
|
||||
#include "btree_io.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_locking.h"
|
||||
#include "buckets.h"
|
||||
#include "clock.h"
|
||||
#include "disk_groups.h"
|
||||
#include "enumerated_ref.h"
|
||||
#include "error.h"
|
||||
#include "extents.h"
|
||||
#include "io_write.h"
|
||||
#include "journal.h"
|
||||
#include "journal_reclaim.h"
|
||||
#include "keylist.h"
|
||||
#include "recovery_passes.h"
|
||||
#include "replicas.h"
|
||||
#include "sb-members.h"
|
||||
#include "super-io.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "alloc/buckets.h"
|
||||
#include "alloc/disk_groups.h"
|
||||
#include "alloc/foreground.h"
|
||||
#include "alloc/replicas.h"
|
||||
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/check.h"
|
||||
#include "btree/update.h"
|
||||
#include "btree/interior.h"
|
||||
#include "btree/io.h"
|
||||
#include "btree/iter.h"
|
||||
#include "btree/journal_overlay.h"
|
||||
#include "btree/locking.h"
|
||||
|
||||
#include "data/extents.h"
|
||||
#include "data/keylist.h"
|
||||
#include "data/write.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
#include "init/passes.h"
|
||||
|
||||
#include "journal/journal.h"
|
||||
#include "journal/reclaim.h"
|
||||
|
||||
#include "sb/members.h"
|
||||
#include "sb/io.h"
|
||||
|
||||
#include "util/clock.h"
|
||||
#include "util/enumerated_ref.h"
|
||||
|
||||
#include <linux/random.h>
|
||||
|
||||
@ -549,10 +556,9 @@ static int bch2_btree_reserve_get(struct btree_trans *trans,
|
||||
* Protects reaping from the btree node cache and using the btree node
|
||||
* open bucket reserve:
|
||||
*/
|
||||
int ret = bch2_btree_cache_cannibalize_lock(trans, cl);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_cache_cannibalize_lock(trans, cl));
|
||||
|
||||
int ret = 0;
|
||||
for (unsigned interior = 0; interior < 2; interior++) {
|
||||
struct prealloc_nodes *p = as->prealloc_nodes + interior;
|
||||
|
||||
@ -644,10 +650,7 @@ static void btree_update_new_nodes_mark_sb(struct btree_update *as)
|
||||
static int btree_update_nodes_written_trans(struct btree_trans *trans,
|
||||
struct btree_update *as)
|
||||
{
|
||||
struct jset_entry *e = bch2_trans_jset_entry_alloc(trans, as->journal_u64s);
|
||||
int ret = PTR_ERR_OR_ZERO(e);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct jset_entry *e = errptr_try(bch2_trans_jset_entry_alloc(trans, as->journal_u64s));
|
||||
|
||||
memcpy(e, as->journal_entries, as->journal_u64s * sizeof(u64));
|
||||
|
||||
@ -656,19 +659,15 @@ static int btree_update_nodes_written_trans(struct btree_trans *trans,
|
||||
for_each_keylist_key(&as->old_keys, k) {
|
||||
unsigned level = bkey_i_to_btree_ptr_v2(k)->v.mem_ptr;
|
||||
|
||||
ret = bch2_key_trigger_old(trans, as->btree_id, level, bkey_i_to_s_c(k),
|
||||
BTREE_TRIGGER_transactional);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_key_trigger_old(trans, as->btree_id, level, bkey_i_to_s_c(k),
|
||||
BTREE_TRIGGER_transactional));
|
||||
}
|
||||
|
||||
for_each_keylist_key(&as->new_keys, k) {
|
||||
unsigned level = bkey_i_to_btree_ptr_v2(k)->v.mem_ptr;
|
||||
|
||||
ret = bch2_key_trigger_new(trans, as->btree_id, level, bkey_i_to_s(k),
|
||||
BTREE_TRIGGER_transactional);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_key_trigger_new(trans, as->btree_id, level, bkey_i_to_s(k),
|
||||
BTREE_TRIGGER_transactional));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1364,13 +1363,10 @@ static int bch2_btree_set_root(struct btree_update *as,
|
||||
* Ensure no one is using the old root while we switch to the
|
||||
* new root:
|
||||
*/
|
||||
if (nofail) {
|
||||
if (nofail)
|
||||
bch2_btree_node_lock_write_nofail(trans, path, &old->c);
|
||||
} else {
|
||||
int ret = bch2_btree_node_lock_write(trans, path, &old->c);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
try(bch2_btree_node_lock_write(trans, path, &old->c));
|
||||
|
||||
bch2_btree_set_root_inmem(c, b);
|
||||
|
||||
@ -1634,9 +1630,7 @@ static int btree_split_insert_keys(struct btree_update *as,
|
||||
|
||||
bch2_btree_node_iter_init(&node_iter, b, &bch2_keylist_front(keys)->k.p);
|
||||
|
||||
int ret = bch2_btree_insert_keys_interior(as, trans, path, b, node_iter, keys);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_insert_keys_interior(as, trans, path, b, node_iter, keys));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1657,9 +1651,7 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
|
||||
BUG_ON(!parent && !btree_node_is_root(c, b));
|
||||
BUG_ON(parent && !btree_node_intent_locked(trans->paths + path, b->c.level + 1));
|
||||
|
||||
ret = bch2_btree_node_check_topology(trans, b);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_node_check_topology(trans, b));
|
||||
|
||||
if (b->nr.live_u64s > BTREE_SPLIT_THRESHOLD(c)) {
|
||||
struct btree *n[2];
|
||||
@ -1868,9 +1860,7 @@ static int bch2_btree_insert_node(struct btree_update *as, struct btree_trans *t
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = bch2_btree_node_lock_write(trans, path, &b->c);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_node_lock_write(trans, path, &b->c));
|
||||
|
||||
bch2_btree_node_prep_for_write(trans, path, b);
|
||||
|
||||
@ -2488,14 +2478,12 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
|
||||
int ret;
|
||||
|
||||
if (!skip_triggers) {
|
||||
ret = bch2_key_trigger_old(trans, b->c.btree_id, b->c.level + 1,
|
||||
bkey_i_to_s_c(&b->key),
|
||||
BTREE_TRIGGER_transactional) ?:
|
||||
bch2_key_trigger_new(trans, b->c.btree_id, b->c.level + 1,
|
||||
bkey_i_to_s(new_key),
|
||||
BTREE_TRIGGER_transactional);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_key_trigger_old(trans, b->c.btree_id, b->c.level + 1,
|
||||
bkey_i_to_s_c(&b->key),
|
||||
BTREE_TRIGGER_transactional));
|
||||
try(bch2_key_trigger_new(trans, b->c.btree_id, b->c.level + 1,
|
||||
bkey_i_to_s(new_key),
|
||||
BTREE_TRIGGER_transactional));
|
||||
}
|
||||
|
||||
if (new_hash) {
|
||||
@ -2528,11 +2516,8 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
|
||||
} else {
|
||||
BUG_ON(!btree_node_is_root(c, b));
|
||||
|
||||
struct jset_entry *e = bch2_trans_jset_entry_alloc(trans,
|
||||
jset_u64s(new_key->k.u64s));
|
||||
ret = PTR_ERR_OR_ZERO(e);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct jset_entry *e = errptr_try(bch2_trans_jset_entry_alloc(trans,
|
||||
jset_u64s(new_key->k.u64s)));
|
||||
|
||||
journal_entry_set(e,
|
||||
BCH_JSET_ENTRY_btree_root,
|
||||
@ -2581,9 +2566,7 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
|
||||
struct closure cl;
|
||||
int ret = 0;
|
||||
|
||||
ret = bch2_btree_path_upgrade(trans, path, b->c.level + 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_path_upgrade(trans, path, b->c.level + 1));
|
||||
|
||||
closure_init_stack(&cl);
|
||||
|
||||
@ -2593,11 +2576,8 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
|
||||
*/
|
||||
if (btree_ptr_hash_val(new_key) != b->hash_val) {
|
||||
ret = bch2_btree_cache_cannibalize_lock(trans, &cl);
|
||||
if (ret) {
|
||||
ret = drop_locks_do(trans, (closure_sync(&cl), 0));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
try(drop_locks_do(trans, (closure_sync(&cl), 0)));
|
||||
|
||||
new_hash = bch2_btree_node_mem_alloc(trans, false);
|
||||
ret = PTR_ERR_OR_ZERO(new_hash);
|
||||
@ -2,9 +2,9 @@
|
||||
#ifndef _BCACHEFS_BTREE_UPDATE_INTERIOR_H
|
||||
#define _BCACHEFS_BTREE_UPDATE_INTERIOR_H
|
||||
|
||||
#include "btree_cache.h"
|
||||
#include "btree_locking.h"
|
||||
#include "btree_update.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/locking.h"
|
||||
#include "btree/update.h"
|
||||
|
||||
#define BTREE_UPDATE_NODES_MAX ((BTREE_MAX_DEPTH - 2) * 2 + GC_MERGE_NODES)
|
||||
|
||||
@ -1,28 +1,36 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "async_objs.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "bkey_sort.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_io.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_locking.h"
|
||||
#include "btree_update.h"
|
||||
#include "btree_update_interior.h"
|
||||
#include "buckets.h"
|
||||
#include "checksum.h"
|
||||
#include "debug.h"
|
||||
#include "enumerated_ref.h"
|
||||
#include "error.h"
|
||||
#include "extents.h"
|
||||
#include "io_write.h"
|
||||
#include "journal_reclaim.h"
|
||||
#include "journal_seq_blacklist.h"
|
||||
#include "recovery.h"
|
||||
#include "super-io.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "alloc/buckets.h"
|
||||
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/bkey_sort.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/io.h"
|
||||
#include "btree/iter.h"
|
||||
#include "btree/locking.h"
|
||||
#include "btree/update.h"
|
||||
#include "btree/interior.h"
|
||||
|
||||
#include "data/checksum.h"
|
||||
#include "data/extents.h"
|
||||
#include "data/write.h"
|
||||
|
||||
#include "debug/async_objs.h"
|
||||
#include "debug/debug.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
#include "init/recovery.h"
|
||||
|
||||
#include "journal/reclaim.h"
|
||||
#include "journal/seq_blacklist.h"
|
||||
|
||||
#include "sb/io.h"
|
||||
|
||||
#include "util/enumerated_ref.h"
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/sched/mm.h>
|
||||
@ -1237,7 +1245,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
|
||||
-BCH_ERR_btree_node_read_err_fixable,
|
||||
c, ca, b, i, NULL,
|
||||
bset_blacklisted_journal_seq,
|
||||
"first btree node bset has blacklisted journal seq (%llu)",
|
||||
"first btree node btree/bset.has blacklisted journal seq (%llu)",
|
||||
le64_to_cpu(i->journal_seq));
|
||||
|
||||
btree_err_on(blacklisted && ptr_written,
|
||||
@ -2,12 +2,12 @@
|
||||
#ifndef _BCACHEFS_BTREE_IO_H
|
||||
#define _BCACHEFS_BTREE_IO_H
|
||||
|
||||
#include "bkey_methods.h"
|
||||
#include "bset.h"
|
||||
#include "btree_locking.h"
|
||||
#include "checksum.h"
|
||||
#include "extents.h"
|
||||
#include "io_write_types.h"
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/bset.h"
|
||||
#include "btree/locking.h"
|
||||
#include "data/checksum.h"
|
||||
#include "data/extents.h"
|
||||
#include "data/write_types.h"
|
||||
|
||||
struct bch_fs;
|
||||
struct btree_write;
|
||||
@ -1,23 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "bkey_methods.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_journal_iter.h"
|
||||
#include "btree_key_cache.h"
|
||||
#include "btree_locking.h"
|
||||
#include "btree_update.h"
|
||||
#include "debug.h"
|
||||
#include "error.h"
|
||||
#include "extents.h"
|
||||
#include "journal.h"
|
||||
#include "journal_io.h"
|
||||
#include "replicas.h"
|
||||
#include "snapshot.h"
|
||||
#include "super.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "alloc/replicas.h"
|
||||
|
||||
#include "btree/bkey_methods.h"
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/iter.h"
|
||||
#include "btree/journal_overlay.h"
|
||||
#include "btree/key_cache.h"
|
||||
#include "btree/locking.h"
|
||||
#include "btree/update.h"
|
||||
|
||||
#include "data/extents.h"
|
||||
|
||||
#include "debug/debug.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/fs.h"
|
||||
|
||||
#include "journal/journal.h"
|
||||
#include "journal/io.h"
|
||||
|
||||
#include "snapshots/snapshot.h"
|
||||
|
||||
#include <linux/random.h>
|
||||
#include <linux/prefetch.h>
|
||||
@ -296,14 +302,10 @@ static int __bch2_btree_iter_verify_ret(struct btree_iter *iter, struct bkey_s_c
|
||||
CLASS(btree_iter, copy)(trans, iter->btree_id, iter->pos,
|
||||
BTREE_ITER_nopreserve|
|
||||
BTREE_ITER_all_snapshots);
|
||||
struct bkey_s_c prev = bch2_btree_iter_prev(©);
|
||||
struct bkey_s_c prev = bkey_try(bch2_btree_iter_prev(©));
|
||||
if (!prev.k)
|
||||
return 0;
|
||||
|
||||
int ret = bkey_err(prev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bkey_eq(prev.k->p, k.k->p) &&
|
||||
bch2_snapshot_is_ancestor(trans->c, iter->snapshot,
|
||||
prev.k->p.snapshot) > 0) {
|
||||
@ -981,9 +983,7 @@ static __always_inline int btree_path_down(struct btree_trans *trans,
|
||||
EBUG_ON(!btree_node_locked(path, path->level));
|
||||
|
||||
if (unlikely(trans->journal_replay_not_finished)) {
|
||||
ret = btree_node_iter_and_journal_peek(trans, path, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(btree_node_iter_and_journal_peek(trans, path, flags));
|
||||
} else {
|
||||
struct bkey_packed *k = bch2_btree_node_iter_peek(&l->iter, l->b);
|
||||
if (unlikely(!k))
|
||||
@ -993,9 +993,7 @@ static __always_inline int btree_path_down(struct btree_trans *trans,
|
||||
|
||||
if (unlikely((flags & BTREE_ITER_prefetch)) &&
|
||||
c->opts.btree_node_prefetch) {
|
||||
ret = btree_path_prefetch(trans, path);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(btree_path_prefetch(trans, path));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1913,7 +1911,6 @@ int __must_check
|
||||
bch2_btree_iter_traverse(struct btree_iter *iter)
|
||||
{
|
||||
struct btree_trans *trans = iter->trans;
|
||||
int ret;
|
||||
|
||||
bch2_trans_verify_not_unlocked_or_in_restart(trans);
|
||||
|
||||
@ -1922,9 +1919,7 @@ bch2_btree_iter_traverse(struct btree_iter *iter)
|
||||
iter->flags & BTREE_ITER_intent,
|
||||
btree_iter_ip_allocated(iter));
|
||||
|
||||
ret = bch2_btree_path_traverse(iter->trans, iter->path, iter->flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_path_traverse(iter->trans, iter->path, iter->flags));
|
||||
|
||||
struct btree_path *path = btree_iter_path(trans, iter);
|
||||
if (btree_path_node(path, path->level))
|
||||
@ -3832,19 +3827,13 @@ void bch2_fs_btree_iter_init_early(struct bch_fs *c)
|
||||
|
||||
int bch2_fs_btree_iter_init(struct bch_fs *c)
|
||||
{
|
||||
int ret;
|
||||
|
||||
c->btree_trans_bufs = alloc_percpu(struct btree_trans_buf);
|
||||
if (!c->btree_trans_bufs)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mempool_init_kmalloc_pool(&c->btree_trans_pool, 1,
|
||||
sizeof(struct btree_trans)) ?:
|
||||
mempool_init_kmalloc_pool(&c->btree_trans_mem_pool, 1,
|
||||
BTREE_TRANS_MEM_MAX) ?:
|
||||
init_srcu_struct(&c->btree_trans_barrier);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(mempool_init_kmalloc_pool(&c->btree_trans_pool, 1, sizeof(struct btree_trans)));
|
||||
try(mempool_init_kmalloc_pool(&c->btree_trans_mem_pool, 1, BTREE_TRANS_MEM_MAX));
|
||||
try(init_srcu_struct(&c->btree_trans_barrier));
|
||||
|
||||
/*
|
||||
* static annotation (hackily done) for lock ordering of reclaim vs.
|
||||
@ -2,9 +2,8 @@
|
||||
#ifndef _BCACHEFS_BTREE_ITER_H
|
||||
#define _BCACHEFS_BTREE_ITER_H
|
||||
|
||||
#include "bset.h"
|
||||
#include "btree_types.h"
|
||||
#include "trace.h"
|
||||
#include "btree/bset.h"
|
||||
#include "btree/types.h"
|
||||
|
||||
void bch2_trans_updates_to_text(struct printbuf *, struct btree_trans *);
|
||||
void bch2_btree_path_to_text(struct printbuf *, struct btree_trans *, btree_path_idx_t);
|
||||
@ -18,6 +17,13 @@ static inline int __bkey_err(const struct bkey *k)
|
||||
|
||||
#define bkey_err(_k) __bkey_err((_k).k)
|
||||
|
||||
#define bkey_try(_do) \
|
||||
({ \
|
||||
typeof(_do) _k = _do; \
|
||||
try(bkey_err(_k)); \
|
||||
_k; \
|
||||
})
|
||||
|
||||
static inline void __btree_path_get(struct btree_trans *trans, struct btree_path *path, bool intent)
|
||||
{
|
||||
unsigned idx = path - trans->paths;
|
||||
@ -1,12 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "bkey_buf.h"
|
||||
#include "bset.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_journal_iter.h"
|
||||
#include "disk_accounting.h"
|
||||
#include "journal_io.h"
|
||||
|
||||
#include "alloc/accounting.h"
|
||||
|
||||
#include "btree/bkey_buf.h"
|
||||
#include "btree/bset.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/journal_overlay.h"
|
||||
|
||||
#include "journal/io.h"
|
||||
|
||||
#include <linux/sort.h>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#ifndef _BCACHEFS_BTREE_JOURNAL_ITER_H
|
||||
#define _BCACHEFS_BTREE_JOURNAL_ITER_H
|
||||
|
||||
#include "bkey.h"
|
||||
#include "btree/bkey.h"
|
||||
|
||||
struct journal_iter {
|
||||
struct list_head list;
|
||||
@ -1,16 +1,17 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_iter.h"
|
||||
#include "btree_key_cache.h"
|
||||
#include "btree_locking.h"
|
||||
#include "btree_update.h"
|
||||
#include "errcode.h"
|
||||
#include "error.h"
|
||||
#include "journal.h"
|
||||
#include "journal_reclaim.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "btree/cache.h"
|
||||
#include "btree/iter.h"
|
||||
#include "btree/key_cache.h"
|
||||
#include "btree/locking.h"
|
||||
#include "btree/update.h"
|
||||
|
||||
#include "init/error.h"
|
||||
|
||||
#include "journal/journal.h"
|
||||
#include "journal/reclaim.h"
|
||||
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
@ -213,6 +214,7 @@ static int btree_key_cache_create(struct btree_trans *trans,
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct btree_key_cache *bc = &c->btree_key_cache;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* bch2_varint_decode can read past the end of the buffer by at
|
||||
@ -228,10 +230,7 @@ static int btree_key_cache_create(struct btree_trans *trans,
|
||||
key_u64s = min(256U, (key_u64s * 3) / 2);
|
||||
key_u64s = roundup_pow_of_two(key_u64s);
|
||||
|
||||
struct bkey_cached *ck = bkey_cached_alloc(trans, ck_path, key_u64s);
|
||||
int ret = PTR_ERR_OR_ZERO(ck);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_cached *ck = errptr_try(bkey_cached_alloc(trans, ck_path, key_u64s));
|
||||
|
||||
if (unlikely(!ck)) {
|
||||
ck = bkey_cached_reuse(bc);
|
||||
@ -329,20 +328,15 @@ static noinline int btree_key_cache_fill(struct btree_trans *trans,
|
||||
BTREE_ITER_key_cache_fill|
|
||||
BTREE_ITER_cached_nofill);
|
||||
iter.flags &= ~BTREE_ITER_with_journal;
|
||||
struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter);
|
||||
int ret = bkey_err(k);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct bkey_s_c k = bkey_try(bch2_btree_iter_peek_slot(&iter));
|
||||
|
||||
/* Recheck after btree lookup, before allocating: */
|
||||
ck_path = trans->paths + ck_path_idx;
|
||||
ret = bch2_btree_key_cache_find(c, ck_path->btree_id, ck_path->pos) ? -EEXIST : 0;
|
||||
int ret = bch2_btree_key_cache_find(c, ck_path->btree_id, ck_path->pos) ? -EEXIST : 0;
|
||||
if (unlikely(ret))
|
||||
goto out;
|
||||
|
||||
ret = btree_key_cache_create(trans, btree_iter_path(trans, &iter), ck_path, k);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(btree_key_cache_create(trans, btree_iter_path(trans, &iter), ck_path, k));
|
||||
|
||||
if (trace_key_cache_fill_enabled())
|
||||
do_trace_key_cache_fill(trans, ck_path, k);
|
||||
@ -365,9 +359,7 @@ retry:
|
||||
|
||||
enum six_lock_type lock_want = __btree_lock_want(path, 0);
|
||||
|
||||
int ret = btree_node_lock(trans, path, (void *) ck, 0, lock_want, _THIS_IP_);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(btree_node_lock(trans, path, (void *) ck, 0, lock_want, _THIS_IP_));
|
||||
|
||||
if (ck->key.btree_id != path->btree_id ||
|
||||
!bpos_eq(ck->key.pos, path->pos)) {
|
||||
@ -432,9 +424,7 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans,
|
||||
BTREE_ITER_intent);
|
||||
b_iter.flags &= ~BTREE_ITER_with_key_cache;
|
||||
|
||||
ret = bch2_btree_iter_traverse(&c_iter);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_btree_iter_traverse(&c_iter));
|
||||
|
||||
ck = (void *) btree_iter_path(trans, &c_iter)->l[0].b;
|
||||
if (!ck)
|
||||
@ -2,7 +2,7 @@
|
||||
#ifndef _BCACHEFS_BTREE_KEY_CACHE_TYPES_H
|
||||
#define _BCACHEFS_BTREE_KEY_CACHE_TYPES_H
|
||||
|
||||
#include "rcu_pending.h"
|
||||
#include "util/rcu_pending.h"
|
||||
|
||||
struct btree_key_cache {
|
||||
struct rhashtable table;
|
||||
@ -1,9 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_locking.h"
|
||||
#include "btree_types.h"
|
||||
#include "btree/cache.h"
|
||||
#include "btree/locking.h"
|
||||
|
||||
static struct lock_class_key bch2_btree_node_lock_key;
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
* updating the iterator state
|
||||
*/
|
||||
|
||||
#include "btree_iter.h"
|
||||
#include "six.h"
|
||||
#include "btree/iter.h"
|
||||
#include "util/six.h"
|
||||
|
||||
void bch2_btree_lock_init(struct btree_bkey_cached_common *, enum six_lock_init_flags, gfp_t gfp);
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "bcachefs.h"
|
||||
#include "btree_cache.h"
|
||||
#include "btree_io.h"
|
||||
#include "btree_journal_iter.h"
|
||||
#include "btree_node_scan.h"
|
||||
#include "btree_update_interior.h"
|
||||
#include "buckets.h"
|
||||
#include "error.h"
|
||||
#include "journal_io.h"
|
||||
#include "recovery_passes.h"
|
||||
|
||||
#include "alloc/buckets.h"
|
||||
|
||||
#include "btree/cache.h"
|
||||
#include "btree/io.h"
|
||||
#include "btree/interior.h"
|
||||
#include "btree/journal_overlay.h"
|
||||
#include "btree/node_scan.h"
|
||||
|
||||
#include "journal/io.h"
|
||||
|
||||
#include "init/error.h"
|
||||
#include "init/passes.h"
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched/sysctl.h>
|
||||
@ -374,9 +378,7 @@ int bch2_scan_for_btree_nodes(struct bch_fs *c)
|
||||
|
||||
mutex_init(&f->lock);
|
||||
|
||||
ret = read_btree_nodes(f);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(read_btree_nodes(f));
|
||||
|
||||
if (!f->nodes.nr) {
|
||||
bch_err(c, "%s: no btree nodes found", __func__);
|
||||
@ -513,9 +515,7 @@ bool bch2_btree_node_is_stale(struct bch_fs *c, struct btree *b)
|
||||
|
||||
int bch2_btree_has_scanned_nodes(struct bch_fs *c, enum btree_id btree)
|
||||
{
|
||||
int ret = bch2_run_print_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_run_print_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes));
|
||||
|
||||
struct found_btree_node search = {
|
||||
.btree_id = btree,
|
||||
@ -535,11 +535,7 @@ int bch2_get_scanned_nodes(struct bch_fs *c, enum btree_id btree,
|
||||
if (!btree_id_recovers_from_scan(btree))
|
||||
return 0;
|
||||
|
||||
struct find_btree_nodes *f = &c->found_btree_nodes;
|
||||
|
||||
int ret = bch2_run_print_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_run_print_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes));
|
||||
|
||||
if (c->opts.verbose) {
|
||||
CLASS(printbuf, buf)();
|
||||
@ -561,6 +557,7 @@ int bch2_get_scanned_nodes(struct bch_fs *c, enum btree_id btree,
|
||||
.max_key = node_max,
|
||||
};
|
||||
|
||||
struct find_btree_nodes *f = &c->found_btree_nodes;
|
||||
for_each_found_btree_node_in_range(f, search, idx) {
|
||||
struct found_btree_node n = f->nodes.data[idx];
|
||||
|
||||
@ -587,9 +584,7 @@ int bch2_get_scanned_nodes(struct bch_fs *c, enum btree_id btree,
|
||||
.btree = btree,
|
||||
}));
|
||||
|
||||
ret = bch2_journal_key_insert(c, btree, level + 1, &tmp.k);
|
||||
if (ret)
|
||||
return ret;
|
||||
try(bch2_journal_key_insert(c, btree, level + 1, &tmp.k));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2,7 +2,7 @@
|
||||
#ifndef _BCACHEFS_BTREE_NODE_SCAN_TYPES_H
|
||||
#define _BCACHEFS_BTREE_NODE_SCAN_TYPES_H
|
||||
|
||||
#include "darray.h"
|
||||
#include "util/darray.h"
|
||||
|
||||
struct found_btree_node {
|
||||
bool range_updated:1;
|
||||
@ -5,14 +5,16 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/rhashtable.h>
|
||||
|
||||
#include "bbpos_types.h"
|
||||
#include "btree_key_cache_types.h"
|
||||
#include "buckets_types.h"
|
||||
#include "darray.h"
|
||||
#include "errcode.h"
|
||||
#include "journal_types.h"
|
||||
#include "replicas_types.h"
|
||||
#include "six.h"
|
||||
#include "alloc/buckets_types.h"
|
||||
#include "alloc/replicas_types.h"
|
||||
|
||||
#include "btree/bbpos_types.h"
|
||||
#include "btree/key_cache_types.h"
|
||||
|
||||
#include "journal/types.h"
|
||||
|
||||
#include "util/darray.h"
|
||||
#include "util/six.h"
|
||||
|
||||
struct open_bucket;
|
||||
struct btree_update;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user