Skip to content

Commit

Permalink
bcachefs: Check for subvolume children when deleting subvolumes
Browse files Browse the repository at this point in the history
Recursively destroying subvolumes isn't allowed yet.

Fixes: #634
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
  • Loading branch information
Kent Overstreet committed Feb 11, 2024
1 parent 1f4cf2e commit 502dcb1
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 5 deletions.
2 changes: 1 addition & 1 deletion fs/bcachefs/dirent.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 snapshot)
SPOS(dir, 0, snapshot),
POS(dir, U64_MAX), 0, k, ret)
if (k.k->type == KEY_TYPE_dirent) {
ret = -ENOTEMPTY;
ret = -BCH_ERR_ENOTEMPTY_dir_not_empty;
break;
}
bch2_trans_iter_exit(trans, &iter);
Expand Down
2 changes: 2 additions & 0 deletions fs/bcachefs/errcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@
x(ENOENT, ENOENT_dirent_doesnt_match_inode) \
x(ENOENT, ENOENT_dev_not_found) \
x(ENOENT, ENOENT_dev_idx_not_found) \
x(ENOTEMPTY, ENOTEMPTY_dir_not_empty) \
x(ENOTEMPTY, ENOTEMPTY_subvol_not_empty) \
x(0, open_buckets_empty) \
x(0, freelist_empty) \
x(BCH_ERR_freelist_empty, no_buckets_found) \
Expand Down
15 changes: 11 additions & 4 deletions fs/bcachefs/fs-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ int bch2_unlink_trans(struct btree_trans *trans,
struct bch_inode_unpacked *dir_u,
struct bch_inode_unpacked *inode_u,
const struct qstr *name,
bool deleting_snapshot)
bool deleting_subvol)
{
struct bch_fs *c = trans->c;
struct btree_iter dir_iter = { NULL };
Expand Down Expand Up @@ -271,18 +271,25 @@ int bch2_unlink_trans(struct btree_trans *trans,
if (ret)
goto err;

if (!deleting_snapshot && S_ISDIR(inode_u->bi_mode)) {
if (!deleting_subvol && S_ISDIR(inode_u->bi_mode)) {
ret = bch2_empty_dir_trans(trans, inum);
if (ret)
goto err;
}

if (deleting_snapshot && !inode_u->bi_subvol) {
if (deleting_subvol && !inode_u->bi_subvol) {
ret = -BCH_ERR_ENOENT_not_subvol;
goto err;
}

if (deleting_snapshot || inode_u->bi_subvol) {
if (inode_u->bi_subvol) {
/* Recursive subvolume destroy not allowed (yet?) */
ret = bch2_subvol_has_children(trans, inode_u->bi_subvol);
if (ret)
goto err;
}

if (deleting_subvol || inode_u->bi_subvol) {
ret = bch2_subvolume_unlink(trans, inode_u->bi_subvol);
if (ret)
goto err;
Expand Down
13 changes: 13 additions & 0 deletions fs/bcachefs/subvolume.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,19 @@ int bch2_subvolume_trigger(struct btree_trans *trans,
return 0;
}

int bch2_subvol_has_children(struct btree_trans *trans, u32 subvol)
{
struct btree_iter iter;

bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolume_children, POS(subvol, 0), 0);
struct bkey_s_c k = bch2_btree_iter_peek(&iter);
bch2_trans_iter_exit(trans, &iter);

return bkey_err(k) ?: k.k && k.k->p.inode == subvol
? -BCH_ERR_ENOTEMPTY_subvol_not_empty
: 0;
}

static __always_inline int
bch2_subvolume_get_inlined(struct btree_trans *trans, unsigned subvol,
bool inconsistent_if_not_found,
Expand Down
1 change: 1 addition & 0 deletions fs/bcachefs/subvolume.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ int bch2_subvolume_trigger(struct btree_trans *, enum btree_id, unsigned,
.min_val_size = 16, \
})

int bch2_subvol_has_children(struct btree_trans *, u32);
int bch2_subvolume_get(struct btree_trans *, unsigned,
bool, int, struct bch_subvolume *);
int bch2_subvolume_get_snapshot(struct btree_trans *, u32, u32 *);
Expand Down

0 comments on commit 502dcb1

Please sign in to comment.