mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
bcachefs: Check for too-large encoded extents
We don't yet repair (split) them, just check. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
2d39081291
commit
9db2f86060
@ -1207,6 +1207,14 @@ int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||
return -BCH_ERR_invalid_bkey;
|
||||
}
|
||||
crc_since_last_ptr = true;
|
||||
|
||||
if (crc_is_encoded(crc) &&
|
||||
(crc.uncompressed_size > c->opts.encoded_extent_max >> 9) &&
|
||||
(flags & (BKEY_INVALID_WRITE|BKEY_INVALID_COMMIT))) {
|
||||
prt_printf(err, "too large encoded extent");
|
||||
return -BCH_ERR_invalid_bkey;
|
||||
}
|
||||
|
||||
break;
|
||||
case BCH_EXTENT_ENTRY_stripe_ptr:
|
||||
if (have_ec) {
|
||||
|
@ -190,6 +190,11 @@ static inline bool crc_is_compressed(struct bch_extent_crc_unpacked crc)
|
||||
crc.compression_type != BCH_COMPRESSION_TYPE_incompressible);
|
||||
}
|
||||
|
||||
static inline bool crc_is_encoded(struct bch_extent_crc_unpacked crc)
|
||||
{
|
||||
return crc.csum_type != BCH_CSUM_none || crc_is_compressed(crc);
|
||||
}
|
||||
|
||||
/* bkey_ptrs: generically over any key type that has ptrs */
|
||||
|
||||
struct bkey_ptrs_c {
|
||||
|
@ -1299,6 +1299,28 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_extent_overbig(struct btree_trans *trans, struct btree_iter *iter,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
|
||||
struct bch_extent_crc_unpacked crc;
|
||||
const union bch_extent_entry *i;
|
||||
unsigned encoded_extent_max_sectors = c->opts.encoded_extent_max >> 9;
|
||||
|
||||
bkey_for_each_crc(k.k, ptrs, crc, i)
|
||||
if (crc_is_encoded(crc) &&
|
||||
crc.uncompressed_size > encoded_extent_max_sectors) {
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
bch2_bkey_val_to_text(&buf, c, k);
|
||||
bch_err(c, "overbig encoded extent, please report this:\n %s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
|
||||
struct bkey_s_c k,
|
||||
struct inode_walker *inode,
|
||||
@ -1434,7 +1456,8 @@ int bch2_check_extents(struct bch_fs *c)
|
||||
&res, NULL,
|
||||
BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, ({
|
||||
bch2_disk_reservation_put(c, &res);
|
||||
check_extent(trans, &iter, k, &w, &s, &extent_ends);
|
||||
check_extent(trans, &iter, k, &w, &s, &extent_ends) ?:
|
||||
check_extent_overbig(trans, &iter, k);
|
||||
})) ?:
|
||||
check_i_sectors(trans, &w);
|
||||
|
||||
@ -1448,6 +1471,30 @@ int bch2_check_extents(struct bch_fs *c)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_check_indirect_extents(struct bch_fs *c)
|
||||
{
|
||||
struct btree_trans *trans = bch2_trans_get(c);
|
||||
struct btree_iter iter;
|
||||
struct bkey_s_c k;
|
||||
struct disk_reservation res = { 0 };
|
||||
int ret = 0;
|
||||
|
||||
ret = for_each_btree_key_commit(trans, iter, BTREE_ID_reflink,
|
||||
POS_MIN,
|
||||
BTREE_ITER_PREFETCH, k,
|
||||
&res, NULL,
|
||||
BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, ({
|
||||
bch2_disk_reservation_put(c, &res);
|
||||
check_extent_overbig(trans, &iter, k);
|
||||
}));
|
||||
|
||||
bch2_disk_reservation_put(c, &res);
|
||||
bch2_trans_put(trans);
|
||||
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
int bch2_check_inodes(struct bch_fs *);
|
||||
int bch2_check_extents(struct bch_fs *);
|
||||
int bch2_check_indirect_extents(struct bch_fs *);
|
||||
int bch2_check_dirents(struct bch_fs *);
|
||||
int bch2_check_xattrs(struct bch_fs *);
|
||||
int bch2_check_root(struct bch_fs *);
|
||||
|
@ -1092,9 +1092,7 @@ static bool bch2_extent_is_writeable(struct bch_write_op *op,
|
||||
|
||||
e = bkey_s_c_to_extent(k);
|
||||
extent_for_each_ptr_decode(e, p, entry) {
|
||||
if (p.crc.csum_type ||
|
||||
crc_is_compressed(p.crc) ||
|
||||
p.has_ec)
|
||||
if (crc_is_encoded(p.crc) || p.has_ec)
|
||||
return false;
|
||||
|
||||
replicas += bch2_extent_ptr_durability(c, &p);
|
||||
|
@ -34,6 +34,7 @@
|
||||
x(resume_logged_ops, PASS_ALWAYS) \
|
||||
x(check_inodes, PASS_FSCK) \
|
||||
x(check_extents, PASS_FSCK) \
|
||||
x(check_indirect_extents, PASS_FSCK) \
|
||||
x(check_dirents, PASS_FSCK) \
|
||||
x(check_xattrs, PASS_FSCK) \
|
||||
x(check_root, PASS_FSCK) \
|
||||
|
Loading…
Reference in New Issue
Block a user