]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/btree_update.c
Update bcachefs sources to 9a555a741e80 bcachefs: omit alignment attribute on big...
[bcachefs-tools-debian] / libbcachefs / btree_update.c
index d3d625d4977aaa7c8fdff4e1c0d8ac6ee72818db..cbb7cf21da5be15c267ddd07dbc0eb09f2fba479 100644 (file)
@@ -82,167 +82,38 @@ static noinline int extent_back_merge(struct btree_trans *trans,
        return 0;
 }
 
-static struct bkey_s_c peek_slot_including_whiteouts(struct btree_trans *trans, struct btree_iter *iter,
-                                                    enum btree_id btree, struct bpos pos)
-{
-       struct bkey_s_c k;
-       int ret;
-
-       for_each_btree_key_norestart(trans, *iter, btree, 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, pos.snapshot, k.k->p.snapshot))
-                       return k;
-       }
-       bch2_trans_iter_exit(trans, iter);
-
-       return ret ? bkey_s_c_err(ret) : bkey_s_c_null;
-}
-
 /*
  * 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, struct bpos pos)
-{
-       pos.snapshot = bch2_snapshot_parent(trans->c, pos.snapshot);
-       if (!pos.snapshot)
-               return 0;
-
-       struct btree_iter iter;
-       struct bkey_s_c k = peek_slot_including_whiteouts(trans, &iter, btree, pos);
-       int ret = bkey_err(k) ?: k.k && !bkey_whiteout(k.k);
-       bch2_trans_iter_exit(trans, &iter);
-
-       return ret;
-}
-
-/*
- * We're overwriting a key at @pos in snapshot @snapshot, so we need to insert a
- * whiteout: that might be in @snapshot, or if there are overwites in sibling
- * snapshots, find the common ancestor where @pos is overwritten in every
- * descendent and insert the whiteout there - which might be at @pos.
- */
-static int delete_interior_snapshot_key(struct btree_trans *trans,
-                                       enum btree_id btree,
-                                       struct bpos whiteout, bool deleting,
-                                       struct bpos overwrite, bool old_is_whiteout)
+static int need_whiteout_for_snapshot(struct btree_trans *trans,
+                                     enum btree_id btree_id, struct bpos pos)
 {
-       struct bch_fs *c = trans->c;
-       struct bpos orig_whiteout = whiteout, sib = whiteout;
        struct btree_iter iter;
        struct bkey_s_c k;
+       u32 snapshot = pos.snapshot;
        int ret;
 
-       sib.snapshot = bch2_snapshot_sibling(c, sib.snapshot);
+       if (!bch2_snapshot_parent(trans->c, pos.snapshot))
+               return 0;
 
-       for_each_btree_key_norestart(trans, iter, btree, sib,
-                                    BTREE_ITER_ALL_SNAPSHOTS|BTREE_ITER_INTENT, k, ret) {
-               BUG_ON(bpos_gt(k.k->p, overwrite));
+       pos.snapshot++;
 
-               if (bpos_lt(k.k->p, sib)) /* unrelated branch - skip */
-                       continue;
-               if (bpos_gt(k.k->p, sib)) /* did not find @sib */
+       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;
 
-               /* @overwrite is also written in @sib, now check parent */
-               whiteout.snapshot = bch2_snapshot_parent(c, whiteout.snapshot);
-               if (bpos_eq(whiteout, overwrite))
+               if (bch2_snapshot_is_ancestor(trans->c, snapshot,
+                                             k.k->p.snapshot)) {
+                       ret = !bkey_whiteout(k.k);
                        break;
-
-               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 (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;
                }
        }
+       bch2_trans_iter_exit(trans, &iter);
 
-       return 0;
+       return ret;
 }
 
 int __bch2_insert_snapshot_whiteouts(struct btree_trans *trans,
@@ -632,29 +503,32 @@ static noinline int bch2_trans_update_get_key_cache(struct btree_trans *trans,
 int __must_check bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter,
                                   struct bkey_i *k, enum btree_update_flags flags)
 {
+       btree_path_idx_t path_idx = iter->update_path ?: iter->path;
+       int ret;
+
        if (iter->flags & BTREE_ITER_IS_EXTENTS)
                return bch2_trans_update_extent(trans, iter, k, flags);
 
-       if (!(flags & (BTREE_UPDATE_SNAPSHOT_WHITEOUT_CHECKS_DONE|
-                      BTREE_UPDATE_KEY_CACHE_RECLAIM)) &&
-           (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) &&
-           bch2_snapshot_parent(trans->c, k->k.p.snapshot)) {
-               int ret = overwrite_interior_snapshot_key(trans, iter, k);
+       if (bkey_deleted(&k->k) &&
+           !(flags & BTREE_UPDATE_KEY_CACHE_RECLAIM) &&
+           (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS)) {
+               ret = need_whiteout_for_snapshot(trans, iter->btree_id, k->k.p);
+               if (unlikely(ret < 0))
+                       return ret;
+
                if (ret)
-                       return ret < 0 ? ret : 0;
+                       k->k.type = KEY_TYPE_whiteout;
        }
 
        /*
         * Ensure that updates to cached btrees go to the key cache:
         */
-       btree_path_idx_t path_idx = iter->update_path ?: iter->path;
        struct btree_path *path = trans->paths + path_idx;
-
        if (!(flags & BTREE_UPDATE_KEY_CACHE_RECLAIM) &&
            !path->cached &&
            !path->level &&
            btree_id_cached(trans->c, path->btree_id)) {
-               int ret = bch2_trans_update_get_key_cache(trans, iter, path);
+               ret = bch2_trans_update_get_key_cache(trans, iter, path);
                if (ret)
                        return ret;