#include "bcachefs.h"
#include "bkey_buf.h"
#include "btree_cache.h"
#include "btree_update.h"
#include "buckets.h"
#include "darray.h"
#include "dirent.h"
#include "error.h"
#include "fs-common.h"
#include "fsck.h"
#include "inode.h"
#include "keylist.h"
#include "recovery_passes.h"
#include "snapshot.h"
#include "super.h"
#include "xattr.h"
#include <linux/bsearch.h>
#include <linux/dcache.h>
static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum,
u32 snapshot)
{ … }
static s64 bch2_count_subdirs(struct btree_trans *trans, u64 inum,
u32 snapshot)
{ … }
static int subvol_lookup(struct btree_trans *trans, u32 subvol,
u32 *snapshot, u64 *inum)
{ … }
static int lookup_first_inode(struct btree_trans *trans, u64 inode_nr,
struct bch_inode_unpacked *inode)
{ … }
static int lookup_inode(struct btree_trans *trans, u64 inode_nr,
struct bch_inode_unpacked *inode,
u32 *snapshot)
{ … }
static int lookup_dirent_in_snapshot(struct btree_trans *trans,
struct bch_hash_info hash_info,
subvol_inum dir, struct qstr *name,
u64 *target, unsigned *type, u32 snapshot)
{ … }
static int __remove_dirent(struct btree_trans *trans, struct bpos pos)
{ … }
static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
struct bch_inode_unpacked *lostfound,
u64 reattaching_inum)
{ … }
static int reattach_inode(struct btree_trans *trans,
struct bch_inode_unpacked *inode,
u32 inode_snapshot)
{ … }
static int remove_backpointer(struct btree_trans *trans,
struct bch_inode_unpacked *inode)
{ … }
static int reattach_subvol(struct btree_trans *trans, struct bkey_s_c_subvolume s)
{ … }
static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 subvolid, u64 inum)
{ … }
static int reconstruct_inode(struct btree_trans *trans, enum btree_id btree, u32 snapshot, u64 inum)
{ … }
struct snapshots_seen { … };
static inline void snapshots_seen_exit(struct snapshots_seen *s)
{ … }
static inline void snapshots_seen_init(struct snapshots_seen *s)
{ … }
static int snapshots_seen_add_inorder(struct bch_fs *c, struct snapshots_seen *s, u32 id)
{ … }
static int snapshots_seen_update(struct bch_fs *c, struct snapshots_seen *s,
enum btree_id btree_id, struct bpos pos)
{ … }
static bool key_visible_in_snapshot(struct bch_fs *c, struct snapshots_seen *seen,
u32 id, u32 ancestor)
{ … }
static bool ref_visible(struct bch_fs *c, struct snapshots_seen *s,
u32 src, u32 dst)
{ … }
static int ref_visible2(struct bch_fs *c,
u32 src, struct snapshots_seen *src_seen,
u32 dst, struct snapshots_seen *dst_seen)
{ … }
#define for_each_visible_inode(_c, _s, _w, _snapshot, _i) …
struct inode_walker_entry { … };
struct inode_walker { … };
static void inode_walker_exit(struct inode_walker *w)
{ … }
static struct inode_walker inode_walker_init(void)
{ … }
static int add_inode(struct bch_fs *c, struct inode_walker *w,
struct bkey_s_c inode)
{ … }
static int get_inodes_all_snapshots(struct btree_trans *trans,
struct inode_walker *w, u64 inum)
{ … }
static struct inode_walker_entry *
lookup_inode_for_snapshot(struct bch_fs *c, struct inode_walker *w, struct bkey_s_c k)
{ … }
static struct inode_walker_entry *walk_inode(struct btree_trans *trans,
struct inode_walker *w,
struct bkey_s_c k)
{ … }
static int get_visible_inodes(struct btree_trans *trans,
struct inode_walker *w,
struct snapshots_seen *s,
u64 inum)
{ … }
static int hash_redo_key(struct btree_trans *trans,
const struct bch_hash_desc desc,
struct bch_hash_info *hash_info,
struct btree_iter *k_iter, struct bkey_s_c k)
{ … }
static int hash_check_key(struct btree_trans *trans,
const struct bch_hash_desc desc,
struct bch_hash_info *hash_info,
struct btree_iter *k_iter, struct bkey_s_c hash_k)
{ … }
static struct bkey_s_c_dirent dirent_get_by_pos(struct btree_trans *trans,
struct btree_iter *iter,
struct bpos pos)
{ … }
static struct bkey_s_c_dirent inode_get_dirent(struct btree_trans *trans,
struct btree_iter *iter,
struct bch_inode_unpacked *inode,
u32 *snapshot)
{ … }
static bool inode_points_to_dirent(struct bch_inode_unpacked *inode,
struct bkey_s_c_dirent d)
{ … }
static bool dirent_points_to_inode(struct bkey_s_c_dirent d,
struct bch_inode_unpacked *inode)
{ … }
static int check_inode_deleted_list(struct btree_trans *trans, struct bpos p)
{ … }
static int check_inode_dirent_inode(struct btree_trans *trans, struct bkey_s_c inode_k,
struct bch_inode_unpacked *inode,
u32 inode_snapshot, bool *write_inode)
{ … }
static int check_inode(struct btree_trans *trans,
struct btree_iter *iter,
struct bkey_s_c k,
struct bch_inode_unpacked *prev,
struct snapshots_seen *s,
bool full)
{ … }
int bch2_check_inodes(struct bch_fs *c)
{ … }
static inline bool btree_matches_i_mode(enum btree_id btree, unsigned mode)
{ … }
static int check_key_has_inode(struct btree_trans *trans,
struct btree_iter *iter,
struct inode_walker *inode,
struct inode_walker_entry *i,
struct bkey_s_c k)
{ … }
static int check_i_sectors_notnested(struct btree_trans *trans, struct inode_walker *w)
{ … }
static int check_i_sectors(struct btree_trans *trans, struct inode_walker *w)
{ … }
struct extent_end { … };
struct extent_ends { … };
static void extent_ends_reset(struct extent_ends *extent_ends)
{ … }
static void extent_ends_exit(struct extent_ends *extent_ends)
{ … }
static void extent_ends_init(struct extent_ends *extent_ends)
{ … }
static int extent_ends_at(struct bch_fs *c,
struct extent_ends *extent_ends,
struct snapshots_seen *seen,
struct bkey_s_c k)
{ … }
static int overlapping_extents_found(struct btree_trans *trans,
enum btree_id btree,
struct bpos pos1, struct snapshots_seen *pos1_seen,
struct bkey pos2,
bool *fixed,
struct extent_end *extent_end)
{ … }
static int check_overlapping_extents(struct btree_trans *trans,
struct snapshots_seen *seen,
struct extent_ends *extent_ends,
struct bkey_s_c k,
struct btree_iter *iter,
bool *fixed)
{ … }
static int check_extent_overbig(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c k)
{ … }
static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c k,
struct inode_walker *inode,
struct snapshots_seen *s,
struct extent_ends *extent_ends)
{ … }
int bch2_check_extents(struct bch_fs *c)
{ … }
int bch2_check_indirect_extents(struct bch_fs *c)
{ … }
static int check_subdir_count_notnested(struct btree_trans *trans, struct inode_walker *w)
{ … }
static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w)
{ … }
noinline_for_stack
static int check_dirent_inode_dirent(struct btree_trans *trans,
struct btree_iter *iter,
struct bkey_s_c_dirent d,
struct bch_inode_unpacked *target,
u32 target_snapshot)
{ … }
noinline_for_stack
static int check_dirent_target(struct btree_trans *trans,
struct btree_iter *iter,
struct bkey_s_c_dirent d,
struct bch_inode_unpacked *target,
u32 target_snapshot)
{ … }
static int find_snapshot_subvol(struct btree_trans *trans, u32 snapshot, u32 *subvolid)
{ … }
noinline_for_stack
static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c_dirent d)
{ … }
static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c k,
struct bch_hash_info *hash_info,
struct inode_walker *dir,
struct inode_walker *target,
struct snapshots_seen *s)
{ … }
int bch2_check_dirents(struct bch_fs *c)
{ … }
static int check_xattr(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c k,
struct bch_hash_info *hash_info,
struct inode_walker *inode)
{ … }
int bch2_check_xattrs(struct bch_fs *c)
{ … }
static int check_root_trans(struct btree_trans *trans)
{ … }
int bch2_check_root(struct bch_fs *c)
{ … }
darray_u32;
static bool darray_u32_has(darray_u32 *d, u32 v)
{ … }
static int subvol_has_dirent(struct btree_trans *trans, struct bkey_s_c_subvolume s)
{ … }
static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter, struct bkey_s_c k)
{ … }
int bch2_check_subvolume_structure(struct bch_fs *c)
{ … }
struct pathbuf_entry { … };
pathbuf;
static bool path_is_dup(pathbuf *p, u64 inum, u32 snapshot)
{ … }
static int check_path(struct btree_trans *trans, pathbuf *p, struct bkey_s_c inode_k)
{ … }
int bch2_check_directory_structure(struct bch_fs *c)
{ … }
struct nlink_table { … };
static int add_nlink(struct bch_fs *c, struct nlink_table *t,
u64 inum, u32 snapshot)
{ … }
static int nlink_cmp(const void *_l, const void *_r)
{ … }
static void inc_link(struct bch_fs *c, struct snapshots_seen *s,
struct nlink_table *links,
u64 range_start, u64 range_end, u64 inum, u32 snapshot)
{ … }
noinline_for_stack
static int check_nlinks_find_hardlinks(struct bch_fs *c,
struct nlink_table *t,
u64 start, u64 *end)
{ … }
noinline_for_stack
static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links,
u64 range_start, u64 range_end)
{ … }
static int check_nlinks_update_inode(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c k,
struct nlink_table *links,
size_t *idx, u64 range_end)
{ … }
noinline_for_stack
static int check_nlinks_update_hardlinks(struct bch_fs *c,
struct nlink_table *links,
u64 range_start, u64 range_end)
{ … }
int bch2_check_nlinks(struct bch_fs *c)
{ … }
static int fix_reflink_p_key(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c k)
{ … }
int bch2_fix_reflink_p(struct bch_fs *c)
{ … }