All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guoyu Ou <benogy@gmail.com>
To: Kent Overstreet <kent.overstreet@linux.dev>
Cc: linux-bcachefs@vger.kernel.org, benogy@gmail.com
Subject: Re: [PATCH] bcachefs: skip invisible entries in empty subvolume checking
Date: Sun, 11 Feb 2024 15:49:17 +0800	[thread overview]
Message-ID: <Zch7_Q9jpu79J2Z6@ousvr> (raw)
In-Reply-To: <3skajn5gtyfbxu2zivet2kpq62i2nwcidzzfe5jk6ovi57esa5@vnbgwdz5ypk7>

On Sat, Feb 10, 2024 at 05:56:15PM -0500, Kent Overstreet wrote:
> On Sat, Feb 10, 2024 at 10:06:37PM +0800, Guoyu Ou wrote:
> > When we are checking whether a subvolume is empty in the specified snapshot,
> > entries that do not belong to this subvolume should be skipped.
> >
> > This fixes the following case:
> >
> >     $ bcachefs subvolume create ./sub
> >     $ cd sub
> >     $ bcachefs subvolume create ./sub2
> >     $ bcachefs subvolume snapshot . ./snap
> >     $ ls -a snap
> >     . ..
> >     $ rmdir snap
> >     rmdir: failed to remove 'snap': Directory not empty
> >
> > Signed-off-by: Guoyu Ou <benogy@gmail.com>
>
> So that's an interesting corner case - can you add a ktest test for it?
> https://evilpiepirate.org/git/ktest.git/
>
> If you're not using it yet, please jump on IRC and ask if you run into
> any issues getting it going;
>
> There's an issue with your fix: in may_delete_deleted_inode(), you're
> getting the subvol from inode.bi_subvol.
>
> That's incorrect, because bi_subvol is only set on subvolume roots,
> because we can't go through every inode in the subvolume and change
> bi_subvol when taking a snapshot.
>
> You're doing it right in bch2_empty_dir_trans(), which is the path that
> matters more; may_delete_deleted_inode() is only checking "did this
> filesystem get borked".
>
> I would just pass in 0 from may_delete_deleted_inode(), and then have
> empty_dir_snapshot() ignore DT_SUBVOL dirents when subvol == 0. It makes
> the check less strict, but that's ok, the rest of fsck will still catch
> it.

Got it. I will add a new test case and update this patch later.

>
> > ---
> >  fs/bcachefs/dirent.c | 7 +++++--
> >  fs/bcachefs/dirent.h | 2 +-
> >  fs/bcachefs/inode.c  | 2 +-
> >  3 files changed, 7 insertions(+), 4 deletions(-)
> >
> > diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
> > index 4ae1e9f002a0..82c5bff01411 100644
> > --- a/fs/bcachefs/dirent.c
> > +++ b/fs/bcachefs/dirent.c
> > @@ -508,7 +508,7 @@ u64 bch2_dirent_lookup(struct bch_fs *c, subvol_inum dir,
> >  	return ret;
> >  }
> >
> > -int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 snapshot)
> > +int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 subvol, u32 snapshot)
> >  {
> >  	struct btree_iter iter;
> >  	struct bkey_s_c k;
> > @@ -518,6 +518,9 @@ 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) {
> > +			struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
> > +			if (d.v->d_type == DT_SUBVOL && le32_to_cpu(d.v->d_parent_subvol) != subvol)
> > +				continue;
> >  			ret = -ENOTEMPTY;
> >  			break;
> >  		}
> > @@ -531,7 +534,7 @@ 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);
> > +		bch2_empty_dir_snapshot(trans, dir.inum, dir.subvol, snapshot);
> >  }
> >
> >  int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
> > diff --git a/fs/bcachefs/dirent.h b/fs/bcachefs/dirent.h
> > index 21ffeb78f02e..aeb8207ca9f2 100644
> > --- a/fs/bcachefs/dirent.h
> > +++ b/fs/bcachefs/dirent.h
> > @@ -69,7 +69,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_snapshot(struct btree_trans *, u64, u32, u32);
> >  int bch2_empty_dir_trans(struct btree_trans *, subvol_inum);
> >  int bch2_readdir(struct bch_fs *, subvol_inum, struct dir_context *);
> >
> > diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c
> > index 086f0090b03a..8f85d0132cc2 100644
> > --- a/fs/bcachefs/inode.c
> > +++ b/fs/bcachefs/inode.c
> > @@ -1088,7 +1088,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans,
> >  		goto out;
> >
> >  	if (S_ISDIR(inode.bi_mode)) {
> > -		ret = bch2_empty_dir_snapshot(trans, pos.offset, pos.snapshot);
> > +		ret = bch2_empty_dir_snapshot(trans, pos.offset, inode.bi_subvol, 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))
> > --
> > 2.43.0
> >

      reply	other threads:[~2024-02-11  7:49 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-10 14:06 [PATCH] bcachefs: skip invisible entries in empty subvolume checking Guoyu Ou
2024-02-10 22:56 ` Kent Overstreet
2024-02-11  7:49   ` Guoyu Ou [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Zch7_Q9jpu79J2Z6@ousvr \
    --to=benogy@gmail.com \
    --cc=kent.overstreet@linux.dev \
    --cc=linux-bcachefs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.