1
2
3
4
5
6
7
8#include <linux/module.h>
9#include <linux/init.h>
10
11#include <linux/time.h>
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <linux/string.h>
15#include <linux/stat.h>
16#include <linux/errno.h>
17#include <linux/unistd.h>
18#include <linux/sunrpc/clnt.h>
19#include <linux/sunrpc/stats.h>
20#include <linux/nfs_fs.h>
21#include <linux/nfs_mount.h>
22#include <linux/lockd/bind.h>
23#include <linux/seq_file.h>
24#include <linux/mount.h>
25#include <linux/vfs.h>
26#include <linux/namei.h>
27#include <linux/security.h>
28
29#include <linux/uaccess.h>
30
31#include "internal.h"
32
33#define NFSDBG_FACILITY NFSDBG_CLIENT
34
35
36
37
38
39static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
40{
41
42 if (sb->s_root == NULL) {
43 sb->s_root = d_make_root(inode);
44 if (sb->s_root == NULL)
45 return -ENOMEM;
46 ihold(inode);
47
48
49
50
51
52
53
54
55 spin_lock(&d_inode(sb->s_root)->i_lock);
56 spin_lock(&sb->s_root->d_lock);
57 hlist_del_init(&sb->s_root->d_u.d_alias);
58 spin_unlock(&sb->s_root->d_lock);
59 spin_unlock(&d_inode(sb->s_root)->i_lock);
60 }
61 return 0;
62}
63
64
65
66
67struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
68 const char *devname)
69{
70 struct nfs_server *server = NFS_SB(sb);
71 struct nfs_fsinfo fsinfo;
72 struct dentry *ret;
73 struct inode *inode;
74 void *name = kstrdup(devname, GFP_KERNEL);
75 int error;
76
77 if (!name)
78 return ERR_PTR(-ENOMEM);
79
80
81 fsinfo.fattr = nfs_alloc_fattr();
82 if (fsinfo.fattr == NULL) {
83 kfree(name);
84 return ERR_PTR(-ENOMEM);
85 }
86
87 error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
88 if (error < 0) {
89 dprintk("nfs_get_root: getattr error = %d\n", -error);
90 ret = ERR_PTR(error);
91 goto out;
92 }
93
94 inode = nfs_fhget(sb, mntfh, fsinfo.fattr, NULL);
95 if (IS_ERR(inode)) {
96 dprintk("nfs_get_root: get root inode failed\n");
97 ret = ERR_CAST(inode);
98 goto out;
99 }
100
101 error = nfs_superblock_set_dummy_root(sb, inode);
102 if (error != 0) {
103 ret = ERR_PTR(error);
104 goto out;
105 }
106
107
108
109
110
111 ret = d_obtain_root(inode);
112 if (IS_ERR(ret)) {
113 dprintk("nfs_get_root: get root dentry failed\n");
114 goto out;
115 }
116
117 security_d_instantiate(ret, inode);
118 spin_lock(&ret->d_lock);
119 if (IS_ROOT(ret) && !ret->d_fsdata &&
120 !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
121 ret->d_fsdata = name;
122 name = NULL;
123 }
124 spin_unlock(&ret->d_lock);
125out:
126 kfree(name);
127 nfs_free_fattr(fsinfo.fattr);
128 return ret;
129}
130