diff options
Diffstat (limited to 'fs/afs/mntpt.c')
-rw-r--r-- | fs/afs/mntpt.c | 56 |
1 files changed, 13 insertions, 43 deletions
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index e83c0336e7b5..aa59184151d0 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -24,7 +24,6 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, | |||
24 | struct dentry *dentry, | 24 | struct dentry *dentry, |
25 | struct nameidata *nd); | 25 | struct nameidata *nd); |
26 | static int afs_mntpt_open(struct inode *inode, struct file *file); | 26 | static int afs_mntpt_open(struct inode *inode, struct file *file); |
27 | static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); | ||
28 | static void afs_mntpt_expiry_timed_out(struct work_struct *work); | 27 | static void afs_mntpt_expiry_timed_out(struct work_struct *work); |
29 | 28 | ||
30 | const struct file_operations afs_mntpt_file_operations = { | 29 | const struct file_operations afs_mntpt_file_operations = { |
@@ -34,13 +33,11 @@ const struct file_operations afs_mntpt_file_operations = { | |||
34 | 33 | ||
35 | const struct inode_operations afs_mntpt_inode_operations = { | 34 | const struct inode_operations afs_mntpt_inode_operations = { |
36 | .lookup = afs_mntpt_lookup, | 35 | .lookup = afs_mntpt_lookup, |
37 | .follow_link = afs_mntpt_follow_link, | ||
38 | .readlink = page_readlink, | 36 | .readlink = page_readlink, |
39 | .getattr = afs_getattr, | 37 | .getattr = afs_getattr, |
40 | }; | 38 | }; |
41 | 39 | ||
42 | const struct inode_operations afs_autocell_inode_operations = { | 40 | const struct inode_operations afs_autocell_inode_operations = { |
43 | .follow_link = afs_mntpt_follow_link, | ||
44 | .getattr = afs_getattr, | 41 | .getattr = afs_getattr, |
45 | }; | 42 | }; |
46 | 43 | ||
@@ -88,6 +85,7 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key) | |||
88 | _debug("symlink is a mountpoint"); | 85 | _debug("symlink is a mountpoint"); |
89 | spin_lock(&vnode->lock); | 86 | spin_lock(&vnode->lock); |
90 | set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); | 87 | set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); |
88 | vnode->vfs_inode.i_flags |= S_AUTOMOUNT; | ||
91 | spin_unlock(&vnode->lock); | 89 | spin_unlock(&vnode->lock); |
92 | } | 90 | } |
93 | 91 | ||
@@ -238,52 +236,24 @@ error_no_devname: | |||
238 | } | 236 | } |
239 | 237 | ||
240 | /* | 238 | /* |
241 | * follow a link from a mountpoint directory, thus causing it to be mounted | 239 | * handle an automount point |
242 | */ | 240 | */ |
243 | static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) | 241 | struct vfsmount *afs_d_automount(struct path *path) |
244 | { | 242 | { |
245 | struct vfsmount *newmnt; | 243 | struct vfsmount *newmnt; |
246 | int err; | ||
247 | 244 | ||
248 | _enter("%p{%s},{%s:%p{%s},}", | 245 | _enter("{%s,%s}", path->mnt->mnt_devname, path->dentry->d_name.name); |
249 | dentry, | ||
250 | dentry->d_name.name, | ||
251 | nd->path.mnt->mnt_devname, | ||
252 | dentry, | ||
253 | nd->path.dentry->d_name.name); | ||
254 | |||
255 | dput(nd->path.dentry); | ||
256 | nd->path.dentry = dget(dentry); | ||
257 | |||
258 | newmnt = afs_mntpt_do_automount(nd->path.dentry); | ||
259 | if (IS_ERR(newmnt)) { | ||
260 | path_put(&nd->path); | ||
261 | return (void *)newmnt; | ||
262 | } | ||
263 | 246 | ||
264 | mntget(newmnt); | 247 | newmnt = afs_mntpt_do_automount(path->dentry); |
265 | err = do_add_mount(newmnt, &nd->path, MNT_SHRINKABLE, &afs_vfsmounts); | 248 | if (IS_ERR(newmnt)) |
266 | switch (err) { | 249 | return newmnt; |
267 | case 0: | ||
268 | path_put(&nd->path); | ||
269 | nd->path.mnt = newmnt; | ||
270 | nd->path.dentry = dget(newmnt->mnt_root); | ||
271 | queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer, | ||
272 | afs_mntpt_expiry_timeout * HZ); | ||
273 | break; | ||
274 | case -EBUSY: | ||
275 | /* someone else made a mount here whilst we were busy */ | ||
276 | while (d_mountpoint(nd->path.dentry) && | ||
277 | follow_down(&nd->path)) | ||
278 | ; | ||
279 | err = 0; | ||
280 | default: | ||
281 | mntput(newmnt); | ||
282 | break; | ||
283 | } | ||
284 | 250 | ||
285 | _leave(" = %d", err); | 251 | mntget(newmnt); /* prevent immediate expiration */ |
286 | return ERR_PTR(err); | 252 | mnt_set_expiry(newmnt, &afs_vfsmounts); |
253 | queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer, | ||
254 | afs_mntpt_expiry_timeout * HZ); | ||
255 | _leave(" = %p {%s}", newmnt, newmnt->mnt_devname); | ||
256 | return newmnt; | ||
287 | } | 257 | } |
288 | 258 | ||
289 | /* | 259 | /* |