Commit 2ffe3ad6 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Snapshot whiteout fix

When fully overwriting an existing extent, we may need to generate a
whiteout - not just if the extent being overwritten was in an older
snapshot, but also if it was overwriting an extent in an older snapshot.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent c58029ec
...@@ -1307,6 +1307,39 @@ static noinline int extent_back_merge(struct btree_trans *trans, ...@@ -1307,6 +1307,39 @@ static noinline int extent_back_merge(struct btree_trans *trans,
return 0; return 0;
} }
/*
* When deleting, check if we need to emit a whiteout (because we're overwriting
* something in an ancestor snapshot)
*/
static int need_whiteout_for_snapshot(struct btree_trans *trans,
enum btree_id btree_id, struct bpos pos)
{
struct btree_iter iter;
struct bkey_s_c k;
u32 snapshot = pos.snapshot;
int ret;
if (!bch2_snapshot_parent(trans->c, pos.snapshot))
return 0;
pos.snapshot++;
for_each_btree_key_norestart(trans, iter, btree_id, pos,
BTREE_ITER_ALL_SNAPSHOTS|
BTREE_ITER_NOPRESERVE, k, ret) {
if (!bkey_eq(k.k->p, pos))
break;
if (bch2_snapshot_is_ancestor(trans->c, snapshot,
k.k->p.snapshot)) {
ret = !bkey_whiteout(k.k);
break;
}
}
bch2_trans_iter_exit(trans, &iter);
return ret;
}
int bch2_trans_update_extent(struct btree_trans *trans, int bch2_trans_update_extent(struct btree_trans *trans,
struct btree_iter *orig_iter, struct btree_iter *orig_iter,
struct bkey_i *insert, struct bkey_i *insert,
...@@ -1388,12 +1421,12 @@ int bch2_trans_update_extent(struct btree_trans *trans, ...@@ -1388,12 +1421,12 @@ int bch2_trans_update_extent(struct btree_trans *trans,
bkey_init(&update->k); bkey_init(&update->k);
update->k.p = k.k->p; update->k.p = k.k->p;
update->k.p.snapshot = insert->k.p.snapshot;
if (insert->k.p.snapshot != k.k->p.snapshot) { if (insert->k.p.snapshot != k.k->p.snapshot ||
update->k.p.snapshot = insert->k.p.snapshot; (btree_type_has_snapshots(btree_id) &&
need_whiteout_for_snapshot(trans, btree_id, update->k.p)))
update->k.type = KEY_TYPE_whiteout; update->k.type = KEY_TYPE_whiteout;
}
ret = bch2_btree_insert_nonextent(trans, btree_id, update, ret = bch2_btree_insert_nonextent(trans, btree_id, update,
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE|flags); BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE|flags);
...@@ -1448,40 +1481,6 @@ int bch2_trans_update_extent(struct btree_trans *trans, ...@@ -1448,40 +1481,6 @@ int bch2_trans_update_extent(struct btree_trans *trans,
return ret; return ret;
} }
/*
* When deleting, check if we need to emit a whiteout (because we're overwriting
* something in an ancestor snapshot)
*/
static int need_whiteout_for_snapshot(struct btree_trans *trans,
enum btree_id btree_id, struct bpos pos)
{
struct btree_iter iter;
struct bkey_s_c k;
u32 snapshot = pos.snapshot;
int ret;
if (!bch2_snapshot_parent(trans->c, pos.snapshot))
return 0;
pos.snapshot++;
for_each_btree_key_norestart(trans, iter, btree_id, pos,
BTREE_ITER_ALL_SNAPSHOTS|
BTREE_ITER_NOPRESERVE, k, ret) {
if (!bkey_eq(k.k->p, pos))
break;
if (bch2_snapshot_is_ancestor(trans->c, snapshot,
k.k->p.snapshot)) {
ret = !bkey_whiteout(k.k);
break;
}
}
bch2_trans_iter_exit(trans, &iter);
return ret;
}
static int __must_check static int __must_check
bch2_trans_update_by_path_trace(struct btree_trans *trans, struct btree_path *path, bch2_trans_update_by_path_trace(struct btree_trans *trans, struct btree_path *path,
struct bkey_i *k, enum btree_update_flags flags, struct bkey_i *k, enum btree_update_flags flags,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment