Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+64 -4
+8
fs/bcachefs/extents.c
··· 1207 1207 return -BCH_ERR_invalid_bkey; 1208 1208 } 1209 1209 crc_since_last_ptr = true; 1210 + 1211 + if (crc_is_encoded(crc) && 1212 + (crc.uncompressed_size > c->opts.encoded_extent_max >> 9) && 1213 + (flags & (BKEY_INVALID_WRITE|BKEY_INVALID_COMMIT))) { 1214 + prt_printf(err, "too large encoded extent"); 1215 + return -BCH_ERR_invalid_bkey; 1216 + } 1217 + 1210 1218 break; 1211 1219 case BCH_EXTENT_ENTRY_stripe_ptr: 1212 1220 if (have_ec) {
+5
fs/bcachefs/extents.h
··· 190 190 crc.compression_type != BCH_COMPRESSION_TYPE_incompressible); 191 191 } 192 192 193 + static inline bool crc_is_encoded(struct bch_extent_crc_unpacked crc) 194 + { 195 + return crc.csum_type != BCH_CSUM_none || crc_is_compressed(crc); 196 + } 197 + 193 198 /* bkey_ptrs: generically over any key type that has ptrs */ 194 199 195 200 struct bkey_ptrs_c {
+48 -1
fs/bcachefs/fsck.c
··· 1299 1299 return ret; 1300 1300 } 1301 1301 1302 + static int check_extent_overbig(struct btree_trans *trans, struct btree_iter *iter, 1303 + struct bkey_s_c k) 1304 + { 1305 + struct bch_fs *c = trans->c; 1306 + struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); 1307 + struct bch_extent_crc_unpacked crc; 1308 + const union bch_extent_entry *i; 1309 + unsigned encoded_extent_max_sectors = c->opts.encoded_extent_max >> 9; 1310 + 1311 + bkey_for_each_crc(k.k, ptrs, crc, i) 1312 + if (crc_is_encoded(crc) && 1313 + crc.uncompressed_size > encoded_extent_max_sectors) { 1314 + struct printbuf buf = PRINTBUF; 1315 + 1316 + bch2_bkey_val_to_text(&buf, c, k); 1317 + bch_err(c, "overbig encoded extent, please report this:\n %s", buf.buf); 1318 + printbuf_exit(&buf); 1319 + } 1320 + 1321 + return 0; 1322 + } 1323 + 1302 1324 static int check_extent(struct btree_trans *trans, struct btree_iter *iter, 1303 1325 struct bkey_s_c k, 1304 1326 struct inode_walker *inode, ··· 1456 1434 &res, NULL, 1457 1435 BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, ({ 1458 1436 bch2_disk_reservation_put(c, &res); 1459 - check_extent(trans, &iter, k, &w, &s, &extent_ends); 1437 + check_extent(trans, &iter, k, &w, &s, &extent_ends) ?: 1438 + check_extent_overbig(trans, &iter, k); 1460 1439 })) ?: 1461 1440 check_i_sectors(trans, &w); 1462 1441 ··· 1465 1442 extent_ends_exit(&extent_ends); 1466 1443 inode_walker_exit(&w); 1467 1444 snapshots_seen_exit(&s); 1445 + bch2_trans_put(trans); 1446 + 1447 + bch_err_fn(c, ret); 1448 + return ret; 1449 + } 1450 + 1451 + int bch2_check_indirect_extents(struct bch_fs *c) 1452 + { 1453 + struct btree_trans *trans = bch2_trans_get(c); 1454 + struct btree_iter iter; 1455 + struct bkey_s_c k; 1456 + struct disk_reservation res = { 0 }; 1457 + int ret = 0; 1458 + 1459 + ret = for_each_btree_key_commit(trans, iter, BTREE_ID_reflink, 1460 + POS_MIN, 1461 + BTREE_ITER_PREFETCH, k, 1462 + &res, NULL, 1463 + BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, ({ 1464 + bch2_disk_reservation_put(c, &res); 1465 + check_extent_overbig(trans, &iter, k); 1466 + })); 1467 + 1468 + bch2_disk_reservation_put(c, &res); 1468 1469 bch2_trans_put(trans); 1469 1470 1470 1471 bch_err_fn(c, ret);
+1
fs/bcachefs/fsck.h
··· 4 4 5 5 int bch2_check_inodes(struct bch_fs *); 6 6 int bch2_check_extents(struct bch_fs *); 7 + int bch2_check_indirect_extents(struct bch_fs *); 7 8 int bch2_check_dirents(struct bch_fs *); 8 9 int bch2_check_xattrs(struct bch_fs *); 9 10 int bch2_check_root(struct bch_fs *);
+1 -3
fs/bcachefs/io_write.c
··· 1092 1092 1093 1093 e = bkey_s_c_to_extent(k); 1094 1094 extent_for_each_ptr_decode(e, p, entry) { 1095 - if (p.crc.csum_type || 1096 - crc_is_compressed(p.crc) || 1097 - p.has_ec) 1095 + if (crc_is_encoded(p.crc) || p.has_ec) 1098 1096 return false; 1099 1097 1100 1098 replicas += bch2_extent_ptr_durability(c, &p);
+1
fs/bcachefs/recovery_types.h
··· 34 34 x(resume_logged_ops, PASS_ALWAYS) \ 35 35 x(check_inodes, PASS_FSCK) \ 36 36 x(check_extents, PASS_FSCK) \ 37 + x(check_indirect_extents, PASS_FSCK) \ 37 38 x(check_dirents, PASS_FSCK) \ 38 39 x(check_xattrs, PASS_FSCK) \ 39 40 x(check_root, PASS_FSCK) \