diff options
Diffstat (limited to 'fs/nfs/namespace.c')
-rw-r--r-- | fs/nfs/namespace.c | 93 |
1 files changed, 27 insertions, 66 deletions
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 1807866bb3ab..d51868e5683c 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -148,66 +148,31 @@ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) | |||
148 | return pseudoflavor; | 148 | return pseudoflavor; |
149 | } | 149 | } |
150 | 150 | ||
151 | static int nfs_negotiate_security(const struct dentry *parent, | 151 | static struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir, |
152 | const struct dentry *dentry, | 152 | struct qstr *name, |
153 | rpc_authflavor_t *flavor) | 153 | struct nfs_fh *fh, |
154 | struct nfs_fattr *fattr) | ||
154 | { | 155 | { |
155 | struct page *page; | ||
156 | struct nfs4_secinfo_flavors *flavors; | ||
157 | int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); | ||
158 | int ret = -EPERM; | ||
159 | |||
160 | secinfo = NFS_PROTO(parent->d_inode)->secinfo; | ||
161 | if (secinfo != NULL) { | ||
162 | page = alloc_page(GFP_KERNEL); | ||
163 | if (!page) { | ||
164 | ret = -ENOMEM; | ||
165 | goto out; | ||
166 | } | ||
167 | flavors = page_address(page); | ||
168 | ret = secinfo(parent->d_inode, &dentry->d_name, flavors); | ||
169 | *flavor = nfs_find_best_sec(flavors); | ||
170 | put_page(page); | ||
171 | } | ||
172 | |||
173 | out: | ||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | static int nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, | ||
178 | struct dentry *dentry, struct path *path, | ||
179 | struct nfs_fh *fh, struct nfs_fattr *fattr, | ||
180 | rpc_authflavor_t *flavor) | ||
181 | { | ||
182 | struct rpc_clnt *clone; | ||
183 | struct rpc_auth *auth; | ||
184 | int err; | 156 | int err; |
185 | 157 | ||
186 | err = nfs_negotiate_security(parent, path->dentry, flavor); | 158 | if (NFS_PROTO(dir)->version == 4) |
187 | if (err < 0) | 159 | return nfs4_proc_lookup_mountpoint(dir, name, fh, fattr); |
188 | goto out; | 160 | |
189 | clone = rpc_clone_client(server->client); | 161 | err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr); |
190 | auth = rpcauth_create(*flavor, clone); | 162 | if (err) |
191 | if (!auth) { | 163 | return ERR_PTR(err); |
192 | err = -EIO; | 164 | return rpc_clone_client(NFS_SERVER(dir)->client); |
193 | goto out_shutdown; | ||
194 | } | ||
195 | err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, | ||
196 | &path->dentry->d_name, | ||
197 | fh, fattr); | ||
198 | out_shutdown: | ||
199 | rpc_shutdown_client(clone); | ||
200 | out: | ||
201 | return err; | ||
202 | } | 165 | } |
203 | #else /* CONFIG_NFS_V4 */ | 166 | #else /* CONFIG_NFS_V4 */ |
204 | static inline int nfs_lookup_with_sec(struct nfs_server *server, | 167 | static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir, |
205 | struct dentry *parent, struct dentry *dentry, | 168 | struct qstr *name, |
206 | struct path *path, struct nfs_fh *fh, | 169 | struct nfs_fh *fh, |
207 | struct nfs_fattr *fattr, | 170 | struct nfs_fattr *fattr) |
208 | rpc_authflavor_t *flavor) | ||
209 | { | 171 | { |
210 | return -EPERM; | 172 | int err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr); |
173 | if (err) | ||
174 | return ERR_PTR(err); | ||
175 | return rpc_clone_client(NFS_SERVER(dir)->client); | ||
211 | } | 176 | } |
212 | #endif /* CONFIG_NFS_V4 */ | 177 | #endif /* CONFIG_NFS_V4 */ |
213 | 178 | ||
@@ -226,12 +191,10 @@ static inline int nfs_lookup_with_sec(struct nfs_server *server, | |||
226 | struct vfsmount *nfs_d_automount(struct path *path) | 191 | struct vfsmount *nfs_d_automount(struct path *path) |
227 | { | 192 | { |
228 | struct vfsmount *mnt; | 193 | struct vfsmount *mnt; |
229 | struct nfs_server *server = NFS_SERVER(path->dentry->d_inode); | ||
230 | struct dentry *parent; | 194 | struct dentry *parent; |
231 | struct nfs_fh *fh = NULL; | 195 | struct nfs_fh *fh = NULL; |
232 | struct nfs_fattr *fattr = NULL; | 196 | struct nfs_fattr *fattr = NULL; |
233 | int err; | 197 | struct rpc_clnt *client; |
234 | rpc_authflavor_t flavor = RPC_AUTH_UNIX; | ||
235 | 198 | ||
236 | dprintk("--> nfs_d_automount()\n"); | 199 | dprintk("--> nfs_d_automount()\n"); |
237 | 200 | ||
@@ -249,21 +212,19 @@ struct vfsmount *nfs_d_automount(struct path *path) | |||
249 | 212 | ||
250 | /* Look it up again to get its attributes */ | 213 | /* Look it up again to get its attributes */ |
251 | parent = dget_parent(path->dentry); | 214 | parent = dget_parent(path->dentry); |
252 | err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, | 215 | client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr); |
253 | &path->dentry->d_name, | ||
254 | fh, fattr); | ||
255 | if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL) | ||
256 | err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor); | ||
257 | dput(parent); | 216 | dput(parent); |
258 | if (err != 0) { | 217 | if (IS_ERR(client)) { |
259 | mnt = ERR_PTR(err); | 218 | mnt = ERR_CAST(client); |
260 | goto out; | 219 | goto out; |
261 | } | 220 | } |
262 | 221 | ||
263 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 222 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
264 | mnt = nfs_do_refmount(path->dentry); | 223 | mnt = nfs_do_refmount(client, path->dentry); |
265 | else | 224 | else |
266 | mnt = nfs_do_submount(path->dentry, fh, fattr, flavor); | 225 | mnt = nfs_do_submount(path->dentry, fh, fattr, client->cl_auth->au_flavor); |
226 | rpc_shutdown_client(client); | ||
227 | |||
267 | if (IS_ERR(mnt)) | 228 | if (IS_ERR(mnt)) |
268 | goto out; | 229 | goto out; |
269 | 230 | ||