summaryrefslogtreecommitdiff
path: root/fs/nfs/getroot.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-02-07 17:39:56 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-02-07 17:39:56 -0800
commitf43574d0ac80d76537e265548a13b1bc46aa751b (patch)
tree8667f7a2fd0825ebf7a636eca3341a8a866f32b0 /fs/nfs/getroot.c
parent41dcd67e88688afbeb3b2bd23960eed5daec74e7 (diff)
parent7dc2993a9e51dd2eee955944efec65bef90265b7 (diff)
Merge tag 'nfs-for-5.6-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
Puyll NFS client updates from Anna Schumaker: "Stable bugfixes: - Fix memory leaks and corruption in readdir # v2.6.37+ - Directory page cache needs to be locked when read # v2.6.37+ New features: - Convert NFS to use the new mount API - Add "softreval" mount option to let clients use cache if server goes down - Add a config option to compile without UDP support - Limit the number of inactive delegations the client can cache at once - Improved readdir concurrency using iterate_shared() Other bugfixes and cleanups: - More 64-bit time conversions - Add additional diagnostic tracepoints - Check for holes in swapfiles, and add dependency on CONFIG_SWAP - Various xprtrdma cleanups to prepare for 5.7's changes - Several fixes for NFS writeback and commit handling - Fix acls over krb5i/krb5p mounts - Recover from premature loss of openstateids - Fix NFS v3 chacl and chmod bug - Compare creds using cred_fscmp() - Use kmemdup_nul() in more places - Optimize readdir cache page invalidation - Lease renewal and recovery fixes" * tag 'nfs-for-5.6-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (93 commits) NFSv4.0: nfs4_do_fsinfo() should not do implicit lease renewals NFSv4: try lease recovery on NFS4ERR_EXPIRED NFS: Fix memory leaks nfs: optimise readdir cache page invalidation NFS: Switch readdir to using iterate_shared() NFS: Use kmemdup_nul() in nfs_readdir_make_qstr() NFS: Directory page cache pages need to be locked when read NFS: Fix memory leaks and corruption in readdir SUNRPC: Use kmemdup_nul() in rpc_parse_scope_id() NFS: Replace various occurrences of kstrndup() with kmemdup_nul() NFSv4: Limit the total number of cached delegations NFSv4: Add accounting for the number of active delegations held NFSv4: Try to return the delegation immediately when marked for return on close NFS: Clear NFS_DELEGATION_RETURN_IF_CLOSED when the delegation is returned NFSv4: nfs_inode_evict_delegation() should set NFS_DELEGATION_RETURNING NFS: nfs_find_open_context() should use cred_fscmp() NFS: nfs_access_get_cached_rcu() should use cred_fscmp() NFSv4: pnfs_roc() must use cred_fscmp() to compare creds NFS: remove unused macros nfs: Return EINVAL rather than ERANGE for mount parse errors ...
Diffstat (limited to 'fs/nfs/getroot.c')
-rw-r--r--fs/nfs/getroot.c73
1 files changed, 39 insertions, 34 deletions
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 878c4c5982d9..b012c2668a1f 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -64,66 +64,71 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
/*
* get an NFS2/NFS3 root dentry from the root filehandle
*/
-struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
- const char *devname)
+int nfs_get_root(struct super_block *s, struct fs_context *fc)
{
- struct nfs_server *server = NFS_SB(sb);
+ struct nfs_fs_context *ctx = nfs_fc2context(fc);
+ struct nfs_server *server = NFS_SB(s);
struct nfs_fsinfo fsinfo;
- struct dentry *ret;
+ struct dentry *root;
struct inode *inode;
- void *name = kstrdup(devname, GFP_KERNEL);
- int error;
+ char *name;
+ int error = -ENOMEM;
+ name = kstrdup(fc->source, GFP_KERNEL);
if (!name)
- return ERR_PTR(-ENOMEM);
+ goto out;
/* get the actual root for this mount */
fsinfo.fattr = nfs_alloc_fattr();
- if (fsinfo.fattr == NULL) {
- kfree(name);
- return ERR_PTR(-ENOMEM);
- }
+ if (fsinfo.fattr == NULL)
+ goto out_name;
- error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+ error = server->nfs_client->rpc_ops->getroot(server, ctx->mntfh, &fsinfo);
if (error < 0) {
dprintk("nfs_get_root: getattr error = %d\n", -error);
- ret = ERR_PTR(error);
- goto out;
+ nfs_errorf(fc, "NFS: Couldn't getattr on root");
+ goto out_fattr;
}
- inode = nfs_fhget(sb, mntfh, fsinfo.fattr, NULL);
+ inode = nfs_fhget(s, ctx->mntfh, fsinfo.fattr, NULL);
if (IS_ERR(inode)) {
dprintk("nfs_get_root: get root inode failed\n");
- ret = ERR_CAST(inode);
- goto out;
+ error = PTR_ERR(inode);
+ nfs_errorf(fc, "NFS: Couldn't get root inode");
+ goto out_fattr;
}
- error = nfs_superblock_set_dummy_root(sb, inode);
- if (error != 0) {
- ret = ERR_PTR(error);
- goto out;
- }
+ error = nfs_superblock_set_dummy_root(s, inode);
+ if (error != 0)
+ goto out_fattr;
/* root dentries normally start off anonymous and get spliced in later
* if the dentry tree reaches them; however if the dentry already
* exists, we'll pick it up at this point and use it as the root
*/
- ret = d_obtain_root(inode);
- if (IS_ERR(ret)) {
+ root = d_obtain_root(inode);
+ if (IS_ERR(root)) {
dprintk("nfs_get_root: get root dentry failed\n");
- goto out;
+ error = PTR_ERR(root);
+ nfs_errorf(fc, "NFS: Couldn't get root dentry");
+ goto out_fattr;
}
- security_d_instantiate(ret, inode);
- spin_lock(&ret->d_lock);
- if (IS_ROOT(ret) && !ret->d_fsdata &&
- !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
- ret->d_fsdata = name;
+ security_d_instantiate(root, inode);
+ spin_lock(&root->d_lock);
+ if (IS_ROOT(root) && !root->d_fsdata &&
+ !(root->d_flags & DCACHE_NFSFS_RENAMED)) {
+ root->d_fsdata = name;
name = NULL;
}
- spin_unlock(&ret->d_lock);
-out:
- kfree(name);
+ spin_unlock(&root->d_lock);
+ fc->root = root;
+ error = 0;
+
+out_fattr:
nfs_free_fattr(fsinfo.fattr);
- return ret;
+out_name:
+ kfree(name);
+out:
+ return error;
}