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>
This commit is contained in:
parent
e597288839
commit
6d1980f0af
@ -485,20 +485,15 @@ retry:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
|
||||
int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 snapshot)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
struct bkey_s_c k;
|
||||
u32 snapshot;
|
||||
int ret;
|
||||
|
||||
ret = bch2_subvolume_get_snapshot(trans, dir.subvol, &snapshot);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_btree_key_upto_norestart(trans, iter, BTREE_ID_dirents,
|
||||
SPOS(dir.inum, 0, snapshot),
|
||||
POS(dir.inum, U64_MAX), 0, k, ret)
|
||||
SPOS(dir, 0, snapshot),
|
||||
POS(dir, U64_MAX), 0, k, ret)
|
||||
if (k.k->type == KEY_TYPE_dirent) {
|
||||
ret = -ENOTEMPTY;
|
||||
break;
|
||||
@ -508,6 +503,14 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
|
||||
{
|
||||
u32 snapshot;
|
||||
|
||||
return bch2_subvolume_get_snapshot(trans, dir.subvol, &snapshot) ?:
|
||||
bch2_empty_dir_snapshot(trans, dir.inum, snapshot);
|
||||
}
|
||||
|
||||
int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
|
||||
{
|
||||
struct btree_trans *trans = bch2_trans_get(c);
|
||||
|
@ -64,6 +64,7 @@ u64 bch2_dirent_lookup(struct bch_fs *, subvol_inum,
|
||||
const struct bch_hash_info *,
|
||||
const struct qstr *, subvol_inum *);
|
||||
|
||||
int bch2_empty_dir_snapshot(struct btree_trans *, u64, u32);
|
||||
int bch2_empty_dir_trans(struct btree_trans *, subvol_inum);
|
||||
int bch2_readdir(struct bch_fs *, subvol_inum, struct dir_context *);
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user