summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-04-25 01:08:34 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2022-04-29 17:40:06 -0400
commita760a3f7505b6c40165a23883db2d08d52bcfd80 (patch)
tree3ef5e05bc3d7495c1d63b4b25972f52cf42acbd6
parent559f2632b9fa7c1fa531bfeb8146501daaad35ce (diff)
check overlapping extents wipexent_overlap_repair
-rw-r--r--fs/bcachefs/fsck.c83
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);