Commit 47d2080e authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Kill bch2_bkey_ptr_data_type()

Remove some duplication, and inconsistency between check_fix_ptrs and
the main ptr marking paths
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent dcc1c045
...@@ -29,8 +29,7 @@ static bool extent_matches_bp(struct bch_fs *c, ...@@ -29,8 +29,7 @@ static bool extent_matches_bp(struct bch_fs *c,
if (p.ptr.cached) if (p.ptr.cached)
continue; continue;
bch2_extent_ptr_to_bp(c, btree_id, level, k, p, bch2_extent_ptr_to_bp(c, btree_id, level, k, p, entry, &bucket2, &bp2);
&bucket2, &bp2);
if (bpos_eq(bucket, bucket2) && if (bpos_eq(bucket, bucket2) &&
!memcmp(&bp, &bp2, sizeof(bp))) !memcmp(&bp, &bp2, sizeof(bp)))
return true; return true;
...@@ -507,8 +506,7 @@ static int check_extent_to_backpointers(struct btree_trans *trans, ...@@ -507,8 +506,7 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
if (p.ptr.cached) if (p.ptr.cached)
continue; continue;
bch2_extent_ptr_to_bp(c, btree, level, bch2_extent_ptr_to_bp(c, btree, level, k, p, entry, &bucket_pos, &bp);
k, p, &bucket_pos, &bp);
ret = check_bp_exists(trans, s, bucket_pos, bp, k); ret = check_bp_exists(trans, s, bucket_pos, bp, k);
if (ret) if (ret)
......
...@@ -90,20 +90,40 @@ static inline int bch2_bucket_backpointer_mod(struct btree_trans *trans, ...@@ -90,20 +90,40 @@ static inline int bch2_bucket_backpointer_mod(struct btree_trans *trans,
return bch2_trans_update_buffered(trans, BTREE_ID_backpointers, &bp_k.k_i); return bch2_trans_update_buffered(trans, BTREE_ID_backpointers, &bp_k.k_i);
} }
static inline enum bch_data_type bkey_ptr_data_type(enum btree_id btree_id, unsigned level, static inline enum bch_data_type bch2_bkey_ptr_data_type(struct bkey_s_c k,
struct bkey_s_c k, struct extent_ptr_decoded p) struct extent_ptr_decoded p,
const union bch_extent_entry *entry)
{ {
return level ? BCH_DATA_btree : switch (k.k->type) {
p.has_ec ? BCH_DATA_stripe : case KEY_TYPE_btree_ptr:
BCH_DATA_user; case KEY_TYPE_btree_ptr_v2:
return BCH_DATA_btree;
case KEY_TYPE_extent:
case KEY_TYPE_reflink_v:
return p.has_ec ? BCH_DATA_stripe : BCH_DATA_user;
case KEY_TYPE_stripe: {
const struct bch_extent_ptr *ptr = &entry->ptr;
struct bkey_s_c_stripe s = bkey_s_c_to_stripe(k);
BUG_ON(ptr < s.v->ptrs ||
ptr >= s.v->ptrs + s.v->nr_blocks);
return ptr >= s.v->ptrs + s.v->nr_blocks - s.v->nr_redundant
? BCH_DATA_parity
: BCH_DATA_user;
}
default:
BUG();
}
} }
static inline void bch2_extent_ptr_to_bp(struct bch_fs *c, static inline void bch2_extent_ptr_to_bp(struct bch_fs *c,
enum btree_id btree_id, unsigned level, enum btree_id btree_id, unsigned level,
struct bkey_s_c k, struct extent_ptr_decoded p, struct bkey_s_c k, struct extent_ptr_decoded p,
const union bch_extent_entry *entry,
struct bpos *bucket_pos, struct bch_backpointer *bp) struct bpos *bucket_pos, struct bch_backpointer *bp)
{ {
enum bch_data_type data_type = bkey_ptr_data_type(btree_id, level, k, p); enum bch_data_type data_type = bch2_bkey_ptr_data_type(k, p, entry);
s64 sectors = level ? btree_sectors(c) : k.k->size; s64 sectors = level ? btree_sectors(c) : k.k->size;
u32 bucket_offset; u32 bucket_offset;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "bcachefs.h" #include "bcachefs.h"
#include "alloc_background.h" #include "alloc_background.h"
#include "alloc_foreground.h" #include "alloc_foreground.h"
#include "backpointers.h"
#include "bkey_methods.h" #include "bkey_methods.h"
#include "bkey_buf.h" #include "bkey_buf.h"
#include "btree_journal_iter.h" #include "btree_journal_iter.h"
...@@ -508,7 +509,7 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id ...@@ -508,7 +509,7 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
bkey_for_each_ptr_decode(k->k, ptrs_c, p, entry_c) { bkey_for_each_ptr_decode(k->k, ptrs_c, p, entry_c) {
struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr); struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, &entry_c->ptr); enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, p, entry_c);
if (fsck_err_on(!g->gen_valid, if (fsck_err_on(!g->gen_valid,
c, ptr_to_missing_alloc_key, c, ptr_to_missing_alloc_key,
...@@ -574,7 +575,8 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id ...@@ -574,7 +575,8 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
continue; continue;
if (fsck_err_on(bucket_data_type(g->data_type) && if (fsck_err_on(bucket_data_type(g->data_type) &&
bucket_data_type(g->data_type) != data_type, c, bucket_data_type(g->data_type) !=
bucket_data_type(data_type), c,
ptr_bucket_data_type_mismatch, ptr_bucket_data_type_mismatch,
"bucket %u:%zu different types of data in same bucket: %s, %s\n" "bucket %u:%zu different types of data in same bucket: %s, %s\n"
"while marking %s", "while marking %s",
...@@ -615,18 +617,13 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id ...@@ -615,18 +617,13 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
} }
if (do_update) { if (do_update) {
struct bkey_ptrs ptrs;
union bch_extent_entry *entry;
struct bch_extent_ptr *ptr;
struct bkey_i *new;
if (is_root) { if (is_root) {
bch_err(c, "cannot update btree roots yet"); bch_err(c, "cannot update btree roots yet");
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
new = kmalloc(bkey_bytes(k->k), GFP_KERNEL); struct bkey_i *new = kmalloc(bkey_bytes(k->k), GFP_KERNEL);
if (!new) { if (!new) {
ret = -BCH_ERR_ENOMEM_gc_repair_key; ret = -BCH_ERR_ENOMEM_gc_repair_key;
bch_err_msg(c, ret, "allocating new key"); bch_err_msg(c, ret, "allocating new key");
...@@ -641,7 +638,7 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id ...@@ -641,7 +638,7 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
* btree node isn't there anymore, the read path will * btree node isn't there anymore, the read path will
* sort it out: * sort it out:
*/ */
ptrs = bch2_bkey_ptrs(bkey_i_to_s(new)); struct bkey_ptrs ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
bkey_for_each_ptr(ptrs, ptr) { bkey_for_each_ptr(ptrs, ptr) {
struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
struct bucket *g = PTR_GC_BUCKET(ca, ptr); struct bucket *g = PTR_GC_BUCKET(ca, ptr);
...@@ -649,19 +646,26 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id ...@@ -649,19 +646,26 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
ptr->gen = g->gen; ptr->gen = g->gen;
} }
} else { } else {
bch2_bkey_drop_ptrs(bkey_i_to_s(new), ptr, ({ struct bkey_ptrs ptrs;
struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); union bch_extent_entry *entry;
struct bucket *g = PTR_GC_BUCKET(ca, ptr); restart_drop_ptrs:
enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, ptr); ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
bkey_for_each_ptr_decode(bkey_i_to_s(new).k, ptrs, p, entry) {
(ptr->cached && struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
(!g->gen_valid || gen_cmp(ptr->gen, g->gen) > 0)) || struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
(!ptr->cached && enum bch_data_type data_type = bch2_bkey_ptr_data_type(bkey_i_to_s_c(new), p, entry);
gen_cmp(ptr->gen, g->gen) < 0) ||
gen_cmp(g->gen, ptr->gen) > BUCKET_GC_GEN_MAX || if ((p.ptr.cached &&
(g->data_type && (!g->gen_valid || gen_cmp(p.ptr.gen, g->gen) > 0)) ||
g->data_type != data_type); (!p.ptr.cached &&
})); gen_cmp(p.ptr.gen, g->gen) < 0) ||
gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX ||
(g->data_type &&
g->data_type != data_type)) {
bch2_bkey_drop_ptr(bkey_i_to_s(new), &entry->ptr);
goto restart_drop_ptrs;
}
}
again: again:
ptrs = bch2_bkey_ptrs(bkey_i_to_s(new)); ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
bkey_extent_entry_for_each(ptrs, entry) { bkey_extent_entry_for_each(ptrs, entry) {
...@@ -736,10 +740,6 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id, ...@@ -736,10 +740,6 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
BUG_ON(bch2_journal_seq_verify && BUG_ON(bch2_journal_seq_verify &&
k->k->version.lo > atomic64_read(&c->journal.seq)); k->k->version.lo > atomic64_read(&c->journal.seq));
ret = bch2_check_fix_ptrs(trans, btree_id, level, is_root, k);
if (ret)
goto err;
if (fsck_err_on(k->k->version.lo > atomic64_read(&c->key_version), c, if (fsck_err_on(k->k->version.lo > atomic64_read(&c->key_version), c,
bkey_version_in_future, bkey_version_in_future,
"key version number higher than recorded: %llu > %llu", "key version number higher than recorded: %llu > %llu",
...@@ -748,8 +748,13 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id, ...@@ -748,8 +748,13 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
atomic64_set(&c->key_version, k->k->version.lo); atomic64_set(&c->key_version, k->k->version.lo);
} }
ret = bch2_check_fix_ptrs(trans, btree_id, level, is_root, k);
if (ret)
goto err;
ret = commit_do(trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_key_trigger(trans, btree_id, level, old, unsafe_bkey_s_c_to_s(*k), BTREE_TRIGGER_GC)); bch2_key_trigger(trans, btree_id, level, old,
unsafe_bkey_s_c_to_s(*k), BTREE_TRIGGER_GC));
fsck_err: fsck_err:
err: err:
bch_err_fn(c, ret); bch_err_fn(c, ret);
......
...@@ -525,6 +525,7 @@ int bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca, ...@@ -525,6 +525,7 @@ int bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
"different types of data in same bucket: %s, %s", "different types of data in same bucket: %s, %s",
bch2_data_type_str(g->data_type), bch2_data_type_str(g->data_type),
bch2_data_type_str(data_type))) { bch2_data_type_str(data_type))) {
BUG();
ret = -EIO; ret = -EIO;
goto err; goto err;
} }
...@@ -628,6 +629,7 @@ int bch2_check_bucket_ref(struct btree_trans *trans, ...@@ -628,6 +629,7 @@ int bch2_check_bucket_ref(struct btree_trans *trans,
bch2_data_type_str(ptr_data_type), bch2_data_type_str(ptr_data_type),
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k), buf.buf)); bch2_bkey_val_to_text(&buf, c, k), buf.buf));
BUG();
ret = -EIO; ret = -EIO;
goto err; goto err;
} }
...@@ -815,14 +817,14 @@ static int __mark_pointer(struct btree_trans *trans, ...@@ -815,14 +817,14 @@ static int __mark_pointer(struct btree_trans *trans,
static int bch2_trigger_pointer(struct btree_trans *trans, static int bch2_trigger_pointer(struct btree_trans *trans,
enum btree_id btree_id, unsigned level, enum btree_id btree_id, unsigned level,
struct bkey_s_c k, struct extent_ptr_decoded p, struct bkey_s_c k, struct extent_ptr_decoded p,
s64 *sectors, const union bch_extent_entry *entry,
unsigned flags) s64 *sectors, unsigned flags)
{ {
bool insert = !(flags & BTREE_TRIGGER_OVERWRITE); bool insert = !(flags & BTREE_TRIGGER_OVERWRITE);
struct bpos bucket; struct bpos bucket;
struct bch_backpointer bp; struct bch_backpointer bp;
bch2_extent_ptr_to_bp(trans->c, btree_id, level, k, p, &bucket, &bp); bch2_extent_ptr_to_bp(trans->c, btree_id, level, k, p, entry, &bucket, &bp);
*sectors = insert ? bp.bucket_len : -((s64) bp.bucket_len); *sectors = insert ? bp.bucket_len : -((s64) bp.bucket_len);
if (flags & BTREE_TRIGGER_TRANSACTIONAL) { if (flags & BTREE_TRIGGER_TRANSACTIONAL) {
...@@ -851,7 +853,7 @@ static int bch2_trigger_pointer(struct btree_trans *trans, ...@@ -851,7 +853,7 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
if (flags & BTREE_TRIGGER_GC) { if (flags & BTREE_TRIGGER_GC) {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
enum bch_data_type data_type = bkey_ptr_data_type(btree_id, level, k, p); enum bch_data_type data_type = bch2_bkey_ptr_data_type(k, p, entry);
percpu_down_read(&c->mark_lock); percpu_down_read(&c->mark_lock);
struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr); struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
...@@ -979,7 +981,7 @@ static int __trigger_extent(struct btree_trans *trans, ...@@ -979,7 +981,7 @@ static int __trigger_extent(struct btree_trans *trans,
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) { bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
s64 disk_sectors; s64 disk_sectors;
ret = bch2_trigger_pointer(trans, btree_id, level, k, p, &disk_sectors, flags); ret = bch2_trigger_pointer(trans, btree_id, level, k, p, entry, &disk_sectors, flags);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -596,30 +596,6 @@ static inline struct bch_devs_list bch2_bkey_cached_devs(struct bkey_s_c k) ...@@ -596,30 +596,6 @@ static inline struct bch_devs_list bch2_bkey_cached_devs(struct bkey_s_c k)
return ret; return ret;
} }
static inline unsigned bch2_bkey_ptr_data_type(struct bkey_s_c k, const struct bch_extent_ptr *ptr)
{
switch (k.k->type) {
case KEY_TYPE_btree_ptr:
case KEY_TYPE_btree_ptr_v2:
return BCH_DATA_btree;
case KEY_TYPE_extent:
case KEY_TYPE_reflink_v:
return BCH_DATA_user;
case KEY_TYPE_stripe: {
struct bkey_s_c_stripe s = bkey_s_c_to_stripe(k);
BUG_ON(ptr < s.v->ptrs ||
ptr >= s.v->ptrs + s.v->nr_blocks);
return ptr >= s.v->ptrs + s.v->nr_blocks - s.v->nr_redundant
? BCH_DATA_parity
: BCH_DATA_user;
}
default:
BUG();
}
}
unsigned bch2_bkey_nr_ptrs(struct bkey_s_c); unsigned bch2_bkey_nr_ptrs(struct bkey_s_c);
unsigned bch2_bkey_nr_ptrs_allocated(struct bkey_s_c); unsigned bch2_bkey_nr_ptrs_allocated(struct bkey_s_c);
unsigned bch2_bkey_nr_ptrs_fully_allocated(struct bkey_s_c); unsigned bch2_bkey_nr_ptrs_fully_allocated(struct bkey_s_c);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment