[Devel] [PATCH RH7] nfs: remove excess dput in nfs_prime_dcache

Konstantin Khorenko khorenko at virtuozzo.com
Thu Aug 11 20:03:10 MSK 2022


On 11.08.2022 15:54, Pavel Tikhomirov wrote:
> Imagine code path:
> 
> static
> void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
> {
> ...
>          dentry = d_lookup(parent, &filename); // get non-null dentry
>          if (dentry != NULL) { // true
>                  /* Is there a mountpoint here? If so, just exit */
>                  if (!nfs_fsid_equal(&NFS_SB(dentry->d_sb)->fsid,
>                                          &entry->fattr->fsid)) // false
>                          goto out;
>                  if (nfs_same_file(dentry, entry)) { // false
>                          if (!entry->fh->size)
>                                  goto out;
>                          nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
>                          status = nfs_refresh_inode(dentry->d_inode, entry->fattr);
>                          if (!status)
>                                  nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label);
>                          goto out;
>                  } else {
>                          if (d_invalidate(dentry) != 0) // false
>                                  goto out;
>                          dput(dentry); // put dentry first time
>                  }
>          }
>          if (!entry->fh->size) // true
> 		goto out;
> ...
> out:
>          dput(dentry); // put dentry second time
> }
> 
> Because of this excess dput we get a crash in __put_nfs_open_context
> as ctx->dentry->inode becomes zero.
> 
> Problem appeared due to bad port of [1] in RHEL.
> 
> 7dc72d5f7a0e ("NFS: Fix inode corruption in nfs_prime_dcache()") [1]
> 
> https://jira.sw.ru/browse/PSBM-141526
> Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>

Acked-by: Konstantin Khorenko <khorenko at virtuozzo.com>

> ---
>   fs/nfs/dir.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index bd1a419d34c7..033e65319327 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -527,7 +527,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
>   		}
>   	}
>   	if (!entry->fh->size)
> -		goto out;
> +		return;
>   
>   	dentry = d_alloc(parent, &filename);
>   	if (dentry == NULL)


More information about the Devel mailing list