Skip to content

Commit 6d1980f

Browse files
author
Kent Overstreet
committed
bcachefs: Fix deleted inode check for dirs
We could delete directories transactionally on rmdir()/unlink(), but we don't; instead, like with regular files we wait for the VFS to call evict(). That means that our check for directories in the deleted inodes btree is wrong - the check should be for non-empty directories. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent e597288 commit 6d1980f

3 files changed

Lines changed: 22 additions & 13 deletions

File tree

fs/bcachefs/dirent.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -485,20 +485,15 @@ u64 bch2_dirent_lookup(struct bch_fs *c, subvol_inum dir,
485485
return ret;
486486
}
487487

488-
int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
488+
int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 snapshot)
489489
{
490490
struct btree_iter iter;
491491
struct bkey_s_c k;
492-
u32 snapshot;
493492
int ret;
494493

495-
ret = bch2_subvolume_get_snapshot(trans, dir.subvol, &snapshot);
496-
if (ret)
497-
return ret;
498-
499494
for_each_btree_key_upto_norestart(trans, iter, BTREE_ID_dirents,
500-
SPOS(dir.inum, 0, snapshot),
501-
POS(dir.inum, U64_MAX), 0, k, ret)
495+
SPOS(dir, 0, snapshot),
496+
POS(dir, U64_MAX), 0, k, ret)
502497
if (k.k->type == KEY_TYPE_dirent) {
503498
ret = -ENOTEMPTY;
504499
break;
@@ -508,6 +503,14 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
508503
return ret;
509504
}
510505

506+
int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
507+
{
508+
u32 snapshot;
509+
510+
return bch2_subvolume_get_snapshot(trans, dir.subvol, &snapshot) ?:
511+
bch2_empty_dir_snapshot(trans, dir.inum, snapshot);
512+
}
513+
511514
int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
512515
{
513516
struct btree_trans *trans = bch2_trans_get(c);

fs/bcachefs/dirent.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ u64 bch2_dirent_lookup(struct bch_fs *, subvol_inum,
6464
const struct bch_hash_info *,
6565
const struct qstr *, subvol_inum *);
6666

67+
int bch2_empty_dir_snapshot(struct btree_trans *, u64, u32);
6768
int bch2_empty_dir_trans(struct btree_trans *, subvol_inum);
6869
int bch2_readdir(struct bch_fs *, subvol_inum, struct dir_context *);
6970

fs/bcachefs/inode.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "btree_update.h"
88
#include "buckets.h"
99
#include "compress.h"
10+
#include "dirent.h"
1011
#include "error.h"
1112
#include "extents.h"
1213
#include "extent_update.h"
@@ -1093,11 +1094,15 @@ static int may_delete_deleted_inode(struct btree_trans *trans,
10931094
if (ret)
10941095
goto out;
10951096

1096-
if (fsck_err_on(S_ISDIR(inode.bi_mode), c,
1097-
deleted_inode_is_dir,
1098-
"directory %llu:%u in deleted_inodes btree",
1099-
pos.offset, pos.snapshot))
1100-
goto delete;
1097+
if (S_ISDIR(inode.bi_mode)) {
1098+
ret = bch2_empty_dir_snapshot(trans, pos.offset, pos.snapshot);
1099+
if (fsck_err_on(ret == -ENOTEMPTY, c, deleted_inode_is_dir,
1100+
"non empty directory %llu:%u in deleted_inodes btree",
1101+
pos.offset, pos.snapshot))
1102+
goto delete;
1103+
if (ret)
1104+
goto out;
1105+
}
11011106

11021107
if (fsck_err_on(!(inode.bi_flags & BCH_INODE_unlinked), c,
11031108
deleted_inode_not_unlinked,

0 commit comments

Comments
 (0)