aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/getroot.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nfs/getroot.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/nfs/getroot.c')
-rw-r--r--fs/nfs/getroot.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index a70e446e1605..dcb61548887f 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -54,8 +54,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
54 iput(inode); 54 iput(inode);
55 return -ENOMEM; 55 return -ENOMEM;
56 } 56 }
57 /* Circumvent igrab(): we know the inode is not being freed */ 57 ihold(inode);
58 atomic_inc(&inode->i_count);
59 /* 58 /*
60 * Ensure that this dentry is invisible to d_find_alias(). 59 * Ensure that this dentry is invisible to d_find_alias().
61 * Otherwise, it may be spliced into the tree by 60 * Otherwise, it may be spliced into the tree by
@@ -64,9 +63,11 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
64 * This again causes shrink_dcache_for_umount_subtree() to 63 * This again causes shrink_dcache_for_umount_subtree() to
65 * Oops, since the test for IS_ROOT() will fail. 64 * Oops, since the test for IS_ROOT() will fail.
66 */ 65 */
67 spin_lock(&dcache_lock); 66 spin_lock(&sb->s_root->d_inode->i_lock);
67 spin_lock(&sb->s_root->d_lock);
68 list_del_init(&sb->s_root->d_alias); 68 list_del_init(&sb->s_root->d_alias);
69 spin_unlock(&dcache_lock); 69 spin_unlock(&sb->s_root->d_lock);
70 spin_unlock(&sb->s_root->d_inode->i_lock);
70 } 71 }
71 return 0; 72 return 0;
72} 73}
@@ -74,18 +75,25 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
74/* 75/*
75 * get an NFS2/NFS3 root dentry from the root filehandle 76 * get an NFS2/NFS3 root dentry from the root filehandle
76 */ 77 */
77struct 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,
79 const char *devname)
78{ 80{
79 struct nfs_server *server = NFS_SB(sb); 81 struct nfs_server *server = NFS_SB(sb);
80 struct nfs_fsinfo fsinfo; 82 struct nfs_fsinfo fsinfo;
81 struct dentry *ret; 83 struct dentry *ret;
82 struct inode *inode; 84 struct inode *inode;
85 void *name = kstrdup(devname, GFP_KERNEL);
83 int error; 86 int error;
84 87
88 if (!name)
89 return ERR_PTR(-ENOMEM);
90
85 /* get the actual root for this mount */ 91 /* get the actual root for this mount */
86 fsinfo.fattr = nfs_alloc_fattr(); 92 fsinfo.fattr = nfs_alloc_fattr();
87 if (fsinfo.fattr == NULL) 93 if (fsinfo.fattr == NULL) {
94 kfree(name);
88 return ERR_PTR(-ENOMEM); 95 return ERR_PTR(-ENOMEM);
96 }
89 97
90 error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); 98 error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
91 if (error < 0) { 99 if (error < 0) {
@@ -118,10 +126,15 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
118 } 126 }
119 127
120 security_d_instantiate(ret, inode); 128 security_d_instantiate(ret, inode);
121 129 spin_lock(&ret->d_lock);
122 if (ret->d_op == NULL) 130 if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
123 ret->d_op = server->nfs_client->rpc_ops->dentry_ops; 131 ret->d_fsdata = name;
132 name = NULL;
133 }
134 spin_unlock(&ret->d_lock);
124out: 135out:
136 if (name)
137 kfree(name);
125 nfs_free_fattr(fsinfo.fattr); 138 nfs_free_fattr(fsinfo.fattr);
126 return ret; 139 return ret;
127} 140}
@@ -171,27 +184,35 @@ out:
171/* 184/*
172 * get an NFS4 root dentry from the root filehandle 185 * get an NFS4 root dentry from the root filehandle
173 */ 186 */
174struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) 187struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
188 const char *devname)
175{ 189{
176 struct nfs_server *server = NFS_SB(sb); 190 struct nfs_server *server = NFS_SB(sb);
177 struct nfs_fattr *fattr = NULL; 191 struct nfs_fattr *fattr = NULL;
178 struct dentry *ret; 192 struct dentry *ret;
179 struct inode *inode; 193 struct inode *inode;
194 void *name = kstrdup(devname, GFP_KERNEL);
180 int error; 195 int error;
181 196
182 dprintk("--> nfs4_get_root()\n"); 197 dprintk("--> nfs4_get_root()\n");
183 198
199 if (!name)
200 return ERR_PTR(-ENOMEM);
201
184 /* get the info about the server and filesystem */ 202 /* get the info about the server and filesystem */
185 error = nfs4_server_capabilities(server, mntfh); 203 error = nfs4_server_capabilities(server, mntfh);
186 if (error < 0) { 204 if (error < 0) {
187 dprintk("nfs_get_root: getcaps error = %d\n", 205 dprintk("nfs_get_root: getcaps error = %d\n",
188 -error); 206 -error);
207 kfree(name);
189 return ERR_PTR(error); 208 return ERR_PTR(error);
190 } 209 }
191 210
192 fattr = nfs_alloc_fattr(); 211 fattr = nfs_alloc_fattr();
193 if (fattr == NULL) 212 if (fattr == NULL) {
194 return ERR_PTR(-ENOMEM);; 213 kfree(name);
214 return ERR_PTR(-ENOMEM);
215 }
195 216
196 /* get the actual root for this mount */ 217 /* get the actual root for this mount */
197 error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); 218 error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
@@ -201,6 +222,10 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
201 goto out; 222 goto out;
202 } 223 }
203 224
225 if (fattr->valid & NFS_ATTR_FATTR_FSID &&
226 !nfs_fsid_equal(&server->fsid, &fattr->fsid))
227 memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
228
204 inode = nfs_fhget(sb, mntfh, fattr); 229 inode = nfs_fhget(sb, mntfh, fattr);
205 if (IS_ERR(inode)) { 230 if (IS_ERR(inode)) {
206 dprintk("nfs_get_root: get root inode failed\n"); 231 dprintk("nfs_get_root: get root inode failed\n");
@@ -225,11 +250,15 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
225 } 250 }
226 251
227 security_d_instantiate(ret, inode); 252 security_d_instantiate(ret, inode);
228 253 spin_lock(&ret->d_lock);
229 if (ret->d_op == NULL) 254 if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
230 ret->d_op = server->nfs_client->rpc_ops->dentry_ops; 255 ret->d_fsdata = name;
231 256 name = NULL;
257 }
258 spin_unlock(&ret->d_lock);
232out: 259out:
260 if (name)
261 kfree(name);
233 nfs_free_fattr(fattr); 262 nfs_free_fattr(fattr);
234 dprintk("<-- nfs4_get_root()\n"); 263 dprintk("<-- nfs4_get_root()\n");
235 return ret; 264 return ret;