diff options
| author | Tejun Heo <tj@kernel.org> | 2010-02-02 14:38:15 +0900 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2010-02-02 14:38:15 +0900 |
| commit | ab386128f20c44c458a90039ab1bdc265ac474c9 (patch) | |
| tree | 2ad188744922b1bb951fd10ff50dc04c83acce22 /fs/namei.c | |
| parent | dbfc196a3cc1a2514ad0737a82f764de23bd65e6 (diff) | |
| parent | ab658321f32770b903a4426e2a6fae0392757755 (diff) | |
| download | net-ab386128f20c44c458a90039ab1bdc265ac474c9.tar.gz | |
Merge branch 'master' into percpu
Diffstat (limited to 'fs/namei.c')
| -rw-r--r-- | fs/namei.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/fs/namei.c b/fs/namei.c index b55440baf7ab83..94a5e60779f917 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -561,6 +561,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata dget(dentry); } mntget(path->mnt); + nd->last_type = LAST_BIND; cookie = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(cookie); if (!IS_ERR(cookie)) { @@ -1603,11 +1604,12 @@ struct file *do_filp_open(int dfd, const char *pathname, struct file *filp; struct nameidata nd; int error; - struct path path, save; + struct path path; struct dentry *dir; int count = 0; int will_truncate; int flag = open_to_namei_flags(open_flag); + int force_reval = 0; /* * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only @@ -1619,7 +1621,7 @@ struct file *do_filp_open(int dfd, const char *pathname, open_flag |= O_DSYNC; if (!acc_mode) - acc_mode = MAY_OPEN | ACC_MODE(flag); + acc_mode = MAY_OPEN | ACC_MODE(open_flag); /* O_TRUNC implies we need access checks for write permissions */ if (flag & O_TRUNC) @@ -1659,9 +1661,12 @@ struct file *do_filp_open(int dfd, const char *pathname, /* * Create - we need to know the parent. */ +reval: error = path_init(dfd, pathname, LOOKUP_PARENT, &nd); if (error) return ERR_PTR(error); + if (force_reval) + nd.flags |= LOOKUP_REVAL; error = path_walk(pathname, &nd); if (error) { if (nd.root.mnt) @@ -1853,17 +1858,7 @@ do_link: error = security_inode_follow_link(path.dentry, &nd); if (error) goto exit_dput; - save = nd.path; - path_get(&save); error = __do_follow_link(&path, &nd); - if (error == -ESTALE) { - /* nd.path had been dropped */ - nd.path = save; - path_get(&nd.path); - nd.flags |= LOOKUP_REVAL; - error = __do_follow_link(&path, &nd); - } - path_put(&save); path_put(&path); if (error) { /* Does someone understand code flow here? Or it is only @@ -1873,6 +1868,10 @@ do_link: release_open_intent(&nd); if (nd.root.mnt) path_put(&nd.root); + if (error == -ESTALE && !force_reval) { + force_reval = 1; + goto reval; + } return ERR_PTR(error); } nd.flags &= ~LOOKUP_PARENT; |
