Re: [PATCH v9 4/7] vfs: Optimize atomic_open() on positive dentry

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Sep 21, 2023 at 12:48 AM Bernd Schubert <bschubert@xxxxxxx> wrote:
>
> This was suggested by Miklos based on review from the previous
> patch that introduced atomic open for positive dentries.
> In open_last_lookups() the dentry was not used anymore when atomic
> revalidate was available, which required to release the dentry,
> then code fall through to lookup_open was done, which resulted
> in another d_lookup and also d_revalidate. All of that can
> be avoided by the new atomic_revalidate_open() function.
>
> Another included change is the introduction of an enum as
> d_revalidate return code.
>
> Signed-off-by: Bernd Schubert <bschubert@xxxxxxx>
> Cc: Miklos Szeredi <miklos@xxxxxxxxxx>
> Cc: Dharmendra Singh <dsingh@xxxxxxx>
> Cc: Christian Brauner <brauner@xxxxxxxxxx>
> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
> Cc: linux-fsdevel@xxxxxxxxxxxxxxx
> ---
>  fs/namei.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 43 insertions(+), 2 deletions(-)
>
> diff --git a/fs/namei.c b/fs/namei.c
> index f01b278ac0ef..8ad7a0dfa596 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -3388,6 +3388,44 @@ static struct dentry *atomic_open(struct nameidata *nd, struct dentry *dentry,
>         return dentry;
>  }
>
> +static struct dentry *atomic_revalidate_open(struct dentry *dentry,
> +                                            struct nameidata *nd,
> +                                            struct file *file,
> +                                            const struct open_flags *op,
> +                                            bool *got_write)
> +{
> +       struct mnt_idmap *idmap;
> +       struct dentry *dir = nd->path.dentry;
> +       struct inode *dir_inode = dir->d_inode;
> +       int open_flag = op->open_flag;
> +       umode_t mode = op->mode;
> +
> +       if (unlikely(IS_DEADDIR(dir_inode)))
> +               return ERR_PTR(-ENOENT);
> +
> +       file->f_mode &= ~FMODE_CREATED;
> +
> +       if (unlikely(open_flag & O_CREAT)) {
> +               WARN_ON(1);

      if (WARN_ON_ONCE(open_flag & O_CREAT)) {

is more compact and produces a nicer print

> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       if (open_flag & (O_TRUNC | O_WRONLY | O_RDWR))
> +               *got_write = !mnt_want_write(nd->path.mnt);
> +       else
> +               *got_write = false;
> +
> +       if (!got_write)
> +               open_flag &= ~O_TRUNC;
> +
> +       inode_lock_shared(dir->d_inode);
> +       dentry = atomic_open(nd, dentry, file, open_flag, mode);
> +       inode_unlock_shared(dir->d_inode);
> +
> +       return dentry;
> +
> +}
> +
>  /*
>   * Look up and maybe create and open the last component.
>   *
> @@ -3541,8 +3579,10 @@ static const char *open_last_lookups(struct nameidata *nd,
>                 if (IS_ERR(dentry))
>                         return ERR_CAST(dentry);
>                 if (dentry && unlikely(atomic_revalidate)) {
> -                       dput(dentry);
> -                       dentry = NULL;
> +                       BUG_ON(nd->flags & LOOKUP_RCU);

The assertion means that someone wrote bad code
it does not mean that the kernel internal state is hopelessly corrupted.
Please avoid BUG_ON and use WARN_ON_ONCE and if possible
(seems to be the case here) also take the graceful error path.
It's better to fail an open than to crash the kernel.

Thanks,
Amir.

> +                       dentry = atomic_revalidate_open(dentry, nd, file, op,
> +                                                       &got_write);
> +                       goto drop_write;
>                 }
>                 if (likely(dentry))
>                         goto finish_lookup;
> @@ -3580,6 +3620,7 @@ static const char *open_last_lookups(struct nameidata *nd,
>         else
>                 inode_unlock_shared(dir->d_inode);
>
> +drop_write:
>         if (got_write)
>                 mnt_drop_write(nd->path.mnt);
>
> --
> 2.39.2
>




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux