aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/getroot.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/getroot.c')
-rw-r--r--fs/nfs/getroot.c92
1 files changed, 38 insertions, 54 deletions
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 522e5ad4d8ad..e6242cdbaf91 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -43,6 +43,36 @@
43#define NFSDBG_FACILITY NFSDBG_CLIENT 43#define NFSDBG_FACILITY NFSDBG_CLIENT
44 44
45/* 45/*
46 * Set the superblock root dentry.
47 * Note that this function frees the inode in case of error.
48 */
49static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
50{
51 /* The mntroot acts as the dummy root dentry for this superblock */
52 if (sb->s_root == NULL) {
53 sb->s_root = d_alloc_root(inode);
54 if (sb->s_root == NULL) {
55 iput(inode);
56 return -ENOMEM;
57 }
58 /* Circumvent igrab(): we know the inode is not being freed */
59 atomic_inc(&inode->i_count);
60 /*
61 * Ensure that this dentry is invisible to d_find_alias().
62 * Otherwise, it may be spliced into the tree by
63 * d_materialise_unique if a parent directory from the same
64 * filesystem gets mounted at a later time.
65 * This again causes shrink_dcache_for_umount_subtree() to
66 * Oops, since the test for IS_ROOT() will fail.
67 */
68 spin_lock(&dcache_lock);
69 list_del_init(&sb->s_root->d_alias);
70 spin_unlock(&dcache_lock);
71 }
72 return 0;
73}
74
75/*
46 * get an NFS2/NFS3 root dentry from the root filehandle 76 * get an NFS2/NFS3 root dentry from the root filehandle
47 */ 77 */
48struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) 78struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
@@ -54,33 +84,6 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
54 struct inode *inode; 84 struct inode *inode;
55 int error; 85 int error;
56 86
57 /* create a dummy root dentry with dummy inode for this superblock */
58 if (!sb->s_root) {
59 struct nfs_fh dummyfh;
60 struct dentry *root;
61 struct inode *iroot;
62
63 memset(&dummyfh, 0, sizeof(dummyfh));
64 memset(&fattr, 0, sizeof(fattr));
65 nfs_fattr_init(&fattr);
66 fattr.valid = NFS_ATTR_FATTR;
67 fattr.type = NFDIR;
68 fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR;
69 fattr.nlink = 2;
70
71 iroot = nfs_fhget(sb, &dummyfh, &fattr);
72 if (IS_ERR(iroot))
73 return ERR_PTR(PTR_ERR(iroot));
74
75 root = d_alloc_root(iroot);
76 if (!root) {
77 iput(iroot);
78 return ERR_PTR(-ENOMEM);
79 }
80
81 sb->s_root = root;
82 }
83
84 /* get the actual root for this mount */ 87 /* get the actual root for this mount */
85 fsinfo.fattr = &fattr; 88 fsinfo.fattr = &fattr;
86 89
@@ -96,6 +99,10 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
96 return ERR_PTR(PTR_ERR(inode)); 99 return ERR_PTR(PTR_ERR(inode));
97 } 100 }
98 101
102 error = nfs_superblock_set_dummy_root(sb, inode);
103 if (error != 0)
104 return ERR_PTR(error);
105
99 /* root dentries normally start off anonymous and get spliced in later 106 /* root dentries normally start off anonymous and get spliced in later
100 * if the dentry tree reaches them; however if the dentry already 107 * if the dentry tree reaches them; however if the dentry already
101 * exists, we'll pick it up at this point and use it as the root 108 * exists, we'll pick it up at this point and use it as the root
@@ -241,33 +248,6 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
241 248
242 dprintk("--> nfs4_get_root()\n"); 249 dprintk("--> nfs4_get_root()\n");
243 250
244 /* create a dummy root dentry with dummy inode for this superblock */
245 if (!sb->s_root) {
246 struct nfs_fh dummyfh;
247 struct dentry *root;
248 struct inode *iroot;
249
250 memset(&dummyfh, 0, sizeof(dummyfh));
251 memset(&fattr, 0, sizeof(fattr));
252 nfs_fattr_init(&fattr);
253 fattr.valid = NFS_ATTR_FATTR;
254 fattr.type = NFDIR;
255 fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR;
256 fattr.nlink = 2;
257
258 iroot = nfs_fhget(sb, &dummyfh, &fattr);
259 if (IS_ERR(iroot))
260 return ERR_PTR(PTR_ERR(iroot));
261
262 root = d_alloc_root(iroot);
263 if (!root) {
264 iput(iroot);
265 return ERR_PTR(-ENOMEM);
266 }
267
268 sb->s_root = root;
269 }
270
271 /* get the info about the server and filesystem */ 251 /* get the info about the server and filesystem */
272 error = nfs4_server_capabilities(server, mntfh); 252 error = nfs4_server_capabilities(server, mntfh);
273 if (error < 0) { 253 if (error < 0) {
@@ -289,6 +269,10 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
289 return ERR_PTR(PTR_ERR(inode)); 269 return ERR_PTR(PTR_ERR(inode));
290 } 270 }
291 271
272 error = nfs_superblock_set_dummy_root(sb, inode);
273 if (error != 0)
274 return ERR_PTR(error);
275
292 /* root dentries normally start off anonymous and get spliced in later 276 /* root dentries normally start off anonymous and get spliced in later
293 * if the dentry tree reaches them; however if the dentry already 277 * if the dentry tree reaches them; however if the dentry already
294 * exists, we'll pick it up at this point and use it as the root 278 * exists, we'll pick it up at this point and use it as the root