Commit 088d0de8 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: btree_gc can now handle unknown btrees



Compatibility fix - we no longer have a separate table for which order
gc walks btrees in, and special case the stripes btree directly.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent b4131076
Loading
Loading
Loading
Loading
+1 −43
Original line number Diff line number Diff line
@@ -457,6 +457,7 @@ enum bch_time_stats {
};

#include "alloc_types.h"
#include "btree_gc_types.h"
#include "btree_types.h"
#include "btree_node_scan_types.h"
#include "btree_write_buffer_types.h"
@@ -488,49 +489,6 @@ enum bch_time_stats {

struct btree;

enum gc_phase {
	GC_PHASE_NOT_RUNNING,
	GC_PHASE_START,
	GC_PHASE_SB,

	GC_PHASE_BTREE_stripes,
	GC_PHASE_BTREE_extents,
	GC_PHASE_BTREE_inodes,
	GC_PHASE_BTREE_dirents,
	GC_PHASE_BTREE_xattrs,
	GC_PHASE_BTREE_alloc,
	GC_PHASE_BTREE_quotas,
	GC_PHASE_BTREE_reflink,
	GC_PHASE_BTREE_subvolumes,
	GC_PHASE_BTREE_snapshots,
	GC_PHASE_BTREE_lru,
	GC_PHASE_BTREE_freespace,
	GC_PHASE_BTREE_need_discard,
	GC_PHASE_BTREE_backpointers,
	GC_PHASE_BTREE_bucket_gens,
	GC_PHASE_BTREE_snapshot_trees,
	GC_PHASE_BTREE_deleted_inodes,
	GC_PHASE_BTREE_logged_ops,
	GC_PHASE_BTREE_rebalance_work,
	GC_PHASE_BTREE_subvolume_children,

	GC_PHASE_PENDING_DELETE,
};

struct gc_pos {
	enum gc_phase		phase;
	u16			level;
	struct bpos		pos;
};

struct reflink_gc {
	u64		offset;
	u32		size;
	u32		refcount;
};

typedef GENRADIX(struct reflink_gc) reflink_gc_table;

struct io_count {
	u64			sectors[2][BCH_DATA_NR];
};
+4 −5
Original line number Diff line number Diff line
@@ -673,8 +673,7 @@ static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree, bool in

static inline int btree_id_gc_phase_cmp(enum btree_id l, enum btree_id r)
{
	return  (int) btree_id_to_gc_phase(l) -
		(int) btree_id_to_gc_phase(r);
	return cmp_int(gc_btree_order(l), gc_btree_order(r));
}

static int bch2_gc_btrees(struct bch_fs *c)
@@ -711,7 +710,7 @@ static int bch2_gc_btrees(struct bch_fs *c)
static int bch2_mark_superblocks(struct bch_fs *c)
{
	mutex_lock(&c->sb_lock);
	gc_pos_set(c, gc_phase(GC_PHASE_SB));
	gc_pos_set(c, gc_phase(GC_PHASE_sb));

	int ret = bch2_trans_mark_dev_sbs_flags(c, BTREE_TRIGGER_gc);
	mutex_unlock(&c->sb_lock);
@@ -1209,7 +1208,7 @@ int bch2_check_allocations(struct bch_fs *c)
	if (ret)
		goto out;

	gc_pos_set(c, gc_phase(GC_PHASE_START));
	gc_pos_set(c, gc_phase(GC_PHASE_start));

	ret = bch2_mark_superblocks(c);
	BUG_ON(ret);
@@ -1231,7 +1230,7 @@ int bch2_check_allocations(struct bch_fs *c)

	percpu_down_write(&c->mark_lock);
	/* Indicates that gc is no longer in progress: */
	__gc_pos_set(c, gc_phase(GC_PHASE_NOT_RUNNING));
	__gc_pos_set(c, gc_phase(GC_PHASE_not_running));

	bch2_gc_free(c);
	percpu_up_write(&c->mark_lock);
+20 −24
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
#define _BCACHEFS_BTREE_GC_H

#include "bkey.h"
#include "btree_gc_types.h"
#include "btree_types.h"

int bch2_check_topology(struct bch_fs *);
@@ -32,36 +33,15 @@ int bch2_check_allocations(struct bch_fs *);
/* Position of (the start of) a gc phase: */
static inline struct gc_pos gc_phase(enum gc_phase phase)
{
	return (struct gc_pos) {
		.phase	= phase,
		.level	= 0,
		.pos	= POS_MIN,
	};
}

static inline int gc_pos_cmp(struct gc_pos l, struct gc_pos r)
{
	return   cmp_int(l.phase, r.phase) ?:
		-cmp_int(l.level, r.level) ?:
		 bpos_cmp(l.pos, r.pos);
}

static inline enum gc_phase btree_id_to_gc_phase(enum btree_id id)
{
	switch (id) {
#define x(name, v, ...) case BTREE_ID_##name: return GC_PHASE_BTREE_##name;
	BCH_BTREE_IDS()
#undef x
	default:
		BUG();
	}
	return (struct gc_pos) { .phase	= phase, };
}

static inline struct gc_pos gc_pos_btree(enum btree_id btree, unsigned level,
					 struct bpos pos)
{
	return (struct gc_pos) {
		.phase	= btree_id_to_gc_phase(btree),
		.phase	= GC_PHASE_btree,
		.btree	= btree,
		.level	= level,
		.pos	= pos,
	};
@@ -76,6 +56,22 @@ static inline struct gc_pos gc_pos_btree_node(struct btree *b)
	return gc_pos_btree(b->c.btree_id, b->c.level, b->key.k.p);
}

static inline int gc_btree_order(enum btree_id btree)
{
	if (btree == BTREE_ID_stripes)
		return -1;
	return btree;
}

static inline int gc_pos_cmp(struct gc_pos l, struct gc_pos r)
{
	return   cmp_int(l.phase, r.phase) ?:
		 cmp_int(gc_btree_order(l.btree),
			 gc_btree_order(r.btree)) ?:
		-cmp_int(l.level, r.level) ?:
		 bpos_cmp(l.pos, r.pos);
}

static inline bool gc_visited(struct bch_fs *c, struct gc_pos pos)
{
	unsigned seq;
+29 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BCACHEFS_BTREE_GC_TYPES_H
#define _BCACHEFS_BTREE_GC_TYPES_H

#include <linux/generic-radix-tree.h>

enum gc_phase {
	GC_PHASE_not_running,
	GC_PHASE_start,
	GC_PHASE_sb,
	GC_PHASE_btree,
};

struct gc_pos {
	enum gc_phase		phase:8;
	enum btree_id		btree:8;
	u16			level;
	struct bpos		pos;
};

struct reflink_gc {
	u64		offset;
	u32		size;
	u32		refcount;
};

typedef GENRADIX(struct reflink_gc) reflink_gc_table;

#endif /* _BCACHEFS_BTREE_GC_TYPES_H */
+1 −1
Original line number Diff line number Diff line
@@ -908,7 +908,7 @@ static int __ec_stripe_mem_alloc(struct bch_fs *c, size_t idx, gfp_t gfp)
	if (!genradix_ptr_alloc(&c->stripes, idx, gfp))
		return -BCH_ERR_ENOMEM_ec_stripe_mem_alloc;

	if (c->gc_pos.phase != GC_PHASE_NOT_RUNNING &&
	if (c->gc_pos.phase != GC_PHASE_not_running &&
	    !genradix_ptr_alloc(&c->gc_stripes, idx, gfp))
		return -BCH_ERR_ENOMEM_ec_stripe_mem_alloc;