diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nfs/getroot.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.c | 61 |
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 | */ |
77 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 78 | struct 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); | ||
124 | out: | 135 | out: |
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 | */ |
174 | struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 187 | struct 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); | ||
232 | out: | 259 | out: |
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; |