Merge tag 'nfsd-5.3-1' of git://linux-nfs.org/~bfields/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 21 Aug 2019 17:04:38 +0000 (10:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 21 Aug 2019 17:04:38 +0000 (10:04 -0700)
Pull nfsd fixes from Bruce Fields:
 "Fix nfsd bugs: three in the new nfsd/clients/ code, one in the reply
  cache containerization"

* tag 'nfsd-5.3-1' of git://linux-nfs.org/~bfields/linux:
  nfsd4: Fix kernel crash when reading proc file reply_cache_stats
  nfsd: initialize i_private before d_add
  nfsd: use i_wrlock instead of rcu for nfsdfs i_private
  nfsd: fix dentry leak upon mkdir failure.

fs/nfsd/nfscache.c
fs/nfsd/nfsctl.c

index 26ad75ae2be042d3372f3bea221a3af0787a4722..96352ab7bd8100af89f2fadfa50825e31221dd7b 100644 (file)
@@ -571,7 +571,7 @@ nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data)
  */
 static int nfsd_reply_cache_stats_show(struct seq_file *m, void *v)
 {
-       struct nfsd_net *nn = v;
+       struct nfsd_net *nn = m->private;
 
        seq_printf(m, "max entries:           %u\n", nn->max_drc_entries);
        seq_printf(m, "num entries:           %u\n",
index 13c548733860cca6414b23bc30caea2d64c69b02..3cf4f6aa48d605499b9b8b766084a50661e7d3a8 100644 (file)
@@ -1171,13 +1171,17 @@ static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode)
        return inode;
 }
 
-static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, struct nfsdfs_client *ncl)
 {
        struct inode *inode;
 
        inode = nfsd_get_inode(dir->i_sb, mode);
        if (!inode)
                return -ENOMEM;
+       if (ncl) {
+               inode->i_private = ncl;
+               kref_get(&ncl->cl_ref);
+       }
        d_add(dentry, inode);
        inc_nlink(dir);
        fsnotify_mkdir(dir, dentry);
@@ -1194,17 +1198,14 @@ static struct dentry *nfsd_mkdir(struct dentry *parent, struct nfsdfs_client *nc
        dentry = d_alloc_name(parent, name);
        if (!dentry)
                goto out_err;
-       ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600);
+       ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600, ncl);
        if (ret)
                goto out_err;
-       if (ncl) {
-               d_inode(dentry)->i_private = ncl;
-               kref_get(&ncl->cl_ref);
-       }
 out:
        inode_unlock(dir);
        return dentry;
 out_err:
+       dput(dentry);
        dentry = ERR_PTR(ret);
        goto out;
 }
@@ -1214,11 +1215,9 @@ static void clear_ncl(struct inode *inode)
        struct nfsdfs_client *ncl = inode->i_private;
 
        inode->i_private = NULL;
-       synchronize_rcu();
        kref_put(&ncl->cl_ref, ncl->cl_release);
 }
 
-
 static struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode)
 {
        struct nfsdfs_client *nc = inode->i_private;
@@ -1232,9 +1231,9 @@ struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
 {
        struct nfsdfs_client *nc;
 
-       rcu_read_lock();
+       inode_lock_shared(inode);
        nc = __get_nfsdfs_client(inode);
-       rcu_read_unlock();
+       inode_unlock_shared(inode);
        return nc;
 }
 /* from __rpc_unlink */