bcachefs: btree_gc can now handle unknown btrees
BugLink: https://bugs.launchpad.net/bugs/2076435 commit 088d0de81220a74d7d553febb81656927f10bb16 upstream. 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: Kent Overstreet <kent.overstreet@linux.dev> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Portia Stephens <portia.stephens@canonical.com> Signed-off-by: Roxana Nicolescu <roxana.nicolescu@canonical.com>
This commit is contained in:
committed by
Stefan Bader
parent
1bcb8e7f63
commit
c7ff906634
+1
-42
@@ -451,6 +451,7 @@ enum bch_time_stats {
|
||||
};
|
||||
|
||||
#include "alloc_types.h"
|
||||
#include "btree_gc_types.h"
|
||||
#include "btree_types.h"
|
||||
#include "btree_write_buffer_types.h"
|
||||
#include "buckets_types.h"
|
||||
@@ -480,48 +481,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_PENDING_DELETE,
|
||||
};
|
||||
|
||||
struct gc_pos {
|
||||
enum gc_phase phase;
|
||||
struct bpos pos;
|
||||
unsigned level;
|
||||
};
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
@@ -1077,8 +1077,7 @@ fsck_err:
|
||||
|
||||
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, bool initial, bool metadata_only)
|
||||
@@ -1123,7 +1122,7 @@ static void mark_metadata_sectors(struct bch_fs *c, struct bch_dev *ca,
|
||||
min_t(u64, bucket_to_sector(ca, b + 1), end) - start;
|
||||
|
||||
bch2_mark_metadata_bucket(c, ca, b, type, sectors,
|
||||
gc_phase(GC_PHASE_SB), flags);
|
||||
gc_phase(GC_PHASE_sb), flags);
|
||||
b++;
|
||||
start += sectors;
|
||||
} while (start < end);
|
||||
@@ -1152,14 +1151,14 @@ static void bch2_mark_dev_superblock(struct bch_fs *c, struct bch_dev *ca,
|
||||
b = ca->journal.buckets[i];
|
||||
bch2_mark_metadata_bucket(c, ca, b, BCH_DATA_journal,
|
||||
ca->mi.bucket_size,
|
||||
gc_phase(GC_PHASE_SB), flags);
|
||||
gc_phase(GC_PHASE_sb), flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void 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));
|
||||
|
||||
for_each_online_member(c, ca)
|
||||
bch2_mark_dev_superblock(c, ca, BTREE_TRIGGER_GC);
|
||||
@@ -1773,7 +1772,7 @@ int bch2_gc(struct bch_fs *c, bool initial, bool metadata_only)
|
||||
if (ret)
|
||||
goto out;
|
||||
again:
|
||||
gc_pos_set(c, gc_phase(GC_PHASE_START));
|
||||
gc_pos_set(c, gc_phase(GC_PHASE_start));
|
||||
|
||||
bch2_mark_superblocks(c);
|
||||
|
||||
@@ -1800,7 +1799,7 @@ again:
|
||||
*/
|
||||
bch_info(c, "Second GC pass needed, restarting:");
|
||||
clear_bit(BCH_FS_need_another_gc, &c->flags);
|
||||
__gc_pos_set(c, gc_phase(GC_PHASE_NOT_RUNNING));
|
||||
__gc_pos_set(c, gc_phase(GC_PHASE_not_running));
|
||||
|
||||
bch2_gc_stripes_reset(c, metadata_only);
|
||||
bch2_gc_alloc_reset(c, metadata_only);
|
||||
@@ -1827,7 +1826,7 @@ out:
|
||||
|
||||
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);
|
||||
|
||||
+22
-26
@@ -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 *);
|
||||
@@ -35,38 +36,17 @@ int bch2_gc_thread_start(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,
|
||||
.pos = POS_MIN,
|
||||
.level = 0,
|
||||
};
|
||||
return (struct gc_pos) { .phase = phase, };
|
||||
}
|
||||
|
||||
static inline int gc_pos_cmp(struct gc_pos l, struct gc_pos r)
|
||||
{
|
||||
return cmp_int(l.phase, r.phase) ?:
|
||||
bpos_cmp(l.pos, r.pos) ?:
|
||||
cmp_int(l.level, r.level);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct gc_pos gc_pos_btree(enum btree_id id,
|
||||
static inline struct gc_pos gc_pos_btree(enum btree_id btree,
|
||||
struct bpos pos, unsigned level)
|
||||
{
|
||||
return (struct gc_pos) {
|
||||
.phase = btree_id_to_gc_phase(id),
|
||||
.pos = pos,
|
||||
.phase = GC_PHASE_btree,
|
||||
.btree = btree,
|
||||
.level = level,
|
||||
.pos = pos,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -91,6 +71,22 @@ static inline struct gc_pos gc_pos_btree_root(enum btree_id id)
|
||||
return gc_pos_btree(id, SPOS_MAX, BTREE_MAX_DEPTH);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/* 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
@@ -878,7 +878,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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user