X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Fsubvolume.c;h=24244bc3d2fbff6703dcf5b4e27d513ebb7082dc;hb=ddac1641ee1e2686c2211a8d671ea723634dfc89;hp=1a212bac2a04624709fde0d92aaa53a47af6b117;hpb=a6128b5335a79cd68b9dbb6b083a835d94539d04;p=bcachefs-tools-debian diff --git a/libbcachefs/subvolume.c b/libbcachefs/subvolume.c index 1a212ba..24244bc 100644 --- a/libbcachefs/subvolume.c +++ b/libbcachefs/subvolume.c @@ -3,6 +3,7 @@ #include "bcachefs.h" #include "btree_key_cache.h" #include "btree_update.h" +#include "errcode.h" #include "error.h" #include "fs.h" #include "subvolume.h" @@ -291,22 +292,14 @@ int bch2_fs_check_snapshots(struct bch_fs *c) } static int check_subvol(struct btree_trans *trans, - struct btree_iter *iter) + struct btree_iter *iter, + struct bkey_s_c k) { - struct bkey_s_c k; struct bkey_s_c_subvolume subvol; struct bch_snapshot snapshot; unsigned snapid; int ret; - k = bch2_btree_iter_peek(iter); - if (!k.k) - return 0; - - ret = bkey_err(k); - if (ret) - return ret; - if (k.k->type != KEY_TYPE_subvolume) return 0; @@ -322,9 +315,9 @@ static int check_subvol(struct btree_trans *trans, if (BCH_SUBVOLUME_UNLINKED(subvol.v)) { ret = bch2_subvolume_delete(trans, iter->pos.offset); - if (ret && ret != -EINTR) - bch_err(trans->c, "error deleting subvolume %llu: %i", - iter->pos.offset, ret); + if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart)) + bch_err(trans->c, "error deleting subvolume %llu: %s", + iter->pos.offset, bch2_err_str(ret)); if (ret) return ret; } @@ -336,22 +329,15 @@ int bch2_fs_check_subvols(struct bch_fs *c) { struct btree_trans trans; struct btree_iter iter; + struct bkey_s_c k; int ret; bch2_trans_init(&trans, c, 0, 0); - bch2_trans_iter_init(&trans, &iter, BTREE_ID_subvolumes, - POS_MIN, BTREE_ITER_PREFETCH); - - do { - ret = commit_do(&trans, NULL, NULL, - BTREE_INSERT_LAZY_RW| - BTREE_INSERT_NOFAIL, - check_subvol(&trans, &iter)); - if (ret) - break; - } while (bch2_btree_iter_advance(&iter)); - bch2_trans_iter_exit(&trans, &iter); + ret = for_each_btree_key_commit(&trans, iter, + BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_PREFETCH, k, + NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, + check_subvol(&trans, &iter, k)); bch2_trans_exit(&trans); @@ -380,7 +366,7 @@ int bch2_fs_snapshots_start(struct bch_fs *c) bch2_trans_exit(&trans); if (ret) - bch_err(c, "error starting snapshots: %i", ret); + bch_err(c, "error starting snapshots: %s", bch2_err_str(ret)); return ret; } @@ -595,59 +581,27 @@ err: return ret; } -static int bch2_snapshot_delete_keys_btree(struct btree_trans *trans, - snapshot_id_list *deleted, - enum btree_id btree_id) +static int snapshot_delete_key(struct btree_trans *trans, + struct btree_iter *iter, + struct bkey_s_c k, + snapshot_id_list *deleted, + snapshot_id_list *equiv_seen, + struct bpos *last_pos) { struct bch_fs *c = trans->c; - struct btree_iter iter; - struct bkey_s_c k; - snapshot_id_list equiv_seen = { 0 }; - struct bpos last_pos = POS_MIN; - int ret = 0; - - /* - * XXX: We should also delete whiteouts that no longer overwrite - * anything - */ + u32 equiv = snapshot_t(c, k.k->p.snapshot)->equiv; - bch2_trans_iter_init(trans, &iter, btree_id, POS_MIN, - BTREE_ITER_INTENT| - BTREE_ITER_PREFETCH| - BTREE_ITER_NOT_EXTENTS| - BTREE_ITER_ALL_SNAPSHOTS); - - while ((bch2_trans_begin(trans), - (k = bch2_btree_iter_peek(&iter)).k) && - !(ret = bkey_err(k))) { - u32 equiv = snapshot_t(c, k.k->p.snapshot)->equiv; - - if (bkey_cmp(k.k->p, last_pos)) - equiv_seen.nr = 0; - last_pos = k.k->p; - - if (snapshot_list_has_id(deleted, k.k->p.snapshot) || - snapshot_list_has_id(&equiv_seen, equiv)) { - ret = commit_do(trans, NULL, NULL, - BTREE_INSERT_NOFAIL, - bch2_btree_iter_traverse(&iter) ?: - bch2_btree_delete_at(trans, &iter, - BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE)); - if (ret) - break; - } else { - ret = snapshot_list_add(c, &equiv_seen, equiv); - if (ret) - break; - } + if (bkey_cmp(k.k->p, *last_pos)) + equiv_seen->nr = 0; + *last_pos = k.k->p; - bch2_btree_iter_advance(&iter); + if (snapshot_list_has_id(deleted, k.k->p.snapshot) || + snapshot_list_has_id(equiv_seen, equiv)) { + return bch2_btree_delete_at(trans, iter, + BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE); + } else { + return snapshot_list_add(c, equiv_seen, equiv); } - bch2_trans_iter_exit(trans, &iter); - - darray_exit(&equiv_seen); - - return ret; } static int bch2_delete_redundant_snapshot(struct btree_trans *trans, struct btree_iter *iter, @@ -694,7 +648,7 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) if (!test_bit(BCH_FS_STARTED, &c->flags)) { ret = bch2_fs_read_write_early(c); if (ret) { - bch_err(c, "error deleleting dead snapshots: error going rw: %i", ret); + bch_err(c, "error deleleting dead snapshots: error going rw: %s", bch2_err_str(ret)); return ret; } } @@ -710,7 +664,7 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) NULL, NULL, 0, bch2_delete_redundant_snapshot(&trans, &iter, k)); if (ret) { - bch_err(c, "error deleting redundant snapshots: %i", ret); + bch_err(c, "error deleting redundant snapshots: %s", bch2_err_str(ret)); goto err; } @@ -718,7 +672,7 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) POS_MIN, 0, k, bch2_snapshot_set_equiv(&trans, k)); if (ret) { - bch_err(c, "error in bch2_snapshots_set_equiv: %i", ret); + bch_err(c, "error in bch2_snapshots_set_equiv: %s", bch2_err_str(ret)); goto err; } @@ -737,17 +691,27 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) bch2_trans_iter_exit(&trans, &iter); if (ret) { - bch_err(c, "error walking snapshots: %i", ret); + bch_err(c, "error walking snapshots: %s", bch2_err_str(ret)); goto err; } for (id = 0; id < BTREE_ID_NR; id++) { + struct bpos last_pos = POS_MIN; + snapshot_id_list equiv_seen = { 0 }; + if (!btree_type_has_snapshots(id)) continue; - ret = bch2_snapshot_delete_keys_btree(&trans, &deleted, id); + ret = for_each_btree_key_commit(&trans, iter, + id, POS_MIN, + BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, + NULL, NULL, BTREE_INSERT_NOFAIL, + snapshot_delete_key(&trans, &iter, k, &deleted, &equiv_seen, &last_pos)); + + darray_exit(&equiv_seen); + if (ret) { - bch_err(c, "error deleting snapshot keys: %i", ret); + bch_err(c, "error deleting snapshot keys: %s", bch2_err_str(ret)); goto err; } } @@ -756,8 +720,8 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) ret = commit_do(&trans, NULL, NULL, 0, bch2_snapshot_node_delete(&trans, deleted.data[i])); if (ret) { - bch_err(c, "error deleting snapshot %u: %i", - deleted.data[i], ret); + bch_err(c, "error deleting snapshot %u: %s", + deleted.data[i], bch2_err_str(ret)); goto err; } } @@ -913,6 +877,8 @@ int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid) goto err; ret = bch2_snapshot_node_set_deleted(trans, snapid); + if (ret) + goto err; h = bch2_trans_kmalloc(trans, sizeof(*h)); ret = PTR_ERR_OR_ZERO(h); @@ -949,7 +915,7 @@ void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work) ret = bch2_trans_do(c, NULL, NULL, BTREE_INSERT_NOFAIL, bch2_subvolume_delete(&trans, *id)); if (ret) { - bch_err(c, "error %i deleting subvolume %u", ret, *id); + bch_err(c, "error deleting subvolume %u: %s", *id, bch2_err_str(ret)); break; } }