--- linux-2.6.24.i686/fs/namei.c.org +++ linux-2.6.24.i686/fs/namei.c @@ -750,7 +750,7 @@ static __always_inline void follow_dotdo { struct fs_struct *fs = current->fs; - while(1) { + while (1) { struct vfsmount *parent; struct dentry *old = nd->path.dentry; @@ -849,7 +849,7 @@ static int __link_path_walk(const char * lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); /* At this point we know we have a real path component. */ - for(;;) { + for (;;) { unsigned long hash; struct qstr this; unsigned int c; @@ -1003,7 +1003,7 @@ return_reval: */ if (nd->path.dentry && nd->path.dentry->d_sb && (nd->path.dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) { - err = -ESTALE; + err = -ENOENT; /* Note: we do not d_invalidate() */ if (!nd->path.dentry->d_op->d_revalidate( nd->path.dentry, nd)) @@ -1015,6 +1015,8 @@ out_dput: path_put_conditional(&next, nd); break; } + if (err == -ESTALE) + d_drop(nd->path.dentry); path_put(&nd->path); return_err: return err; @@ -1031,13 +1033,24 @@ static int link_path_walk(const char *na { struct nameidata save = *nd; int result; + struct dentry *svd; /* make sure the stuff we saved doesn't go away */ dget(save.path.dentry); mntget(save.path.mnt); + svd = nd->path.dentry; result = __link_path_walk(name, nd); - if (result == -ESTALE) { + while (result == -ESTALE) { + /* + * If no progress was made looking up the pathname, + * then stop and return ENOENT instead of ESTALE. + */ + if (nd->path.dentry == svd) { + result = -ENOENT; + break; + } + svd = nd->path.dentry; *nd = save; dget(nd->path.dentry); mntget(nd->path.mnt); @@ -1714,7 +1727,10 @@ int open_namei(int dfd, const char *path int acc_mode, error; struct path path; struct dentry *dir; - int count = 0; + int count; + +top: + count = 0; acc_mode = ACC_MODE(flag); @@ -1741,7 +1757,8 @@ int open_namei(int dfd, const char *path /* * Create - we need to know the parent. */ - error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode); + error = path_lookup_create(dfd, pathname, LOOKUP_PARENT, nd, + flag, mode); if (error) return error; @@ -1814,10 +1831,17 @@ ok: return 0; exit_dput: + if (error == -ESTALE) + d_drop(path.dentry); path_put_conditional(&path, nd); exit: if (!IS_ERR(nd->intent.open.file)) release_open_intent(nd); + if (error == -ESTALE) { + d_drop(nd->path.dentry); + path_put(&nd->path); + goto top; + } path_put(&nd->path); return error; @@ -1827,7 +1851,7 @@ do_link: goto exit_dput; /* * This is subtle. Instead of calling do_follow_link() we do the - * thing by hands. The reason is that this way we have zero link_count + * thing by hand. The reason is that this way we have zero link_count * and path_walk() (called from ->follow_link) honoring LOOKUP_PARENT. * After that we have the parent and last component, i.e. * we are in the same situation as after the first path_walk(). @@ -1846,6 +1870,8 @@ do_link: * with "intent.open". */ release_open_intent(nd); + if (error == ESTALE) + goto top; return error; } nd->flags &= ~LOOKUP_PARENT; @@ -1859,7 +1885,7 @@ do_link: goto exit; } error = -ELOOP; - if (count++==32) { + if (count++ == 32) { __putname(nd->last.name); goto exit; }