#include "fifo.h"
#include "nocow_locking_types.h"
#include "opts.h"
+#include "seqmutex.h"
#include "util.h"
#ifdef CONFIG_BCACHEFS_DEBUG
#define BCH_WRITE_REF_DEBUG
#endif
+#ifndef dynamic_fault
#define dynamic_fault(...) 0
-#define race_fault(...) 0
+#endif
+
+#define race_fault(...) dynamic_fault("bcachefs:race")
#define trace_and_count(_c, _name, ...) \
do { \
#define bch_err_inum_offset_ratelimited(c, _inum, _offset, fmt, ...) \
printk_ratelimited(KERN_ERR bch2_fmt_inum_offset(c, _inum, _offset, fmt), ##__VA_ARGS__)
+#define bch_err_fn(_c, _ret) \
+ bch_err(_c, "%s(): error %s", __func__, bch2_err_str(_ret))
+#define bch_err_msg(_c, _ret, _msg) \
+ bch_err(_c, "%s(): error " _msg " %s", __func__, bch2_err_str(_ret))
+
#define bch_verbose(c, fmt, ...) \
do { \
if ((c)->opts.verbose) \
GC_PHASE_BTREE_need_discard,
GC_PHASE_BTREE_backpointers,
GC_PHASE_BTREE_bucket_gens,
+ GC_PHASE_BTREE_snapshot_trees,
GC_PHASE_PENDING_DELETE,
};
* Committed by bch2_write_super() -> bch_fs_mi_update()
*/
struct bch_member_cpu mi;
- uuid_le uuid;
+ __uuid_t uuid;
char name[BDEVNAME_SIZE];
struct bch_sb_handle disk_sb;
/* fsck passes: */
BCH_FS_TOPOLOGY_REPAIR_DONE,
- BCH_FS_INITIAL_GC_DONE, /* kill when we enumerate fsck passes */
- BCH_FS_CHECK_ALLOC_DONE,
- BCH_FS_CHECK_LRUS_DONE,
- BCH_FS_CHECK_BACKPOINTERS_DONE,
- BCH_FS_CHECK_ALLOC_TO_LRU_REFS_DONE,
BCH_FS_FSCK_DONE,
BCH_FS_INITIAL_GC_UNFIXED, /* kill when we enumerate fsck errors */
BCH_FS_NEED_ANOTHER_GC,
#define REPLICAS_DELTA_LIST_MAX (1U << 16)
-struct snapshot_t {
- u32 parent;
- u32 children[2];
- u32 subvol; /* Nonzero only if a subvolume points to this node: */
- u32 equiv;
-};
-
-typedef struct {
- u32 subvol;
- u64 inum;
-} subvol_inum;
-
#define BCACHEFS_ROOT_SUBVOL_INUM \
((subvol_inum) { BCACHEFS_ROOT_SUBVOL, BCACHEFS_ROOT_INO })
x(fallocate) \
x(discard) \
x(invalidate) \
- x(move) \
x(delete_dead_snapshots) \
x(snapshot_delete_pagecache) \
x(sysfs)
BCH_WRITE_REF_NR,
};
+#define PASS_SILENT BIT(0)
+#define PASS_FSCK BIT(1)
+#define PASS_UNCLEAN BIT(2)
+#define PASS_ALWAYS BIT(3)
+#define PASS_UPGRADE(v) ((v) << 4)
+
+#define BCH_RECOVERY_PASSES() \
+ x(alloc_read, PASS_ALWAYS) \
+ x(stripes_read, PASS_ALWAYS) \
+ x(initialize_subvolumes, PASS_UPGRADE(bcachefs_metadata_version_snapshot_2)) \
+ x(snapshots_read, PASS_ALWAYS) \
+ x(check_allocations, PASS_FSCK) \
+ x(set_may_go_rw, PASS_ALWAYS|PASS_SILENT) \
+ x(journal_replay, PASS_ALWAYS) \
+ x(check_alloc_info, PASS_FSCK) \
+ x(check_lrus, PASS_FSCK) \
+ x(check_btree_backpointers, PASS_FSCK) \
+ x(check_backpointers_to_extents,PASS_FSCK) \
+ x(check_extents_to_backpointers,PASS_FSCK) \
+ x(check_alloc_to_lru_refs, PASS_FSCK) \
+ x(fs_freespace_init, PASS_ALWAYS|PASS_SILENT) \
+ x(bucket_gens_init, PASS_UPGRADE(bcachefs_metadata_version_bucket_gens)) \
+ x(fs_upgrade_for_subvolumes, PASS_UPGRADE(bcachefs_metadata_version_snapshot_2)) \
+ x(check_snapshot_trees, PASS_FSCK) \
+ x(check_snapshots, PASS_FSCK) \
+ x(check_subvols, PASS_FSCK) \
+ x(delete_dead_snapshots, PASS_FSCK|PASS_UNCLEAN|PASS_SILENT) \
+ x(check_inodes, PASS_FSCK|PASS_UNCLEAN) \
+ x(check_extents, PASS_FSCK) \
+ x(check_dirents, PASS_FSCK) \
+ x(check_xattrs, PASS_FSCK) \
+ x(check_root, PASS_FSCK) \
+ x(check_directory_structure, PASS_FSCK) \
+ x(check_nlinks, PASS_FSCK) \
+ x(fix_reflink_p, PASS_UPGRADE(bcachefs_metadata_version_reflink_p_fix)) \
+
+enum bch_recovery_pass {
+#define x(n, when) BCH_RECOVERY_PASS_##n,
+ BCH_RECOVERY_PASSES()
+#undef x
+};
+
struct bch_fs {
struct closure cl;
/* Updated by bch2_sb_update():*/
struct {
- uuid_le uuid;
- uuid_le user_uuid;
+ __uuid_t uuid;
+ __uuid_t user_uuid;
u16 version;
u16 version_min;
+ u16 version_upgrade_complete;
u8 nr_devices;
u8 clean;
struct bio_set btree_bio;
struct workqueue_struct *io_complete_wq;
- struct btree_root btree_roots[BTREE_ID_NR];
+ struct btree_root btree_roots_known[BTREE_ID_NR];
+ DARRAY(struct btree_root) btree_roots_extra;
struct mutex btree_root_lock;
struct btree_cache btree_cache;
} btree_write_stats[BTREE_WRITE_TYPE_NR];
/* btree_iter.c: */
- struct mutex btree_trans_lock;
+ struct seqmutex btree_trans_lock;
struct list_head btree_trans_list;
mempool_t btree_paths_pool;
mempool_t btree_trans_mem_pool;
struct workqueue_struct *btree_io_complete_wq;
/* copygc needs its own workqueue for index updates.. */
struct workqueue_struct *copygc_wq;
+ /*
+ * Use a dedicated wq for write ref holder tasks. Required to avoid
+ * dependency problems with other wq tasks that can block on ref
+ * draining, such as read-only transition.
+ */
+ struct workqueue_struct *write_ref_wq;
/* ALLOCATION */
struct bch_devs_mask rw_devs[BCH_DATA_NR];
mempool_t large_bkey_pool;
+ /* MOVE.C */
+ struct list_head moving_context_list;
+ struct mutex moving_context_lock;
+
+ struct list_head data_progress_list;
+ struct mutex data_progress_lock;
+
/* REBALANCE */
struct bch_fs_rebalance rebalance;
/* COPYGC */
struct task_struct *copygc_thread;
struct write_point copygc_write_point;
+ s64 copygc_wait_at;
s64 copygc_wait;
bool copygc_running;
wait_queue_head_t copygc_running_wq;
- /* DATA PROGRESS STATS */
- struct list_head data_progress_list;
- struct mutex data_progress_lock;
-
/* STRIPES: */
GENRADIX(struct stripe) stripes;
GENRADIX(struct gc_stripe) gc_stripes;
struct list_head ec_stripe_new_list;
struct mutex ec_stripe_new_lock;
+ wait_queue_head_t ec_stripe_new_wait;
struct work_struct ec_stripe_create_work;
u64 ec_stripe_hint;
- struct bio_set ec_bioset;
-
struct work_struct ec_stripe_delete_work;
- struct llist_head ec_stripe_delete_list;
+
+ struct bio_set ec_bioset;
/* REFLINK */
- u64 reflink_hint;
reflink_gc_table reflink_gc_table;
size_t reflink_gc_nr;
+ /* fs.c */
+ struct list_head vfs_inodes_list;
+ struct mutex vfs_inodes_lock;
+
/* VFS IO PATH - fs-io.c */
struct bio_set writepage_bioset;
struct bio_set dio_write_bioset;
/* QUOTAS */
struct bch_memquota_type quotas[QTYP_NR];
+ /* RECOVERY */
+ u64 journal_replay_seq_start;
+ u64 journal_replay_seq_end;
+ enum bch_recovery_pass curr_recovery_pass;
+
/* DEBUG JUNK */
struct dentry *fs_debug_dir;
struct dentry *btree_debug_dir;
return dev < c->sb.nr_devices && c->devs[dev];
}
+static inline bool bch2_version_upgrading_to(const struct bch_fs *c, unsigned new_version)
+{
+ return c->sb.version_upgrade_complete < new_version &&
+ c->sb.version >= new_version;
+}
+
+#define BKEY_PADDED_ONSTACK(key, pad) \
+ struct { struct bkey_i key; __u64 key ## _pad[pad]; }
+
#endif /* _BCACHEFS_H */