diff options
author | David Howells <dhowells@redhat.com> | 2011-01-14 14:04:05 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-15 20:07:33 -0500 |
commit | d18610b0ce9eb48c60649d8fcbf68374c84349d3 (patch) | |
tree | 58a4088b75a14a35e343b7ee6a4ba57d63792270 /fs | |
parent | 6f45b65672c8017d5e210e338bb5858a938ef445 (diff) |
AFS: Use d_automount() rather than abusing follow_link()
Make AFS use the new d_automount() dentry operation rather than abusing
follow_link() on directories.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/afs/dir.c | 1 | ||||
-rw-r--r-- | fs/afs/inode.c | 3 | ||||
-rw-r--r-- | fs/afs/internal.h | 1 | ||||
-rw-r--r-- | fs/afs/mntpt.c | 44 |
4 files changed, 19 insertions, 30 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index e6a4ab980e31..20c106f24927 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -66,6 +66,7 @@ const struct dentry_operations afs_fs_dentry_operations = { | |||
66 | .d_revalidate = afs_d_revalidate, | 66 | .d_revalidate = afs_d_revalidate, |
67 | .d_delete = afs_d_delete, | 67 | .d_delete = afs_d_delete, |
68 | .d_release = afs_d_release, | 68 | .d_release = afs_d_release, |
69 | .d_automount = afs_d_automount, | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | #define AFS_DIR_HASHTBL_SIZE 128 | 72 | #define AFS_DIR_HASHTBL_SIZE 128 |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 0747339011c3..db66c5201474 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
@@ -184,7 +184,8 @@ struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name, | |||
184 | inode->i_generation = 0; | 184 | inode->i_generation = 0; |
185 | 185 | ||
186 | set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags); | 186 | set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags); |
187 | inode->i_flags |= S_NOATIME; | 187 | set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); |
188 | inode->i_flags |= S_AUTOMOUNT | S_NOATIME; | ||
188 | unlock_new_inode(inode); | 189 | unlock_new_inode(inode); |
189 | _leave(" = %p", inode); | 190 | _leave(" = %p", inode); |
190 | return inode; | 191 | return inode; |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 58c633b80246..5a9b6843bac1 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -592,6 +592,7 @@ extern const struct inode_operations afs_mntpt_inode_operations; | |||
592 | extern const struct inode_operations afs_autocell_inode_operations; | 592 | extern const struct inode_operations afs_autocell_inode_operations; |
593 | extern const struct file_operations afs_mntpt_file_operations; | 593 | extern const struct file_operations afs_mntpt_file_operations; |
594 | 594 | ||
595 | extern struct vfsmount *afs_d_automount(struct path *); | ||
595 | extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); | 596 | extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); |
596 | extern void afs_mntpt_kill_timer(void); | 597 | extern void afs_mntpt_kill_timer(void); |
597 | 598 | ||
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index f3e891d57a2c..d23b2e344a78 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,49 +236,37 @@ 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; | 244 | int err; |
247 | 245 | ||
248 | _enter("%p{%s},{%s:%p{%s},}", | 246 | _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 | 247 | ||
258 | newmnt = afs_mntpt_do_automount(nd->path.dentry); | 248 | newmnt = afs_mntpt_do_automount(path->dentry); |
259 | if (IS_ERR(newmnt)) { | 249 | if (IS_ERR(newmnt)) |
260 | path_put(&nd->path); | 250 | return newmnt; |
261 | return (void *)newmnt; | ||
262 | } | ||
263 | 251 | ||
264 | mntget(newmnt); | 252 | mntget(newmnt); |
265 | err = do_add_mount(newmnt, &nd->path, MNT_SHRINKABLE, &afs_vfsmounts); | 253 | err = do_add_mount(newmnt, path, MNT_SHRINKABLE, &afs_vfsmounts); |
266 | switch (err) { | 254 | switch (err) { |
267 | case 0: | 255 | 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, | 256 | queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer, |
272 | afs_mntpt_expiry_timeout * HZ); | 257 | afs_mntpt_expiry_timeout * HZ); |
273 | break; | 258 | _leave(" = %p {%s}", newmnt, newmnt->mnt_devname); |
259 | return newmnt; | ||
274 | case -EBUSY: | 260 | case -EBUSY: |
275 | /* someone else made a mount here whilst we were busy */ | 261 | /* someone else made a mount here whilst we were busy */ |
276 | err = follow_down(&nd->path, false); | 262 | mntput(newmnt); |
263 | _leave(" = NULL [EBUSY]"); | ||
264 | return NULL; | ||
277 | default: | 265 | default: |
278 | mntput(newmnt); | 266 | mntput(newmnt); |
279 | break; | 267 | _leave(" = %d", err); |
268 | return ERR_PTR(err); | ||
280 | } | 269 | } |
281 | |||
282 | _leave(" = %d", err); | ||
283 | return ERR_PTR(err); | ||
284 | } | 270 | } |
285 | 271 | ||
286 | /* | 272 | /* |