Commit cef27048 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'bcachefs-2024-04-15' of https://evilpiepirate.org/git/bcachefs

Pull yet more bcachefs fixes from Kent Overstreet:
 "This gets recovery working again for the affected user I've been
  working with, and I'm still waiting to hear back on other bug reports
  but should fix it for everyone else who's been having issues with
  recovery.

   - Various recovery fixes:

       - fixes for the btree_insert_entry being resized on path
         allocation btree_path array recently became dynamically
         resizable, and btree_insert_entry along with it; this was being
         observed during journal replay, when write buffer btree updates
         don't use the write buffer and instead use the normal btree
         update path

       - multiple fixes for deadlock in recovery when we need to do lots
         of btree node merges; excessive merges were clocking up the
         whole pipeline

       - write buffer path now correctly does btree node merges when
         needed

       - fix failure to go RW when superblock indicates recovery passes
         needed (i.e. to complete an unfinished upgrade)

   - Various unsafety fixes - test case contributed by a user who had
     two drives out of a six drive array write out a whole bunch of
     garbage after power failure

   - New (tiny) on disk format feature: since it appears the btree node
     scan tool will be a more regular thing (crappy hardware, user
     error) - this adds a 64 bit per-device bitmap of regions that have
     ever had btree nodes.

   - A path->should_be_locked fix, from a larger patch series tightening
     up invariants and assertions around btree transaction and path
     locking state.

     This particular fix prevents us from keeping around btree_paths
     that are no longer needed"

* tag 'bcachefs-2024-04-15' of https://evilpiepirate.org/git/bcachefs: (24 commits)
  bcachefs: set_btree_iter_dontneed also clears should_be_locked
  bcachefs: fix error path of __bch2_read_super()
  bcachefs: Check for backpointer bucket_offset >= bucket size
  bcachefs: bch_member.btree_allocated_bitmap
  bcachefs: sysfs internal/trigger_journal_flush
  bcachefs: Fix bch2_btree_node_fill() for !path
  bcachefs: add safety checks in bch2_btree_node_fill()
  bcachefs: Interior known are required to have known key types
  bcachefs: add missing bounds check in __bch2_bkey_val_invalid()
  bcachefs: Fix btree node merging on write buffer btrees
  bcachefs: Disable merges from interior update path
  bcachefs: Run merges at BCH_WATERMARK_btree
  bcachefs: Fix missing write refs in fs fio paths
  bcachefs: Fix deadlock in journal replay
  bcachefs: Go rw if running any explicit recovery passes
  bcachefs: Standardize helpers for printing enum strs with bounds checks
  bcachefs: don't queue btree nodes for rewrites during scan
  bcachefs: fix race in bch2_btree_node_evict()
  bcachefs: fix unsafety in bch2_stripe_to_text()
  bcachefs: fix unsafety in bch2_extent_ptr_to_text()
  ...
parents 3fdfcd98 ad29cf99
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -49,13 +49,15 @@ int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k,
	if (!bch2_dev_exists2(c, bp.k->p.inode))
		return 0;

	struct bch_dev *ca = bch_dev_bkey_exists(c, bp.k->p.inode);
	struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
	int ret = 0;

	bkey_fsck_err_on(!bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)),
	bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
			 !bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)),
			 c, err,
			 backpointer_pos_wrong,
			 "backpointer at wrong pos");
			 backpointer_bucket_offset_wrong,
			 "backpointer bucket_offset wrong");
fsck_err:
	return ret;
}
+3 −6
Original line number Diff line number Diff line
@@ -53,14 +53,11 @@ static inline struct bpos bucket_pos_to_bp(const struct bch_fs *c,
					   u64 bucket_offset)
{
	struct bch_dev *ca = bch_dev_bkey_exists(c, bucket.inode);
	struct bpos ret;

	ret = POS(bucket.inode,
	struct bpos ret = POS(bucket.inode,
			      (bucket_to_sector(ca, bucket.offset) <<
			       MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset);

	EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(c, ret)));

	return ret;
}

+2 −0
Original line number Diff line number Diff line
@@ -709,6 +709,8 @@ struct btree_trans_buf {
	x(stripe_delete)						\
	x(reflink)							\
	x(fallocate)							\
	x(fsync)							\
	x(dio_write)							\
	x(discard)							\
	x(discard_fast)							\
	x(invalidate)							\
+7 −4
Original line number Diff line number Diff line
@@ -578,7 +578,8 @@ struct bch_member {
	__le64			nbuckets;	/* device size */
	__le16			first_bucket;   /* index of first bucket used */
	__le16			bucket_size;	/* sectors */
	__le32			pad;
	__u8			btree_bitmap_shift;
	__u8			pad[3];
	__le64			last_mount;	/* time_t */

	__le64			flags;
@@ -587,6 +588,7 @@ struct bch_member {
	__le64			errors_at_reset[BCH_MEMBER_ERROR_NR];
	__le64			errors_reset_time;
	__le64			seq;
	__le64			btree_allocated_bitmap;
};

#define BCH_MEMBER_V1_BYTES	56
@@ -876,7 +878,8 @@ struct bch_sb_field_downgrade {
	x(rebalance_work,		BCH_VERSION(1,  3))		\
	x(member_seq,			BCH_VERSION(1,  4))		\
	x(subvolume_fs_parent,		BCH_VERSION(1,  5))		\
	x(btree_subvolume_children,	BCH_VERSION(1,  6))
	x(btree_subvolume_children,	BCH_VERSION(1,  6))		\
	x(mi_btree_bitmap,		BCH_VERSION(1,  7))

enum bcachefs_metadata_version {
	bcachefs_metadata_version_min = 9,
@@ -1314,7 +1317,7 @@ static inline __u64 __bset_magic(struct bch_sb *sb)
	x(write_buffer_keys,	11)		\
	x(datetime,		12)

enum {
enum bch_jset_entry_type {
#define x(f, nr)	BCH_JSET_ENTRY_##f	= nr,
	BCH_JSET_ENTRY_TYPES()
#undef x
@@ -1360,7 +1363,7 @@ struct jset_entry_blacklist_v2 {
	x(inodes,		1)		\
	x(key_version,		2)

enum {
enum bch_fs_usage_type {
#define x(f, nr)	BCH_FS_USAGE_##f	= nr,
	BCH_FS_USAGE_TYPES()
#undef x
+6 −0
Original line number Diff line number Diff line
@@ -314,6 +314,12 @@ static inline unsigned bkeyp_key_u64s(const struct bkey_format *format,
	return bkey_packed(k) ? format->key_u64s : BKEY_U64s;
}

static inline bool bkeyp_u64s_valid(const struct bkey_format *f,
				    const struct bkey_packed *k)
{
	return ((unsigned) k->u64s - bkeyp_key_u64s(f, k) <= U8_MAX - BKEY_U64s);
}

static inline unsigned bkeyp_key_bytes(const struct bkey_format *format,
				       const struct bkey_packed *k)
{
Loading