]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/inode.c
Update bcachefs sources to 5d0a6c2b32f1 bcachefs: check_directory_structure() can...
[bcachefs-tools-debian] / libbcachefs / inode.c
index b861ab2e27bd9b322543fd978fdd29e19297b231..c39844b8e596b41bd1a106718b3e756db0359bda 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_update.h"
 #include "buckets.h"
 #include "compress.h"
+#include "dirent.h"
 #include "error.h"
 #include "extents.h"
 #include "extent_update.h"
@@ -1093,11 +1094,15 @@ static int may_delete_deleted_inode(struct btree_trans *trans,
        if (ret)
                goto out;
 
-       if (fsck_err_on(S_ISDIR(inode.bi_mode), c,
-                       deleted_inode_is_dir,
-                       "directory %llu:%u in deleted_inodes btree",
-                       pos.offset, pos.snapshot))
-               goto delete;
+       if (S_ISDIR(inode.bi_mode)) {
+               ret = bch2_empty_dir_snapshot(trans, pos.offset, pos.snapshot);
+               if (fsck_err_on(ret == -ENOTEMPTY, c, deleted_inode_is_dir,
+                               "non empty directory %llu:%u in deleted_inodes btree",
+                               pos.offset, pos.snapshot))
+                       goto delete;
+               if (ret)
+                       goto out;
+       }
 
        if (fsck_err_on(!(inode.bi_flags & BCH_INODE_unlinked), c,
                        deleted_inode_not_unlinked,
@@ -1150,8 +1155,6 @@ delete:
 int bch2_delete_dead_inodes(struct bch_fs *c)
 {
        struct btree_trans *trans = bch2_trans_get(c);
-       struct btree_iter iter;
-       struct bkey_s_c k;
        bool need_another_pass;
        int ret;
 again:
@@ -1163,29 +1166,29 @@ again:
         * but we can't retry because the btree write buffer won't have been
         * flushed and we'd spin:
         */
-       for_each_btree_key(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
-                          BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
-               ret = commit_do(trans, NULL, NULL,
-                               BCH_TRANS_COMMIT_no_enospc|
-                               BCH_TRANS_COMMIT_lazy_rw,
-                       may_delete_deleted_inode(trans, &iter, k.k->p, &need_another_pass));
-               if (ret < 0)
-                       break;
-
-               if (ret) {
-                       if (!test_bit(BCH_FS_rw, &c->flags)) {
-                               bch2_trans_unlock(trans);
-                               bch2_fs_lazy_rw(c);
-                       }
-
+       ret = for_each_btree_key_commit(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
+                                       BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
+                                       NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
+               ret = may_delete_deleted_inode(trans, &iter, k.k->p, &need_another_pass);
+               if (ret > 0) {
                        bch_verbose(c, "deleting unlinked inode %llu:%u", k.k->p.offset, k.k->p.snapshot);
 
                        ret = bch2_inode_rm_snapshot(trans, k.k->p.offset, k.k->p.snapshot);
-                       if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
-                               break;
+                       /*
+                        * We don't want to loop here: a transaction restart
+                        * error here means we handled a transaction restart and
+                        * we're actually done, but if we loop we'll retry the
+                        * same key because the write buffer hasn't been flushed
+                        * yet
+                        */
+                       if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
+                               ret = 0;
+                               continue;
+                       }
                }
-       }
-       bch2_trans_iter_exit(trans, &iter);
+
+               ret;
+       }));
 
        if (!ret && need_another_pass) {
                ret = bch2_btree_write_buffer_flush_sync(trans);
@@ -1195,6 +1198,5 @@ again:
        }
 err:
        bch2_trans_put(trans);
-
        return ret;
 }