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

Merge tag 'bcachefs-2024-08-08' of git://evilpiepirate.org/bcachefs

Pull bcachefs fixes from Kent Overstreet:
 "Assorted little stuff:

   - lockdep fixup for lockdep_set_notrack_class()

   - we can now remove a device when using erasure coding without
     deadlocking, though we still hit other issues

   - the 'allocator stuck' timeout is now configurable, and messages are
     ratelimited. The default timeout has been increased from 10 seconds
     to 30"

* tag 'bcachefs-2024-08-08' of git://evilpiepirate.org/bcachefs:
  bcachefs: Use bch2_wait_on_allocator() in btree node alloc path
  bcachefs: Make allocator stuck timeout configurable, ratelimit messages
  bcachefs: Add missing path_traverse() to btree_iter_next_node()
  bcachefs: ec should not allocate from ro devs
  bcachefs: Improved allocator debugging for ec
  bcachefs: Add missing bch2_trans_begin() call
  bcachefs: Add a comment for bucket helper types
  bcachefs: Don't rely on implicit unsigned -> signed integer conversion
  lockdep: Fix lockdep_set_notrack_class() for CONFIG_LOCK_STAT
  bcachefs: Fix double free of ca->buckets_nouse
parents cb5b81bc 73dc1656
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -82,6 +82,14 @@ static inline bool bucket_data_type_mismatch(enum bch_data_type bucket,
		bucket_data_type(bucket) != bucket_data_type(ptr);
}

/*
 * It is my general preference to use unsigned types for unsigned quantities -
 * however, these helpers are used in disk accounting calculations run by
 * triggers where the output will be negated and added to an s64. unsigned is
 * right out even though all these quantities will fit in 32 bits, since it
 * won't be sign extended correctly; u64 will negate "correctly", but s64 is the
 * simpler option here.
 */
static inline s64 bch2_bucket_sectors_total(struct bch_alloc_v4 a)
{
	return a.stripe_sectors + a.dirty_sectors + a.cached_sectors;
@@ -166,7 +174,7 @@ static inline u64 alloc_lru_idx_fragmentation(struct bch_alloc_v4 a,
	 * avoid overflowing LRU_TIME_BITS on a corrupted fs, when
	 * bucket_sectors_dirty is (much) bigger than bucket_size
	 */
	u64 d = min(bch2_bucket_sectors_dirty(a),
	u64 d = min_t(s64, bch2_bucket_sectors_dirty(a),
		      ca->mi.bucket_size);

	return div_u64(d * (1ULL << 31), ca->mi.bucket_size);
+28 −4
Original line number Diff line number Diff line
@@ -1603,7 +1603,8 @@ void bch2_open_bucket_to_text(struct printbuf *out, struct bch_fs *c, struct ope
	prt_newline(out);
}

void bch2_open_buckets_to_text(struct printbuf *out, struct bch_fs *c)
void bch2_open_buckets_to_text(struct printbuf *out, struct bch_fs *c,
			       struct bch_dev *ca)
{
	struct open_bucket *ob;

@@ -1613,7 +1614,8 @@ void bch2_open_buckets_to_text(struct printbuf *out, struct bch_fs *c)
	     ob < c->open_buckets + ARRAY_SIZE(c->open_buckets);
	     ob++) {
		spin_lock(&ob->lock);
		if (ob->valid && !ob->on_partial_list)
		if (ob->valid && !ob->on_partial_list &&
		    (!ca || ob->dev == ca->dev_idx))
			bch2_open_bucket_to_text(out, c, ob);
		spin_unlock(&ob->lock);
	}
@@ -1756,11 +1758,12 @@ void bch2_dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca)
	prt_printf(out, "buckets to invalidate\t%llu\r\n",	should_invalidate_buckets(ca, stats));
}

void bch2_print_allocator_stuck(struct bch_fs *c)
static noinline void bch2_print_allocator_stuck(struct bch_fs *c)
{
	struct printbuf buf = PRINTBUF;

	prt_printf(&buf, "Allocator stuck? Waited for 10 seconds\n");
	prt_printf(&buf, "Allocator stuck? Waited for %u seconds\n",
		   c->opts.allocator_stuck_timeout);

	prt_printf(&buf, "Allocator debug:\n");
	printbuf_indent_add(&buf, 2);
@@ -1790,3 +1793,24 @@ void bch2_print_allocator_stuck(struct bch_fs *c)
	bch2_print_string_as_lines(KERN_ERR, buf.buf);
	printbuf_exit(&buf);
}

static inline unsigned allocator_wait_timeout(struct bch_fs *c)
{
	if (c->allocator_last_stuck &&
	    time_after(c->allocator_last_stuck + HZ * 60 * 2, jiffies))
		return 0;

	return c->opts.allocator_stuck_timeout * HZ;
}

void __bch2_wait_on_allocator(struct bch_fs *c, struct closure *cl)
{
	unsigned t = allocator_wait_timeout(c);

	if (t && closure_sync_timeout(cl, t)) {
		c->allocator_last_stuck = jiffies;
		bch2_print_allocator_stuck(c);
	}

	closure_sync(cl);
}
+7 −2
Original line number Diff line number Diff line
@@ -223,7 +223,7 @@ static inline struct write_point_specifier writepoint_ptr(struct write_point *wp
void bch2_fs_allocator_foreground_init(struct bch_fs *);

void bch2_open_bucket_to_text(struct printbuf *, struct bch_fs *, struct open_bucket *);
void bch2_open_buckets_to_text(struct printbuf *, struct bch_fs *);
void bch2_open_buckets_to_text(struct printbuf *, struct bch_fs *, struct bch_dev *);
void bch2_open_buckets_partial_to_text(struct printbuf *, struct bch_fs *);

void bch2_write_points_to_text(struct printbuf *, struct bch_fs *);
@@ -231,6 +231,11 @@ void bch2_write_points_to_text(struct printbuf *, struct bch_fs *);
void bch2_fs_alloc_debug_to_text(struct printbuf *, struct bch_fs *);
void bch2_dev_alloc_debug_to_text(struct printbuf *, struct bch_dev *);

void bch2_print_allocator_stuck(struct bch_fs *);
void __bch2_wait_on_allocator(struct bch_fs *, struct closure *);
static inline void bch2_wait_on_allocator(struct bch_fs *c, struct closure *cl)
{
	if (cl->closure_get_happened)
		__bch2_wait_on_allocator(c, cl);
}

#endif /* _BCACHEFS_ALLOC_FOREGROUND_H */
+2 −0
Original line number Diff line number Diff line
@@ -893,6 +893,8 @@ struct bch_fs {
	struct bch_fs_usage_base __percpu *usage;
	u64 __percpu		*online_reserved;

	unsigned long		allocator_last_stuck;

	struct io_clock		io_clock[2];

	/* JOURNAL SEQ BLACKLIST */
+2 −0
Original line number Diff line number Diff line
@@ -836,6 +836,8 @@ LE64_BITMASK(BCH_SB_BACKGROUND_COMPRESSION_TYPE_HI,

LE64_BITMASK(BCH_SB_VERSION_UPGRADE_COMPLETE,
					struct bch_sb, flags[5],  0, 16);
LE64_BITMASK(BCH_SB_ALLOCATOR_STUCK_TIMEOUT,
					struct bch_sb, flags[5], 16, 32);

static inline __u64 BCH_SB_COMPRESSION_TYPE(const struct bch_sb *sb)
{
Loading