X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=fs%2Fnamei.c;h=12ed29712b4e03cfad6cc53cc1bdc09413f34a21;hb=b6183df7b294997a748eeb9991daa126986ead12;hp=7d694194024ac4d2459e7cc3d60014bdff64e3ba;hpb=f5e7e844a571124ffc117d4696787d6afc4fc5ae;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git diff --git a/fs/namei.c b/fs/namei.c index 7d69419..12ed297 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -605,7 +605,7 @@ static inline void path_to_nameidata(const struct path *path, static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) { struct inode *inode = link->dentry->d_inode; - if (!IS_ERR(cookie) && inode->i_op->put_link) + if (inode->i_op->put_link) inode->i_op->put_link(link->dentry, nd, cookie); path_put(link); } @@ -613,19 +613,19 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki static __always_inline int follow_link(struct path *link, struct nameidata *nd, void **p) { - int error; struct dentry *dentry = link->dentry; + int error; + char *s; BUG_ON(nd->flags & LOOKUP_RCU); if (link->mnt == nd->path.mnt) mntget(link->mnt); - if (unlikely(current->total_link_count >= 40)) { - *p = ERR_PTR(-ELOOP); /* no ->put_link(), please */ - path_put(&nd->path); - return -ELOOP; - } + error = -ELOOP; + if (unlikely(current->total_link_count >= 40)) + goto out_put_nd_path; + cond_resched(); current->total_link_count++; @@ -633,30 +633,37 @@ follow_link(struct path *link, struct nameidata *nd, void **p) nd_set_link(nd, NULL); error = security_inode_follow_link(link->dentry, nd); - if (error) { - *p = ERR_PTR(error); /* no ->put_link(), please */ - path_put(&nd->path); - return error; - } + if (error) + goto out_put_nd_path; nd->last_type = LAST_BIND; *p = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(*p); - if (!IS_ERR(*p)) { - char *s = nd_get_link(nd); - error = 0; - if (s) - error = __vfs_follow_link(nd, s); - else if (nd->last_type == LAST_BIND) { - nd->flags |= LOOKUP_JUMPED; - nd->inode = nd->path.dentry->d_inode; - if (nd->inode->i_op->follow_link) { - /* stepped on a _really_ weird one */ - path_put(&nd->path); - error = -ELOOP; - } + if (IS_ERR(*p)) + goto out_put_link; + + error = 0; + s = nd_get_link(nd); + if (s) { + error = __vfs_follow_link(nd, s); + } else if (nd->last_type == LAST_BIND) { + nd->flags |= LOOKUP_JUMPED; + nd->inode = nd->path.dentry->d_inode; + if (nd->inode->i_op->follow_link) { + /* stepped on a _really_ weird one */ + path_put(&nd->path); + error = -ELOOP; } } + if (unlikely(error)) + put_link(nd, link, *p); + + return error; + +out_put_nd_path: + path_put(&nd->path); +out_put_link: + path_put(link); return error; } @@ -1383,9 +1390,10 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) void *cookie; res = follow_link(&link, nd, &cookie); - if (!res) - res = walk_component(nd, path, &nd->last, - nd->last_type, LOOKUP_FOLLOW); + if (res) + break; + res = walk_component(nd, path, &nd->last, + nd->last_type, LOOKUP_FOLLOW); put_link(nd, &link, cookie); } while (res > 0); @@ -1777,8 +1785,9 @@ static int path_lookupat(int dfd, const char *name, struct path link = path; nd->flags |= LOOKUP_PARENT; err = follow_link(&link, nd, &cookie); - if (!err) - err = lookup_last(nd, &path); + if (err) + break; + err = lookup_last(nd, &path); put_link(nd, &link, cookie); } } @@ -2245,29 +2254,43 @@ static struct file *do_last(struct nameidata *nd, struct path *path, if (error < 0) goto exit; - error = lookup_slow(nd, &nd->last, path); - if (error < 0) + BUG_ON(nd->inode != dir->d_inode); + + mutex_lock(&dir->d_inode->i_mutex); + dentry = __lookup_hash(&nd->last, dir, nd); + mutex_unlock(&dir->d_inode->i_mutex); + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) goto exit; + path->mnt = nd->path.mnt; + path->dentry = dentry; + error = follow_managed(path, nd->flags); + if (unlikely(error < 0)) + goto exit_dput; + + if (error) + nd->flags |= LOOKUP_JUMPED; inode = path->dentry->d_inode; } goto finish_lookup; - } - - /* create side of things */ - /* - * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED has been - * cleared when we got to the last component we are about to look up - */ - error = complete_walk(nd); - if (error) - return ERR_PTR(error); + } else { + /* create side of things */ + /* + * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED + * has been cleared when we got to the last component we are + * about to look up + */ + error = complete_walk(nd); + if (error) + return ERR_PTR(error); - audit_inode(pathname, dir); - error = -EISDIR; - /* trailing slashes? */ - if (nd->last.name[nd->last.len]) - goto exit; + audit_inode(pathname, dir); + error = -EISDIR; + /* trailing slashes? */ + if (nd->last.name[nd->last.len]) + goto exit; + } retry_lookup: mutex_lock(&dir->d_inode->i_mutex); @@ -2283,7 +2306,7 @@ retry_lookup: path->mnt = nd->path.mnt; /* Negative dentry, just create the file */ - if (!dentry->d_inode) { + if (!dentry->d_inode && (open_flag & O_CREAT)) { umode_t mode = op->mode; if (!IS_POSIXACL(dir->d_inode)) mode &= ~current_umask(); @@ -2475,9 +2498,8 @@ static struct file *path_openat(int dfd, const char *pathname, nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); error = follow_link(&link, nd, &cookie); if (unlikely(error)) - filp = ERR_PTR(error); - else - filp = do_last(nd, &path, op, pathname); + goto out_filp; + filp = do_last(nd, &path, op, pathname); put_link(nd, &link, cookie); } out: