aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2008-07-24 00:30:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:31 -0400
commit6d5cb926fa0162b1e62f37c117cc7ce763cfcbb9 (patch)
tree275f1154f7724c6b86c3ec9e2c36ff8f96c3e55d
parentc432c2586a0811c7d0030d78f0993568bc889a6f (diff)
autofs4: use lookup intent flags to trigger mounts
When an open(2) call is made on an autofs mount point directory that already exists and the O_DIRECTORY flag is not used the needed mount callback to the daemon is not done. This leads to the path walk continuing resulting in a callback to the daemon with an incorrect key. open(2) is called without O_DIRECTORY by the "find" utility but this should be handled properly anyway. This happens because autofs needs to use the lookup flags to decide when to callback to the daemon to perform a mount to prevent mount storms. For example, an autofs indirect mount map that has the "browse" option will have the mount point directories are pre-created and the stat(2) call made by a color ls against each directory will cause all these directories to be mounted. It is unfortunate we need to resort to this but mount maps can be quite large. Additionally, if a user manually umounts an autofs indirect mount the directory isn't removed which also leads to this situation. To resolve this autofs needs to use the lookup intent flags to enable it to make this decision. This patch adds this check and triggers a call back if any of the lookup intent flags are set as all these calls warrant a mount attempt be requested. I know that external VFS code which uses the lookup flags is something that the VFS would like to eliminate but I have no choice as I can't see any other way to do this. A VFS dentry or inode operation callback which returns the lookup "type" (requires a definition) would be sufficient. But this change is needed now and I'm not aware of the form that coming VFS changes will take so I'm not willing to propose anything along these lines. If anyone can provide an alternate method I would be happy to use it. [akpm@linux-foundation.org: fix build for concurrent VFS changes] Signed-off-by: Ian Kent <raven@themaw.net> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/autofs4/root.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 1e901e5ea013..87352654ff4e 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -31,6 +31,9 @@ static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t fil
31static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); 31static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
32static void *autofs4_follow_link(struct dentry *, struct nameidata *); 32static void *autofs4_follow_link(struct dentry *, struct nameidata *);
33 33
34#define TRIGGER_FLAGS (LOOKUP_CONTINUE | LOOKUP_DIRECTORY)
35#define TRIGGER_INTENTS (LOOKUP_OPEN | LOOKUP_CREATE)
36
34const struct file_operations autofs4_root_operations = { 37const struct file_operations autofs4_root_operations = {
35 .open = dcache_dir_open, 38 .open = dcache_dir_open,
36 .release = dcache_dir_close, 39 .release = dcache_dir_close,
@@ -291,7 +294,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
291 return status; 294 return status;
292 } 295 }
293 /* Trigger mount for path component or follow link */ 296 /* Trigger mount for path component or follow link */
294 } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || 297 } else if (flags & (TRIGGER_FLAGS | TRIGGER_INTENTS) ||
295 current->link_count) { 298 current->link_count) {
296 DPRINTK("waiting for mount name=%.*s", 299 DPRINTK("waiting for mount name=%.*s",
297 dentry->d_name.len, dentry->d_name.name); 300 dentry->d_name.len, dentry->d_name.name);
@@ -336,7 +339,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
336 nd->flags); 339 nd->flags);
337 340
338 /* If it's our master or we shouldn't trigger a mount we're done */ 341 /* If it's our master or we shouldn't trigger a mount we're done */
339 lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY); 342 lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS);
340 if (oz_mode || !lookup_type) 343 if (oz_mode || !lookup_type)
341 goto done; 344 goto done;
342 345