mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
bcachefs: Kill bch2_dev_bkey_exists() in backpointer code
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
1f2f92ec3f
commit
633cf06944
6 changed files with 102 additions and 52 deletions
|
@ -342,7 +342,7 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc
|
|||
struct bch_backpointer bp;
|
||||
struct bpos bp_pos = POS_MIN;
|
||||
|
||||
ret = bch2_get_next_backpointer(trans, POS(ca->dev_idx, b), -1,
|
||||
ret = bch2_get_next_backpointer(trans, ca, POS(ca->dev_idx, b), -1,
|
||||
&bp_pos, &bp,
|
||||
BTREE_ITER_nopreserve);
|
||||
if (ret) {
|
||||
|
|
|
@ -23,6 +23,7 @@ static bool extent_matches_bp(struct bch_fs *c,
|
|||
const union bch_extent_entry *entry;
|
||||
struct extent_ptr_decoded p;
|
||||
|
||||
rcu_read_lock();
|
||||
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
|
||||
struct bpos bucket2;
|
||||
struct bch_backpointer bp2;
|
||||
|
@ -30,13 +31,18 @@ static bool extent_matches_bp(struct bch_fs *c,
|
|||
if (p.ptr.cached)
|
||||
continue;
|
||||
|
||||
struct bch_dev *ca = bch2_dev_bkey_exists(c, p.ptr.dev);
|
||||
struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
|
||||
if (!ca)
|
||||
continue;
|
||||
|
||||
bch2_extent_ptr_to_bp(c, ca, btree_id, level, k, p, entry, &bucket2, &bp2);
|
||||
if (bpos_eq(bucket, bucket2) &&
|
||||
!memcmp(&bp, &bp2, sizeof(bp)))
|
||||
!memcmp(&bp, &bp2, sizeof(bp))) {
|
||||
rcu_read_unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -47,16 +53,21 @@ int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k,
|
|||
{
|
||||
struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
|
||||
|
||||
/* these will be caught by fsck */
|
||||
if (!bch2_dev_exists(c, bp.k->p.inode))
|
||||
rcu_read_lock();
|
||||
struct bch_dev *ca = bch2_dev_rcu(c, bp.k->p.inode);
|
||||
if (!ca) {
|
||||
/* these will be caught by fsck */
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bch_dev *ca = bch2_dev_bkey_exists(c, bp.k->p.inode);
|
||||
struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
|
||||
struct bpos bucket = bp_pos_to_bucket(ca, bp.k->p);
|
||||
struct bpos bp_pos = bucket_pos_to_bp_noerror(ca, bucket, bp.v->bucket_offset);
|
||||
rcu_read_unlock();
|
||||
int ret = 0;
|
||||
|
||||
bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
|
||||
!bpos_eq(bp.k->p, bucket_pos_to_bp_noerror(ca, bucket, bp.v->bucket_offset)),
|
||||
!bpos_eq(bp.k->p, bp_pos),
|
||||
c, err,
|
||||
backpointer_bucket_offset_wrong,
|
||||
"backpointer bucket_offset wrong");
|
||||
|
@ -77,10 +88,16 @@ void bch2_backpointer_to_text(struct printbuf *out, const struct bch_backpointer
|
|||
|
||||
void bch2_backpointer_k_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
|
||||
{
|
||||
if (bch2_dev_exists(c, k.k->p.inode)) {
|
||||
rcu_read_lock();
|
||||
struct bch_dev *ca = bch2_dev_rcu(c, k.k->p.inode);
|
||||
if (ca) {
|
||||
struct bpos bucket = bp_pos_to_bucket(ca, k.k->p);
|
||||
rcu_read_unlock();
|
||||
prt_str(out, "bucket=");
|
||||
bch2_bpos_to_text(out, bp_pos_to_bucket(c, k.k->p));
|
||||
bch2_bpos_to_text(out, bucket);
|
||||
prt_str(out, " ");
|
||||
} else {
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
bch2_backpointer_to_text(out, bkey_s_c_to_backpointer(k).v);
|
||||
|
@ -146,6 +163,7 @@ static noinline int backpointer_mod_err(struct btree_trans *trans,
|
|||
}
|
||||
|
||||
int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
|
||||
struct bch_dev *ca,
|
||||
struct bpos bucket,
|
||||
struct bch_backpointer bp,
|
||||
struct bkey_s_c orig_k,
|
||||
|
@ -162,7 +180,7 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
|
|||
return ret;
|
||||
|
||||
bkey_backpointer_init(&bp_k->k_i);
|
||||
bp_k->k.p = bucket_pos_to_bp(trans->c, bucket, bp.bucket_offset);
|
||||
bp_k->k.p = bucket_pos_to_bp(ca, bucket, bp.bucket_offset);
|
||||
bp_k->v = bp;
|
||||
|
||||
if (!insert) {
|
||||
|
@ -198,13 +216,13 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
|
|||
* Find the next backpointer >= *bp_offset:
|
||||
*/
|
||||
int bch2_get_next_backpointer(struct btree_trans *trans,
|
||||
struct bch_dev *ca,
|
||||
struct bpos bucket, int gen,
|
||||
struct bpos *bp_pos,
|
||||
struct bch_backpointer *bp,
|
||||
unsigned iter_flags)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bpos bp_end_pos = bucket_pos_to_bp(c, bpos_nosnap_successor(bucket), 0);
|
||||
struct bpos bp_end_pos = bucket_pos_to_bp(ca, bpos_nosnap_successor(bucket), 0);
|
||||
struct btree_iter alloc_iter = { NULL }, bp_iter = { NULL };
|
||||
struct bkey_s_c k;
|
||||
int ret = 0;
|
||||
|
@ -224,7 +242,7 @@ int bch2_get_next_backpointer(struct btree_trans *trans,
|
|||
goto done;
|
||||
}
|
||||
|
||||
*bp_pos = bpos_max(*bp_pos, bucket_pos_to_bp(c, bucket, 0));
|
||||
*bp_pos = bpos_max(*bp_pos, bucket_pos_to_bp(ca, bucket, 0));
|
||||
|
||||
for_each_btree_key_norestart(trans, bp_iter, BTREE_ID_backpointers,
|
||||
*bp_pos, iter_flags, k, ret) {
|
||||
|
@ -250,7 +268,6 @@ static void backpointer_not_found(struct btree_trans *trans,
|
|||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
|
||||
|
||||
/*
|
||||
* If we're using the btree write buffer, the backpointer we were
|
||||
|
@ -260,6 +277,10 @@ static void backpointer_not_found(struct btree_trans *trans,
|
|||
if (likely(!bch2_backpointers_no_use_write_buffer))
|
||||
return;
|
||||
|
||||
struct bpos bucket;
|
||||
if (!bp_pos_to_bucket_nodev(c, bp_pos, &bucket))
|
||||
return;
|
||||
|
||||
prt_printf(&buf, "backpointer doesn't match %s it points to:\n ",
|
||||
bp.level ? "btree node" : "extent");
|
||||
prt_printf(&buf, "bucket: ");
|
||||
|
@ -289,15 +310,17 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
|
|||
{
|
||||
if (likely(!bp.level)) {
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
|
||||
struct bkey_s_c k;
|
||||
|
||||
struct bpos bucket;
|
||||
if (!bp_pos_to_bucket_nodev(c, bp_pos, &bucket))
|
||||
return bkey_s_c_err(-EIO);
|
||||
|
||||
bch2_trans_node_iter_init(trans, iter,
|
||||
bp.btree_id,
|
||||
bp.pos,
|
||||
0, 0,
|
||||
iter_flags);
|
||||
k = bch2_btree_iter_peek_slot(iter);
|
||||
struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
|
||||
if (bkey_err(k)) {
|
||||
bch2_trans_iter_exit(trans, iter);
|
||||
return k;
|
||||
|
@ -326,18 +349,20 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
|
|||
struct bch_backpointer bp)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
|
||||
struct btree *b;
|
||||
|
||||
BUG_ON(!bp.level);
|
||||
|
||||
struct bpos bucket;
|
||||
if (!bp_pos_to_bucket_nodev(c, bp_pos, &bucket))
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
bch2_trans_node_iter_init(trans, iter,
|
||||
bp.btree_id,
|
||||
bp.pos,
|
||||
0,
|
||||
bp.level - 1,
|
||||
0);
|
||||
b = bch2_btree_iter_peek_node(iter);
|
||||
struct btree *b = bch2_btree_iter_peek_node(iter);
|
||||
if (IS_ERR_OR_NULL(b))
|
||||
goto err;
|
||||
|
||||
|
@ -368,16 +393,16 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_
|
|||
struct printbuf buf = PRINTBUF;
|
||||
int ret = 0;
|
||||
|
||||
if (fsck_err_on(!bch2_dev_exists(c, k.k->p.inode), c,
|
||||
backpointer_to_missing_device,
|
||||
"backpointer for missing device:\n%s",
|
||||
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
|
||||
ret = bch2_btree_delete_at(trans, bp_iter, 0);
|
||||
struct bpos bucket;
|
||||
if (!bp_pos_to_bucket_nodev_noerror(c, k.k->p, &bucket)) {
|
||||
if (fsck_err(c, backpointer_to_missing_device,
|
||||
"backpointer for missing device:\n%s",
|
||||
(bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
|
||||
ret = bch2_btree_delete_at(trans, bp_iter, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
alloc_k = bch2_bkey_get_iter(trans, &alloc_iter, BTREE_ID_alloc,
|
||||
bp_pos_to_bucket(c, k.k->p), 0);
|
||||
alloc_k = bch2_bkey_get_iter(trans, &alloc_iter, BTREE_ID_alloc, bucket, 0);
|
||||
ret = bkey_err(alloc_k);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -512,25 +537,27 @@ static int check_bp_exists(struct btree_trans *trans,
|
|||
struct printbuf buf = PRINTBUF;
|
||||
struct bkey_s_c bp_k;
|
||||
struct bkey_buf tmp;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
bch2_bkey_buf_init(&tmp);
|
||||
|
||||
if (!bch2_dev_bucket_exists(c, bucket)) {
|
||||
struct bch_dev *ca = bch2_dev_bucket_tryget(c, bucket);
|
||||
if (!ca) {
|
||||
prt_str(&buf, "extent for nonexistent device:bucket ");
|
||||
bch2_bpos_to_text(&buf, bucket);
|
||||
prt_str(&buf, "\n ");
|
||||
bch2_bkey_val_to_text(&buf, c, orig_k);
|
||||
bch_err(c, "%s", buf.buf);
|
||||
return -BCH_ERR_fsck_repair_unimplemented;
|
||||
ret = -BCH_ERR_fsck_repair_unimplemented;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (bpos_lt(bucket, s->bucket_start) ||
|
||||
bpos_gt(bucket, s->bucket_end))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
bp_k = bch2_bkey_get_iter(trans, &bp_iter, BTREE_ID_backpointers,
|
||||
bucket_pos_to_bp(c, bucket, bp.bucket_offset),
|
||||
bucket_pos_to_bp(ca, bucket, bp.bucket_offset),
|
||||
0);
|
||||
ret = bkey_err(bp_k);
|
||||
if (ret)
|
||||
|
@ -563,6 +590,7 @@ static int check_bp_exists(struct btree_trans *trans,
|
|||
bch2_trans_iter_exit(trans, &other_extent_iter);
|
||||
bch2_trans_iter_exit(trans, &bp_iter);
|
||||
bch2_bkey_buf_exit(&tmp, c);
|
||||
bch2_dev_put(ca);
|
||||
printbuf_exit(&buf);
|
||||
return ret;
|
||||
check_existing_bp:
|
||||
|
@ -638,13 +666,13 @@ static int check_bp_exists(struct btree_trans *trans,
|
|||
|
||||
struct bkey_i_backpointer n_bp_k;
|
||||
bkey_backpointer_init(&n_bp_k.k_i);
|
||||
n_bp_k.k.p = bucket_pos_to_bp(trans->c, bucket, bp.bucket_offset);
|
||||
n_bp_k.k.p = bucket_pos_to_bp(ca, bucket, bp.bucket_offset);
|
||||
n_bp_k.v = bp;
|
||||
prt_printf(&buf, "\n want: ");
|
||||
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&n_bp_k.k_i));
|
||||
|
||||
if (fsck_err(c, ptr_to_missing_backpointer, "%s", buf.buf))
|
||||
ret = bch2_bucket_backpointer_mod(trans, bucket, bp, orig_k, true);
|
||||
ret = bch2_bucket_backpointer_mod(trans, ca, bucket, bp, orig_k, true);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
@ -668,8 +696,14 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
|
|||
if (p.ptr.cached)
|
||||
continue;
|
||||
|
||||
struct bch_dev *ca = bch2_dev_bkey_exists(c, p.ptr.dev);
|
||||
bch2_extent_ptr_to_bp(c, ca, btree, level, k, p, entry, &bucket_pos, &bp);
|
||||
rcu_read_lock();
|
||||
struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
|
||||
if (ca)
|
||||
bch2_extent_ptr_to_bp(c, ca, btree, level, k, p, entry, &bucket_pos, &bp);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!ca)
|
||||
continue;
|
||||
|
||||
ret = check_bp_exists(trans, s, bucket_pos, bp, k);
|
||||
if (ret)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "btree_iter.h"
|
||||
#include "btree_update.h"
|
||||
#include "buckets.h"
|
||||
#include "error.h"
|
||||
#include "super.h"
|
||||
|
||||
static inline u64 swab40(u64 x)
|
||||
|
@ -36,15 +37,29 @@ void bch2_backpointer_swab(struct bkey_s);
|
|||
* Convert from pos in backpointer btree to pos of corresponding bucket in alloc
|
||||
* btree:
|
||||
*/
|
||||
static inline struct bpos bp_pos_to_bucket(const struct bch_fs *c,
|
||||
struct bpos bp_pos)
|
||||
static inline struct bpos bp_pos_to_bucket(const struct bch_dev *ca, struct bpos bp_pos)
|
||||
{
|
||||
struct bch_dev *ca = bch2_dev_bkey_exists(c, bp_pos.inode);
|
||||
u64 bucket_sector = bp_pos.offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT;
|
||||
|
||||
return POS(bp_pos.inode, sector_to_bucket(ca, bucket_sector));
|
||||
}
|
||||
|
||||
static inline bool bp_pos_to_bucket_nodev_noerror(struct bch_fs *c, struct bpos bp_pos, struct bpos *bucket)
|
||||
{
|
||||
rcu_read_lock();
|
||||
struct bch_dev *ca = bch2_dev_rcu(c, bp_pos.inode);
|
||||
if (ca)
|
||||
*bucket = bp_pos_to_bucket(ca, bp_pos);
|
||||
rcu_read_unlock();
|
||||
return ca != NULL;
|
||||
}
|
||||
|
||||
static inline bool bp_pos_to_bucket_nodev(struct bch_fs *c, struct bpos bp_pos, struct bpos *bucket)
|
||||
{
|
||||
return !bch2_fs_inconsistent_on(!bp_pos_to_bucket_nodev_noerror(c, bp_pos, bucket),
|
||||
c, "backpointer for missing device %llu", bp_pos.inode);
|
||||
}
|
||||
|
||||
static inline struct bpos bucket_pos_to_bp_noerror(const struct bch_dev *ca,
|
||||
struct bpos bucket,
|
||||
u64 bucket_offset)
|
||||
|
@ -57,32 +72,32 @@ static inline struct bpos bucket_pos_to_bp_noerror(const struct bch_dev *ca,
|
|||
/*
|
||||
* Convert from pos in alloc btree + bucket offset to pos in backpointer btree:
|
||||
*/
|
||||
static inline struct bpos bucket_pos_to_bp(const struct bch_fs *c,
|
||||
static inline struct bpos bucket_pos_to_bp(const struct bch_dev *ca,
|
||||
struct bpos bucket,
|
||||
u64 bucket_offset)
|
||||
{
|
||||
struct bch_dev *ca = bch2_dev_bkey_exists(c, bucket.inode);
|
||||
struct bpos ret = bucket_pos_to_bp_noerror(ca, bucket, bucket_offset);
|
||||
EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(c, ret)));
|
||||
EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(ca, ret)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *, struct bpos bucket,
|
||||
struct bch_backpointer, struct bkey_s_c, bool);
|
||||
int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *, struct bch_dev *,
|
||||
struct bpos bucket, struct bch_backpointer, struct bkey_s_c, bool);
|
||||
|
||||
static inline int bch2_bucket_backpointer_mod(struct btree_trans *trans,
|
||||
struct bch_dev *ca,
|
||||
struct bpos bucket,
|
||||
struct bch_backpointer bp,
|
||||
struct bkey_s_c orig_k,
|
||||
bool insert)
|
||||
{
|
||||
if (unlikely(bch2_backpointers_no_use_write_buffer))
|
||||
return bch2_bucket_backpointer_mod_nowritebuffer(trans, bucket, bp, orig_k, insert);
|
||||
return bch2_bucket_backpointer_mod_nowritebuffer(trans, ca, bucket, bp, orig_k, insert);
|
||||
|
||||
struct bkey_i_backpointer bp_k;
|
||||
|
||||
bkey_backpointer_init(&bp_k.k_i);
|
||||
bp_k.k.p = bucket_pos_to_bp(trans->c, bucket, bp.bucket_offset);
|
||||
bp_k.k.p = bucket_pos_to_bp(ca, bucket, bp.bucket_offset);
|
||||
bp_k.v = bp;
|
||||
|
||||
if (!insert) {
|
||||
|
@ -142,7 +157,7 @@ static inline void bch2_extent_ptr_to_bp(struct bch_fs *c, struct bch_dev *ca,
|
|||
};
|
||||
}
|
||||
|
||||
int bch2_get_next_backpointer(struct btree_trans *, struct bpos, int,
|
||||
int bch2_get_next_backpointer(struct btree_trans *, struct bch_dev *ca, struct bpos, int,
|
||||
struct bpos *, struct bch_backpointer *, unsigned);
|
||||
struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *, struct btree_iter *,
|
||||
struct bpos, struct bch_backpointer,
|
||||
|
|
|
@ -988,7 +988,7 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
|
|||
goto err;
|
||||
|
||||
if (!p.ptr.cached) {
|
||||
ret = bch2_bucket_backpointer_mod(trans, bucket, bp, k, insert);
|
||||
ret = bch2_bucket_backpointer_mod(trans, ca, bucket, bp, k, insert);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
|
|
@ -1198,6 +1198,7 @@ static int ec_stripe_key_update(struct btree_trans *trans,
|
|||
}
|
||||
|
||||
static int ec_stripe_update_extent(struct btree_trans *trans,
|
||||
struct bch_dev *ca,
|
||||
struct bpos bucket, u8 gen,
|
||||
struct ec_stripe_buf *s,
|
||||
struct bpos *bp_pos)
|
||||
|
@ -1213,7 +1214,7 @@ static int ec_stripe_update_extent(struct btree_trans *trans,
|
|||
struct bkey_i *n;
|
||||
int ret, dev, block;
|
||||
|
||||
ret = bch2_get_next_backpointer(trans, bucket, gen,
|
||||
ret = bch2_get_next_backpointer(trans, ca, bucket, gen,
|
||||
bp_pos, &bp, BTREE_ITER_cached);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -1311,7 +1312,7 @@ static int ec_stripe_update_bucket(struct btree_trans *trans, struct ec_stripe_b
|
|||
ret = commit_do(trans, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_check_rw|
|
||||
BCH_TRANS_COMMIT_no_enospc,
|
||||
ec_stripe_update_extent(trans, bucket_pos, ptr.gen, s, &bp_pos));
|
||||
ec_stripe_update_extent(trans, ca, bucket_pos, ptr.gen, s, &bp_pos));
|
||||
if (ret)
|
||||
break;
|
||||
if (bkey_eq(bp_pos, POS_MAX))
|
||||
|
|
|
@ -729,7 +729,7 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
|
|||
|
||||
bch2_trans_begin(trans);
|
||||
|
||||
ret = bch2_get_next_backpointer(trans, bucket, gen,
|
||||
ret = bch2_get_next_backpointer(trans, ca, bucket, gen,
|
||||
&bp_pos, &bp,
|
||||
BTREE_ITER_cached);
|
||||
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
|
||||
|
|
Loading…
Reference in a new issue