aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-02-05 02:28:01 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-05 14:06:53 -0500
commitf55eab822b93864ef4eef3bd7eadac2a727c914b (patch)
treeab5103610ecc7699a7307c157c517f2ad790e3a7
parent4484ebf12bdb0ebcdc6e8951243cbab3d7f6f4c1 (diff)
[PATCH] VFS: Ensure LOOKUP_CONTINUE flag is preserved by link_path_walk()
When walking a path, the LOOKUP_CONTINUE flag is used by some filesystems (for instance NFS) in order to determine whether or not it is looking up the last component of the path. It this is the case, it may have to look at the intent information in order to perform various tasks such as atomic open. A problem currently occurs when link_path_walk() hits a symlink. In this case LOOKUP_CONTINUE may be cleared prematurely when we hit the end of the path passed by __vfs_follow_link() (i.e. the end of the symlink path) rather than when we hit the end of the path passed by the user. The solution is to have link_path_walk() clear LOOKUP_CONTINUE if and only if that flag was unset when we entered the function. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: Al Viro <viro@ftp.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/namei.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 7ac9fb4acb2c..b760e1e18b48 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -790,7 +790,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
790 790
791 inode = nd->dentry->d_inode; 791 inode = nd->dentry->d_inode;
792 if (nd->depth) 792 if (nd->depth)
793 lookup_flags = LOOKUP_FOLLOW; 793 lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE);
794 794
795 /* At this point we know we have a real path component. */ 795 /* At this point we know we have a real path component. */
796 for(;;) { 796 for(;;) {
@@ -885,7 +885,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
885last_with_slashes: 885last_with_slashes:
886 lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; 886 lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
887last_component: 887last_component:
888 nd->flags &= ~LOOKUP_CONTINUE; 888 /* Clear LOOKUP_CONTINUE iff it was previously unset */
889 nd->flags &= lookup_flags | ~LOOKUP_CONTINUE;
889 if (lookup_flags & LOOKUP_PARENT) 890 if (lookup_flags & LOOKUP_PARENT)
890 goto lookup_parent; 891 goto lookup_parent;
891 if (this.name[0] == '.') switch (this.len) { 892 if (this.name[0] == '.') switch (this.len) {