Commit fb3f57bb authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: rebalance_work



This adds a new btree, rebalance_work, to eliminate scanning required
for finding extents that need work done on them in the background - i.e.
for the background_target and background_compression options.

rebalance_work is a bitset btree, where a KEY_TYPE_set corresponds to an
extent in the extents or reflink btree at the same pos.

A new extent field is added, bch_extent_rebalance, which indicates that
this extent has work that needs to be done in the background - and which
options to use. This allows per-inode options to be propagated to
indirect extents - at least in some circumstances. In this patch,
changing IO options on a file will not propagate the new options to
indirect extents pointed to by that file.

Updating (setting/clearing) the rebalance_work btree is done by the
extent trigger, which looks at the bch_extent_rebalance field.

Scanning is still requrired after changing IO path options - either just
for a given inode, or for the whole filesystem. We indicate that
scanning is required by adding a KEY_TYPE_cookie key to the
rebalance_work btree: the cookie counter is so that we can detect that
scanning is still required when an option has been flipped mid-way
through an existing scan.

Future possible work:
 - Propagate options to indirect extents when being changed
 - Add other IO path options - nr_replicas, ec, to rebalance_work so
   they can be applied in the background when they change
 - Add a counter, for bcachefs fs usage output, showing the pending
   amount of rebalance work: we'll probably want to do this after the
   disk space accounting rewrite (moving it to a new btree)

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 55c11a15
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -464,6 +464,7 @@ enum gc_phase {
	GC_PHASE_BTREE_snapshot_trees,
	GC_PHASE_BTREE_deleted_inodes,
	GC_PHASE_BTREE_logged_ops,
	GC_PHASE_BTREE_rebalance_work,

	GC_PHASE_PENDING_DELETE,
};
+12 −22
Original line number Diff line number Diff line
@@ -613,31 +613,17 @@ struct bch_extent_stripe_ptr {
#endif
};

struct bch_extent_reservation {
#if defined(__LITTLE_ENDIAN_BITFIELD)
	__u64			type:6,
				unused:22,
				replicas:4,
				generation:32;
#elif defined (__BIG_ENDIAN_BITFIELD)
	__u64			generation:32,
				replicas:4,
				unused:22,
				type:6;
#endif
};

struct bch_extent_rebalance {
#if defined(__LITTLE_ENDIAN_BITFIELD)
	__u64			type:7,
				unused:33,
				compression:8,
	__u64			type:6,
				unused:34,
				compression:8, /* enum bch_compression_opt */
				target:16;
#elif defined (__BIG_ENDIAN_BITFIELD)
	__u64			target:16,
				compression:8,
				unused:33,
				type:7;
				unused:34,
				type:6;
#endif
};

@@ -1682,7 +1668,9 @@ struct bch_sb_field_journal_seq_blacklist {
	x(snapshot_skiplists,		BCH_VERSION(1,  1),		\
	  BIT_ULL(BCH_RECOVERY_PASS_check_snapshots))			\
	x(deleted_inodes,		BCH_VERSION(1,  2),		\
	  BIT_ULL(BCH_RECOVERY_PASS_check_inodes))
	  BIT_ULL(BCH_RECOVERY_PASS_check_inodes))			\
	x(rebalance_work,		BCH_VERSION(1,  3),		\
	  BIT_ULL(BCH_RECOVERY_PASS_set_fs_needs_rebalance))

enum bcachefs_metadata_version {
	bcachefs_metadata_version_min = 9,
@@ -1693,7 +1681,7 @@ enum bcachefs_metadata_version {
};

static const __maybe_unused
unsigned bcachefs_metadata_required_upgrade_below = bcachefs_metadata_version_major_minor;
unsigned bcachefs_metadata_required_upgrade_below = bcachefs_metadata_version_rebalance_work;

#define bcachefs_metadata_version_current	(bcachefs_metadata_version_max - 1)

@@ -2306,7 +2294,9 @@ enum btree_id_flags {
	  BIT_ULL(KEY_TYPE_set))						\
	x(logged_ops,		17,	0,					\
	  BIT_ULL(KEY_TYPE_logged_op_truncate)|					\
	  BIT_ULL(KEY_TYPE_logged_op_finsert))
	  BIT_ULL(KEY_TYPE_logged_op_finsert))					\
	x(rebalance_work,	18,	BTREE_ID_SNAPSHOTS,			\
	  BIT_ULL(KEY_TYPE_set)|BIT_ULL(KEY_TYPE_cookie))

enum btree_id {
#define x(name, nr, ...) BTREE_ID_##name = nr,
+10 −0
Original line number Diff line number Diff line
@@ -1536,6 +1536,16 @@ int bch2_trans_mark_extent(struct btree_trans *trans,
			   struct bkey_s_c old, struct bkey_i *new,
			   unsigned flags)
{
	struct bch_fs *c = trans->c;
	int mod = (int) bch2_bkey_needs_rebalance(c, bkey_i_to_s_c(new)) -
		  (int) bch2_bkey_needs_rebalance(c, old);

	if (mod) {
		int ret = bch2_btree_bit_mod(trans, BTREE_ID_rebalance_work, new->k.p, mod > 0);
		if (ret)
			return ret;
	}

	return trigger_run_overwrite_then_insert(__trans_mark_extent, trans, btree_id, level, old, new, flags);
}

+13 −5
Original line number Diff line number Diff line
@@ -697,18 +697,26 @@ int bch2_opt_compression_parse(struct bch_fs *c, const char *_val, u64 *res,
	return ret;
}

void bch2_opt_compression_to_text(struct printbuf *out,
				  struct bch_fs *c,
				  struct bch_sb *sb,
				  u64 v)
void bch2_compression_opt_to_text(struct printbuf *out, u64 v)
{
	struct bch_compression_opt opt = bch2_compression_decode(v);

	if (opt.type < BCH_COMPRESSION_OPT_NR)
		prt_str(out, bch2_compression_opts[opt.type]);
	else
		prt_printf(out, "(unknown compression opt %u)", opt.type);
	if (opt.level)
		prt_printf(out, ":%u", opt.level);
}

void bch2_opt_compression_to_text(struct printbuf *out,
				  struct bch_fs *c,
				  struct bch_sb *sb,
				  u64 v)
{
	return bch2_compression_opt_to_text(out, v);
}

int bch2_opt_compression_validate(u64 v, struct printbuf *err)
{
	if (!bch2_compression_opt_valid(v)) {
+2 −0
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ int bch2_check_set_has_compressed_data(struct bch_fs *, unsigned);
void bch2_fs_compress_exit(struct bch_fs *);
int bch2_fs_compress_init(struct bch_fs *);

void bch2_compression_opt_to_text(struct printbuf *, u64);

int bch2_opt_compression_parse(struct bch_fs *, const char *, u64 *, struct printbuf *);
void bch2_opt_compression_to_text(struct printbuf *, struct bch_fs *, struct bch_sb *, u64);
int bch2_opt_compression_validate(u64, struct printbuf *);
Loading