Commit 47799326 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet
Browse files

bcachefs: more key marking refactoring



prep work for erasure coding

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 103e2127
Loading
Loading
Loading
Loading
+18 −21
Original line number Diff line number Diff line
@@ -212,34 +212,31 @@ static int bch2_gc_mark_key(struct bch_fs *c, enum bkey_type type,
			    struct bkey_s_c k, bool initial)
{
	struct gc_pos pos = { 0 };
	unsigned flags = initial ? BCH_BUCKET_MARK_NOATOMIC : 0;
	unsigned flags =
		BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE|
		BCH_BUCKET_MARK_GC_LOCK_HELD|
		(initial ? BCH_BUCKET_MARK_NOATOMIC : 0);
	int ret = 0;

	switch (type) {
	case BKEY_TYPE_BTREE:
	case BKEY_TYPE_EXTENTS:
		if (initial) {
			ret = bch2_btree_mark_ptrs_initial(c, type, k);
			if (ret < 0)
				return ret;
		}

		bch2_mark_key(c, k, c->opts.btree_node_size,
			      BCH_DATA_BTREE, pos, NULL,
			      0, flags|
			      BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE|
			      BCH_BUCKET_MARK_GC_LOCK_HELD);
		break;
	case BKEY_TYPE_EXTENTS:
		if (initial) {
			ret = bch2_btree_mark_ptrs_initial(c, type, k);
			if (ret < 0)
				return ret;
	default:
		break;
	}

		bch2_mark_key(c, k, k.k->size, BCH_DATA_USER, pos, NULL,
			      0, flags|
			      BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE|
			      BCH_BUCKET_MARK_GC_LOCK_HELD);
	bch2_mark_key(c, type, k, true, k.k->size,
		      pos, NULL, 0, flags);

	switch (type) {
	case BKEY_TYPE_BTREE:
	case BKEY_TYPE_EXTENTS:
		ret = bch2_btree_key_recalc_oldest_gen(c, k);
		break;
	default:
@@ -473,10 +470,10 @@ static void bch2_mark_pending_btree_node_frees(struct bch_fs *c)

	for_each_pending_btree_node_free(c, as, d)
		if (d->index_update_done)
			bch2_mark_key(c, bkey_i_to_s_c(&d->key),
				      c->opts.btree_node_size,
				      BCH_DATA_BTREE, pos,
				      &stats, 0,
			bch2_mark_key(c, BKEY_TYPE_BTREE,
				      bkey_i_to_s_c(&d->key),
				      true, 0,
				      pos, &stats, 0,
				      BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE|
				      BCH_BUCKET_MARK_GC_LOCK_HELD);
	/*
+21 −16
Original line number Diff line number Diff line
@@ -211,8 +211,9 @@ static void bch2_btree_node_free_index(struct btree_update *as, struct btree *b,
	if (gc_pos_cmp(c->gc_pos, gc_phase(GC_PHASE_PENDING_DELETE)) < 0) {
		struct bch_fs_usage tmp = { 0 };

		bch2_mark_key(c, bkey_i_to_s_c(&d->key),
			     -c->opts.btree_node_size, BCH_DATA_BTREE, b
		bch2_mark_key(c, BKEY_TYPE_BTREE,
			      bkey_i_to_s_c(&d->key),
			      false, 0, b
			      ? gc_pos_btree_node(b)
			      : gc_pos_btree_root(as->btree_id),
			      &tmp, 0, 0);
@@ -290,8 +291,9 @@ static void bch2_btree_node_free_ondisk(struct bch_fs *c,

	BUG_ON(!pending->index_update_done);

	bch2_mark_key(c, bkey_i_to_s_c(&pending->key),
		     -c->opts.btree_node_size, BCH_DATA_BTREE,
	bch2_mark_key(c, BKEY_TYPE_BTREE,
		      bkey_i_to_s_c(&pending->key),
		      false, 0,
		      gc_phase(GC_PHASE_PENDING_DELETE),
		      &stats, 0, 0);
	/*
@@ -1092,8 +1094,9 @@ static void bch2_btree_set_root_inmem(struct btree_update *as, struct btree *b)

	__bch2_btree_set_root_inmem(c, b);

	bch2_mark_key(c, bkey_i_to_s_c(&b->key),
		      c->opts.btree_node_size, BCH_DATA_BTREE,
	bch2_mark_key(c, BKEY_TYPE_BTREE,
		      bkey_i_to_s_c(&b->key),
		      true, 0,
		      gc_pos_btree_root(b->btree_id),
		      &stats, 0, 0);

@@ -1180,8 +1183,9 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as, struct btree *b
	BUG_ON(insert->k.u64s > bch_btree_keys_u64s_remaining(c, b));

	if (bkey_extent_is_data(&insert->k))
		bch2_mark_key(c, bkey_i_to_s_c(insert),
			     c->opts.btree_node_size, BCH_DATA_BTREE,
		bch2_mark_key(c, BKEY_TYPE_BTREE,
			      bkey_i_to_s_c(insert),
			      true, 0,
			      gc_pos_btree_node(b), &stats, 0, 0);

	while ((k = bch2_btree_node_iter_peek_all(node_iter, b)) &&
@@ -1967,8 +1971,9 @@ static void __bch2_btree_node_update_key(struct bch_fs *c,

		bch2_btree_node_lock_write(b, iter);

		bch2_mark_key(c, bkey_i_to_s_c(&new_key->k_i),
			      c->opts.btree_node_size, BCH_DATA_BTREE,
		bch2_mark_key(c, BKEY_TYPE_BTREE,
			      bkey_i_to_s_c(&new_key->k_i),
			      true, 0,
			      gc_pos_btree_root(b->btree_id),
			      &stats, 0, 0);
		bch2_btree_node_free_index(as, NULL,
+87 −52
Original line number Diff line number Diff line
@@ -539,24 +539,10 @@ static int __disk_sectors(struct bch_extent_crc_unpacked crc, unsigned sectors)
				    crc.uncompressed_size));
}

/*
 * Checking against gc's position has to be done here, inside the cmpxchg()
 * loop, to avoid racing with the start of gc clearing all the marks - GC does
 * that with the gc pos seqlock held.
 */
static void bch2_mark_pointer(struct bch_fs *c,
			      struct bkey_s_c_extent e,
static s64 ptr_disk_sectors(struct bkey_s_c_extent e,
			    struct extent_ptr_decoded p,
			      s64 sectors, enum bch_data_type data_type,
			      unsigned replicas,
			      struct bch_fs_usage *fs_usage,
			      u64 journal_seq, unsigned flags)
			    s64 sectors)
{
	struct bucket_mark old, new;
	struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
	struct bucket *g = PTR_BUCKET(ca, &p.ptr);
	s64 uncompressed_sectors = sectors;
	u64 v;

	if (p.crc.compression_type) {
		unsigned old_sectors, new_sectors;
@@ -573,19 +559,25 @@ static void bch2_mark_pointer(struct bch_fs *c,
			  +__disk_sectors(p.crc, new_sectors);
	}

	return sectors;
}

/*
	 * fs level usage (which determines free space) is in uncompressed
	 * sectors, until copygc + compression is sorted out:
	 *
	 * note also that we always update @fs_usage, even when we otherwise
	 * wouldn't do anything because gc is running - this is because the
	 * caller still needs to account w.r.t. its disk reservation. It is
	 * caller's responsibility to not apply @fs_usage if gc is in progress.
 * Checking against gc's position has to be done here, inside the cmpxchg()
 * loop, to avoid racing with the start of gc clearing all the marks - GC does
 * that with the gc pos seqlock held.
 */
	fs_usage->replicas
		[!p.ptr.cached && replicas ? replicas - 1 : 0].data
		[!p.ptr.cached ? data_type : BCH_DATA_CACHED] +=
			uncompressed_sectors;
static void bch2_mark_pointer(struct bch_fs *c,
			      struct bkey_s_c_extent e,
			      struct extent_ptr_decoded p,
			      s64 sectors, enum bch_data_type data_type,
			      struct bch_fs_usage *fs_usage,
			      u64 journal_seq, unsigned flags)
{
	struct bucket_mark old, new;
	struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
	struct bucket *g = PTR_BUCKET(ca, &p.ptr);
	u64 v;

	if (flags & BCH_BUCKET_MARK_GC_WILL_VISIT) {
		if (journal_seq)
@@ -644,7 +636,7 @@ static void bch2_mark_pointer(struct bch_fs *c,
	       bucket_became_unavailable(c, old, new));
}

void bch2_mark_key(struct bch_fs *c, struct bkey_s_c k,
static void bch2_mark_extent(struct bch_fs *c, struct bkey_s_c k,
			     s64 sectors, enum bch_data_type data_type,
			     struct gc_pos pos,
			     struct bch_fs_usage *stats,
@@ -653,7 +645,55 @@ void bch2_mark_key(struct bch_fs *c, struct bkey_s_c k,
	unsigned replicas = bch2_extent_nr_dirty_ptrs(k);

	BUG_ON(replicas && replicas - 1 > ARRAY_SIZE(stats->replicas));
	BUG_ON(!sectors);

	switch (k.k->type) {
	case BCH_EXTENT:
	case BCH_EXTENT_CACHED: {
		struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
		const union bch_extent_entry *entry;
		struct extent_ptr_decoded p;

		extent_for_each_ptr_decode(e, p, entry) {
			s64 disk_sectors = ptr_disk_sectors(e, p, sectors);

			/*
			 * fs level usage (which determines free space) is in
			 * uncompressed sectors, until copygc + compression is
			 * sorted out:
			 *
			 * note also that we always update @fs_usage, even when
			 * we otherwise wouldn't do anything because gc is
			 * running - this is because the caller still needs to
			 * account w.r.t. its disk reservation. It is caller's
			 * responsibility to not apply @fs_usage if gc is in
			 * progress.
			 */
			stats->replicas
				[!p.ptr.cached && replicas ? replicas - 1 : 0].data
				[!p.ptr.cached ? data_type : BCH_DATA_CACHED] +=
					sectors;

			bch2_mark_pointer(c, e, p, disk_sectors, data_type,
					  stats, journal_seq, flags);
		}
		break;
	}
	case BCH_RESERVATION:
		if (replicas)
			stats->replicas[replicas - 1].persistent_reserved +=
				sectors * replicas;
		break;
	}
}

void bch2_mark_key(struct bch_fs *c,
		   enum bkey_type type, struct bkey_s_c k,
		   bool inserting, s64 sectors,
		   struct gc_pos pos,
		   struct bch_fs_usage *stats,
		   u64 journal_seq, unsigned flags)
{
	/*
	 * synchronization w.r.t. GC:
	 *
@@ -690,24 +730,19 @@ void bch2_mark_key(struct bch_fs *c, struct bkey_s_c k,
	if (!stats)
		stats = this_cpu_ptr(c->usage_percpu);

	switch (k.k->type) {
	case BCH_EXTENT:
	case BCH_EXTENT_CACHED: {
		struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
		const union bch_extent_entry *entry;
		struct extent_ptr_decoded p;

		BUG_ON(!sectors);

		extent_for_each_ptr_decode(e, p, entry)
			bch2_mark_pointer(c, e, p, sectors, data_type,
					  replicas, stats, journal_seq, flags);
	switch (type) {
	case BKEY_TYPE_BTREE:
		bch2_mark_extent(c, k, inserting
				 ?  c->opts.btree_node_size
				 : -c->opts.btree_node_size,
				 BCH_DATA_BTREE,
				 pos, stats, journal_seq, flags);
		break;
	}
	case BCH_RESERVATION:
		if (replicas)
			stats->replicas[replicas - 1].persistent_reserved +=
				sectors * replicas;
	case BKEY_TYPE_EXTENTS:
		bch2_mark_extent(c, k, sectors, BCH_DATA_USER,
				 pos, stats, journal_seq, flags);
		break;
	default:
		break;
	}
	percpu_up_read(&c->usage_lock);
+3 −2
Original line number Diff line number Diff line
@@ -204,8 +204,9 @@ void bch2_mark_metadata_bucket(struct bch_fs *, struct bch_dev *,
#define BCH_BUCKET_MARK_GC_WILL_VISIT		(1 << 2)
#define BCH_BUCKET_MARK_GC_LOCK_HELD		(1 << 3)

void bch2_mark_key(struct bch_fs *, struct bkey_s_c, s64, enum bch_data_type,
		   struct gc_pos, struct bch_fs_usage *, u64, unsigned);
void bch2_mark_key(struct bch_fs *, enum bkey_type, struct bkey_s_c,
		   bool, s64, struct gc_pos,
		   struct bch_fs_usage *, u64, unsigned);

void bch2_recalc_sectors_available(struct bch_fs *);

+3 −2
Original line number Diff line number Diff line
@@ -1009,8 +1009,9 @@ static void bch2_add_sectors(struct extent_insert_state *s,
	if (!sectors)
		return;

	bch2_mark_key(c, k, sectors, BCH_DATA_USER, gc_pos_btree_node(b),
		      &s->stats, s->trans->journal_res.seq, 0);
	bch2_mark_key(c, BKEY_TYPE_EXTENTS, k, sectors > 0, sectors,
		      gc_pos_btree_node(b), &s->stats,
		      s->trans->journal_res.seq, 0);
}

static void bch2_subtract_sectors(struct extent_insert_state *s,