-
- sib = whiteout;
- sib.snapshot = bch2_snapshot_sibling(c, sib.snapshot);
- }
-
- if (ret)
- goto err;
-
- if (!deleting && bpos_eq(whiteout, orig_whiteout))
- goto out;
-
- if (!bpos_eq(iter.pos, whiteout)) {
- bch2_trans_iter_exit(trans, &iter);
- bch2_trans_iter_init(trans, &iter, btree, whiteout, BTREE_ITER_INTENT);
- k = bch2_btree_iter_peek_slot(&iter);
- ret = bkey_err(k);
- if (ret)
- goto err;
- }
-
- iter.flags &= ~BTREE_ITER_ALL_SNAPSHOTS;
- iter.flags |= BTREE_ITER_FILTER_SNAPSHOTS;
-
- struct bkey_i *delete = bch2_trans_kmalloc(trans, sizeof(*delete));
- ret = PTR_ERR_OR_ZERO(delete);
- if (ret)
- goto err;
-
- bkey_init(&delete->k);
- delete->k.p = whiteout;
-
- ret = !bpos_eq(whiteout, overwrite)
- ? !old_is_whiteout
- : need_whiteout_for_snapshot(trans, btree, whiteout);
- if (ret < 0)
- goto err;
- if (ret)
- delete->k.type = KEY_TYPE_whiteout;
-
- ret = bch2_trans_update(trans, &iter, delete,
- BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE|
- BTREE_UPDATE_SNAPSHOT_WHITEOUT_CHECKS_DONE);
-out:
-err:
- bch2_trans_iter_exit(trans, &iter);
- return ret;
-}
-
-/*
- * We're overwriting a key in a snapshot that has ancestors: if we're
- * overwriting a key in a different snapshot, we need to check if it is now
- * fully overritten and can be deleted, and if we're deleting a key in the
- * current snapshot we need to check if we need to leave a whiteout.
- */
-static noinline int
-overwrite_interior_snapshot_key(struct btree_trans *trans,
- struct btree_iter *iter,
- struct bkey_i *k)
-{
- struct bkey_s_c old = bch2_btree_iter_peek_slot(iter);
-
- int ret = bkey_err(old);
- if (ret)
- return ret;
-
- if (!bkey_deleted(old.k)) {
- if (btree_type_snapshots_unreffed(iter->btree_id) &&
- old.k->p.snapshot != k->k.p.snapshot) {
- /*
- * We're overwriting a key in a different snapshot:
- * check if it's also been overwritten in siblings
- */
- ret = delete_interior_snapshot_key(trans, iter->btree_id,
- k->k.p, bkey_deleted(&k->k),
- old.k->p, bkey_whiteout(old.k));
- if (ret)
- return ret;
- if (bkey_deleted(&k->k))
- return 1;
- } else if (bkey_deleted(&k->k)) {
- /*
- * We're deleting a key in the current snapshot:
- * check if we need to leave a whiteout
- */
- ret = need_whiteout_for_snapshot(trans, iter->btree_id, k->k.p);
- if (unlikely(ret < 0))
- return ret;
- if (ret)
- k->k.type = KEY_TYPE_whiteout;