diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2022-04-25 01:08:34 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2022-04-29 17:40:06 -0400 |
commit | a760a3f7505b6c40165a23883db2d08d52bcfd80 (patch) | |
tree | 3ef5e05bc3d7495c1d63b4b25972f52cf42acbd6 | |
parent | 559f2632b9fa7c1fa531bfeb8146501daaad35ce (diff) |
check overlapping extents wipexent_overlap_repair
-rw-r--r-- | fs/bcachefs/fsck.c | 83 |
1 files changed, 65 insertions, 18 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index f1abec95a740..70c44e6793eb 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -1150,9 +1150,61 @@ fsck_err: return ret ?: ret2; } +struct extent_end { + u32 snapshot; + u64 offset; +}; + +typedef DARRAY(struct extent_end) extent_ends; + +static int extent_ends_at(extent_ends *extent_ends, + struct bkey_s_c k) +{ + struct extent_end *i, n = (struct extent_end) { + .snapshot = k.k->p.snapshot, + .offset = k.k->p.offset, + }; + + darray_for_each(*extent_ends, i) + if (i->snapshot >= k.k->p.snapshot) + break; + + if (i->snapshot == k.k->p.snapshot) { + *i = n; + return 0; + } else { + return darray_insert_item(extent_ends, i - extent_ends->data, n); + } +} + +static int check_extent_start(struct btree_trans *trans, + struct snapshots_seen *s, + extent_ends *extent_ends, + struct bkey_s_c k) +{ + struct bch_fs *c = trans->c; + struct extent_end *i; + struct printbuf buf = PRINTBUF; + int ret = 0; + + darray_for_each(*extent_ends, i) { + if (fsck_err_on(i->offset > bkey_start_offset(k.k) && + key_visible_in_snapshot(c, s, ), c, + "overlapping extents: extent in snapshot %u ends at %llu overlaps with\n%s", + (printbuf_reset(&buf), + bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { + BUG(); + } + } +fsck_err: + printbuf_exit(&buf); + return ret; +} + static int check_extent(struct btree_trans *trans, struct btree_iter *iter, struct inode_walker *inode, - struct snapshots_seen *s) + struct snapshots_seen *s, + extent_ends *extent_ends) { struct bch_fs *c = trans->c; struct bkey_s_c k; @@ -1182,6 +1234,8 @@ peek: goto out; if (inode->cur_inum != k.k->p.inode) { + extent_ends->nr = 0; + ret = check_i_sectors(trans, inode); if (ret) goto err; @@ -1195,20 +1249,7 @@ peek: */ goto peek; } -#if 0 - if (bkey_cmp(prev.k->k.p, bkey_start_pos(k.k)) > 0) { - char buf1[200]; - char buf2[200]; - bch2_bkey_val_to_text(&PBUF(buf1), c, bkey_i_to_s_c(prev.k)); - bch2_bkey_val_to_text(&PBUF(buf2), c, k); - - if (fsck_err(c, "overlapping extents:\n%s\n%s", buf1, buf2)) { - ret = fix_overlapping_extent(trans, k, prev.k->k.p) ?: -EINTR; - goto out; - } - } -#endif ret = __walk_inode(trans, inode, k.k->p); if (ret < 0) goto err; @@ -1259,13 +1300,17 @@ peek: } } + ret = check_extent_start(trans, s, extent_ends, k); + if (ret) + goto err; + if (bkey_extent_is_allocation(k.k)) for_each_visible_inode(c, s, inode, k.k->p.snapshot, i) i->count += k.k->size; -#if 0 - bch2_bkey_buf_reassemble(&prev, c, k); -#endif + ret = extent_ends_at(extent_ends, k); + if (ret) + goto err; out: err: fsck_err: @@ -1287,6 +1332,7 @@ static int check_extents(struct bch_fs *c) struct snapshots_seen s; struct btree_trans trans; struct btree_iter iter; + extent_ends extent_ends = { 0 }; int ret = 0; #if 0 @@ -1309,7 +1355,7 @@ static int check_extents(struct bch_fs *c) ret = __bch2_trans_do(&trans, NULL, NULL, BTREE_INSERT_LAZY_RW| BTREE_INSERT_NOFAIL, - check_extent(&trans, &iter, &w, &s)); + check_extent(&trans, &iter, &w, &s, &extent_ends)); if (ret) break; } while (bch2_btree_iter_advance(&iter)); @@ -1317,6 +1363,7 @@ static int check_extents(struct bch_fs *c) #if 0 bch2_bkey_buf_exit(&prev, c); #endif + darray_exit(&extent_ends); inode_walker_exit(&w); bch2_trans_exit(&trans); snapshots_seen_exit(&s); |