Commit 2675a4eb authored by Al Viro's avatar Al Viro

fs/namei.c: get do_last() and friends return int

Same conventions as for ->atomic_open().  Trimmed the
forest of labels a bit, while we are at it...
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 30d90494
...@@ -2193,18 +2193,17 @@ static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode) ...@@ -2193,18 +2193,17 @@ static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode)
return security_inode_create(dir->dentry->d_inode, dentry, mode); return security_inode_create(dir->dentry->d_inode, dentry, mode);
} }
static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, static int atomic_open(struct nameidata *nd, struct dentry *dentry,
struct path *path, struct file *file, struct path *path, struct file *file,
const struct open_flags *op, const struct open_flags *op,
bool *want_write, bool need_lookup, bool *want_write, bool need_lookup,
int *opened) int *opened)
{ {
struct inode *dir = nd->path.dentry->d_inode; struct inode *dir = nd->path.dentry->d_inode;
unsigned open_flag = open_to_namei_flags(op->open_flag); unsigned open_flag = open_to_namei_flags(op->open_flag);
umode_t mode; umode_t mode;
int error; int error;
int acc_mode; int acc_mode;
struct file *filp = NULL;
int create_error = 0; int create_error = 0;
struct dentry *const DENTRY_NOT_SET = (void *) -1UL; struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
...@@ -2212,7 +2211,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2212,7 +2211,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
/* Don't create child dentry for a dead directory. */ /* Don't create child dentry for a dead directory. */
if (unlikely(IS_DEADDIR(dir))) { if (unlikely(IS_DEADDIR(dir))) {
filp = ERR_PTR(-ENOENT); error = -ENOENT;
goto out; goto out;
} }
...@@ -2276,7 +2275,6 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2276,7 +2275,6 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
if (error < 0) { if (error < 0) {
if (create_error && error == -ENOENT) if (create_error && error == -ENOENT)
error = create_error; error = create_error;
filp = ERR_PTR(error);
goto out; goto out;
} }
...@@ -2288,7 +2286,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2288,7 +2286,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
if (error) { /* returned 1, that is */ if (error) { /* returned 1, that is */
if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) { if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
filp = ERR_PTR(-EIO); error = -EIO;
goto out; goto out;
} }
if (file->f_path.dentry) { if (file->f_path.dentry) {
...@@ -2302,27 +2300,24 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2302,27 +2300,24 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
* We didn't have the inode before the open, so check open permission * We didn't have the inode before the open, so check open permission
* here. * here.
*/ */
filp = file; error = may_open(&file->f_path, acc_mode, open_flag);
error = may_open(&filp->f_path, acc_mode, open_flag); if (error)
if (error) { fput(file);
fput(filp);
filp = ERR_PTR(error);
}
out: out:
dput(dentry); dput(dentry);
return filp; return error;
no_open: no_open:
if (need_lookup) { if (need_lookup) {
dentry = lookup_real(dir, dentry, nd); dentry = lookup_real(dir, dentry, nd);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return ERR_CAST(dentry); return PTR_ERR(dentry);
if (create_error) { if (create_error) {
int open_flag = op->open_flag; int open_flag = op->open_flag;
filp = ERR_PTR(create_error); error = create_error;
if ((open_flag & O_EXCL)) { if ((open_flag & O_EXCL)) {
if (!dentry->d_inode) if (!dentry->d_inode)
goto out; goto out;
...@@ -2338,7 +2333,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2338,7 +2333,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
looked_up: looked_up:
path->dentry = dentry; path->dentry = dentry;
path->mnt = nd->path.mnt; path->mnt = nd->path.mnt;
return NULL; return 1;
} }
/* /*
...@@ -2349,10 +2344,10 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2349,10 +2344,10 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
* Returns open file or NULL on success, error otherwise. NULL means no open * Returns open file or NULL on success, error otherwise. NULL means no open
* was performed, only lookup. * was performed, only lookup.
*/ */
static struct file *lookup_open(struct nameidata *nd, struct path *path, static int lookup_open(struct nameidata *nd, struct path *path,
struct file *file, struct file *file,
const struct open_flags *op, const struct open_flags *op,
bool *want_write, int *opened) bool *want_write, int *opened)
{ {
struct dentry *dir = nd->path.dentry; struct dentry *dir = nd->path.dentry;
struct inode *dir_inode = dir->d_inode; struct inode *dir_inode = dir->d_inode;
...@@ -2363,7 +2358,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path, ...@@ -2363,7 +2358,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
*opened &= ~FILE_CREATED; *opened &= ~FILE_CREATED;
dentry = lookup_dcache(&nd->last, dir, nd, &need_lookup); dentry = lookup_dcache(&nd->last, dir, nd, &need_lookup);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return ERR_CAST(dentry); return PTR_ERR(dentry);
/* Cached positive dentry: will open in f_op->open */ /* Cached positive dentry: will open in f_op->open */
if (!need_lookup && dentry->d_inode) if (!need_lookup && dentry->d_inode)
...@@ -2379,7 +2374,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path, ...@@ -2379,7 +2374,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
dentry = lookup_real(dir_inode, dentry, nd); dentry = lookup_real(dir_inode, dentry, nd);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return ERR_CAST(dentry); return PTR_ERR(dentry);
} }
/* Negative dentry, just create the file */ /* Negative dentry, just create the file */
...@@ -2409,26 +2404,25 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path, ...@@ -2409,26 +2404,25 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
out_no_open: out_no_open:
path->dentry = dentry; path->dentry = dentry;
path->mnt = nd->path.mnt; path->mnt = nd->path.mnt;
return NULL; return 1;
out_dput: out_dput:
dput(dentry); dput(dentry);
return ERR_PTR(error); return error;
} }
/* /*
* Handle the last step of open() * Handle the last step of open()
*/ */
static struct file *do_last(struct nameidata *nd, struct path *path, static int do_last(struct nameidata *nd, struct path *path,
struct file *file, const struct open_flags *op, struct file *file, const struct open_flags *op,
int *opened, const char *pathname) int *opened, const char *pathname)
{ {
struct dentry *dir = nd->path.dentry; struct dentry *dir = nd->path.dentry;
int open_flag = op->open_flag; int open_flag = op->open_flag;
bool will_truncate = (open_flag & O_TRUNC) != 0; bool will_truncate = (open_flag & O_TRUNC) != 0;
bool want_write = false; bool want_write = false;
int acc_mode = op->acc_mode; int acc_mode = op->acc_mode;
struct file *filp;
struct inode *inode; struct inode *inode;
bool symlink_ok = false; bool symlink_ok = false;
struct path save_parent = { .dentry = NULL, .mnt = NULL }; struct path save_parent = { .dentry = NULL, .mnt = NULL };
...@@ -2443,22 +2437,22 @@ static struct file *do_last(struct nameidata *nd, struct path *path, ...@@ -2443,22 +2437,22 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
case LAST_DOT: case LAST_DOT:
error = handle_dots(nd, nd->last_type); error = handle_dots(nd, nd->last_type);
if (error) if (error)
return ERR_PTR(error); return error;
/* fallthrough */ /* fallthrough */
case LAST_ROOT: case LAST_ROOT:
error = complete_walk(nd); error = complete_walk(nd);
if (error) if (error)
return ERR_PTR(error); return error;
audit_inode(pathname, nd->path.dentry); audit_inode(pathname, nd->path.dentry);
if (open_flag & O_CREAT) { if (open_flag & O_CREAT) {
error = -EISDIR; error = -EISDIR;
goto exit; goto out;
} }
goto finish_open; goto finish_open;
case LAST_BIND: case LAST_BIND:
error = complete_walk(nd); error = complete_walk(nd);
if (error) if (error)
return ERR_PTR(error); return error;
audit_inode(pathname, dir); audit_inode(pathname, dir);
goto finish_open; goto finish_open;
} }
...@@ -2474,7 +2468,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, ...@@ -2474,7 +2468,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
goto finish_lookup; goto finish_lookup;
if (error < 0) if (error < 0)
goto exit; goto out;
BUG_ON(nd->inode != dir->d_inode); BUG_ON(nd->inode != dir->d_inode);
} else { } else {
...@@ -2486,29 +2480,29 @@ static struct file *do_last(struct nameidata *nd, struct path *path, ...@@ -2486,29 +2480,29 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
*/ */
error = complete_walk(nd); error = complete_walk(nd);
if (error) if (error)
return ERR_PTR(error); return error;
audit_inode(pathname, dir); audit_inode(pathname, dir);
error = -EISDIR; error = -EISDIR;
/* trailing slashes? */ /* trailing slashes? */
if (nd->last.name[nd->last.len]) if (nd->last.name[nd->last.len])
goto exit; goto out;
} }
retry_lookup: retry_lookup:
mutex_lock(&dir->d_inode->i_mutex); mutex_lock(&dir->d_inode->i_mutex);
filp = lookup_open(nd, path, file, op, &want_write, opened); error = lookup_open(nd, path, file, op, &want_write, opened);
mutex_unlock(&dir->d_inode->i_mutex); mutex_unlock(&dir->d_inode->i_mutex);
if (filp) { if (error <= 0) {
if (IS_ERR(filp)) if (error)
goto out; goto out;
if ((*opened & FILE_CREATED) || if ((*opened & FILE_CREATED) ||
!S_ISREG(filp->f_path.dentry->d_inode->i_mode)) !S_ISREG(file->f_path.dentry->d_inode->i_mode))
will_truncate = false; will_truncate = false;
audit_inode(pathname, filp->f_path.dentry); audit_inode(pathname, file->f_path.dentry);
goto opened; goto opened;
} }
...@@ -2554,18 +2548,18 @@ static struct file *do_last(struct nameidata *nd, struct path *path, ...@@ -2554,18 +2548,18 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
error = -ENOENT; error = -ENOENT;
if (!inode) { if (!inode) {
path_to_nameidata(path, nd); path_to_nameidata(path, nd);
goto exit; goto out;
} }
if (should_follow_link(inode, !symlink_ok)) { if (should_follow_link(inode, !symlink_ok)) {
if (nd->flags & LOOKUP_RCU) { if (nd->flags & LOOKUP_RCU) {
if (unlikely(unlazy_walk(nd, path->dentry))) { if (unlikely(unlazy_walk(nd, path->dentry))) {
error = -ECHILD; error = -ECHILD;
goto exit; goto out;
} }
} }
BUG_ON(inode != path->dentry->d_inode); BUG_ON(inode != path->dentry->d_inode);
return NULL; return 1;
} }
if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) { if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
...@@ -2581,14 +2575,14 @@ static struct file *do_last(struct nameidata *nd, struct path *path, ...@@ -2581,14 +2575,14 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
error = complete_walk(nd); error = complete_walk(nd);
if (error) { if (error) {
path_put(&save_parent); path_put(&save_parent);
return ERR_PTR(error); return error;
} }
error = -EISDIR; error = -EISDIR;
if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
goto exit; goto out;
error = -ENOTDIR; error = -ENOTDIR;
if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
goto exit; goto out;
audit_inode(pathname, nd->path.dentry); audit_inode(pathname, nd->path.dentry);
finish_open: finish_open:
if (!S_ISREG(nd->inode->i_mode)) if (!S_ISREG(nd->inode->i_mode))
...@@ -2597,32 +2591,30 @@ static struct file *do_last(struct nameidata *nd, struct path *path, ...@@ -2597,32 +2591,30 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (will_truncate) { if (will_truncate) {
error = mnt_want_write(nd->path.mnt); error = mnt_want_write(nd->path.mnt);
if (error) if (error)
goto exit; goto out;
want_write = true; want_write = true;
} }
finish_open_created: finish_open_created:
error = may_open(&nd->path, acc_mode, open_flag); error = may_open(&nd->path, acc_mode, open_flag);
if (error) if (error)
goto exit; goto out;
file->f_path.mnt = nd->path.mnt; file->f_path.mnt = nd->path.mnt;
error = finish_open(file, nd->path.dentry, NULL, opened); error = finish_open(file, nd->path.dentry, NULL, opened);
if (error) { if (error) {
filp = ERR_PTR(error);
if (error == -EOPENSTALE) if (error == -EOPENSTALE)
goto stale_open; goto stale_open;
goto out; goto out;
} }
filp = file;
opened: opened:
error = open_check_o_direct(filp); error = open_check_o_direct(file);
if (error) if (error)
goto exit_fput; goto exit_fput;
error = ima_file_check(filp, op->acc_mode); error = ima_file_check(file, op->acc_mode);
if (error) if (error)
goto exit_fput; goto exit_fput;
if (will_truncate) { if (will_truncate) {
error = handle_truncate(filp); error = handle_truncate(file);
if (error) if (error)
goto exit_fput; goto exit_fput;
} }
...@@ -2631,16 +2623,14 @@ static struct file *do_last(struct nameidata *nd, struct path *path, ...@@ -2631,16 +2623,14 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
mnt_drop_write(nd->path.mnt); mnt_drop_write(nd->path.mnt);
path_put(&save_parent); path_put(&save_parent);
terminate_walk(nd); terminate_walk(nd);
return filp; return error;
exit_dput: exit_dput:
path_put_conditional(path, nd); path_put_conditional(path, nd);
exit:
filp = ERR_PTR(error);
goto out; goto out;
exit_fput: exit_fput:
fput(filp); fput(file);
goto exit; goto out;
stale_open: stale_open:
/* If no saved parent or already retried then can't retry */ /* If no saved parent or already retried then can't retry */
...@@ -2666,7 +2656,6 @@ static struct file *path_openat(int dfd, const char *pathname, ...@@ -2666,7 +2656,6 @@ static struct file *path_openat(int dfd, const char *pathname,
{ {
struct file *base = NULL; struct file *base = NULL;
struct file *file; struct file *file;
struct file *res;
struct path path; struct path path;
int opened = 0; int opened = 0;
int error; int error;
...@@ -2679,29 +2668,29 @@ static struct file *path_openat(int dfd, const char *pathname, ...@@ -2679,29 +2668,29 @@ static struct file *path_openat(int dfd, const char *pathname,
error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base); error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
if (unlikely(error)) if (unlikely(error))
goto out_filp; goto out;
current->total_link_count = 0; current->total_link_count = 0;
error = link_path_walk(pathname, nd); error = link_path_walk(pathname, nd);
if (unlikely(error)) if (unlikely(error))
goto out_filp; goto out;
res = do_last(nd, &path, file, op, &opened, pathname); error = do_last(nd, &path, file, op, &opened, pathname);
while (unlikely(!res)) { /* trailing symlink */ while (unlikely(error > 0)) { /* trailing symlink */
struct path link = path; struct path link = path;
void *cookie; void *cookie;
if (!(nd->flags & LOOKUP_FOLLOW)) { if (!(nd->flags & LOOKUP_FOLLOW)) {
path_put_conditional(&path, nd); path_put_conditional(&path, nd);
path_put(&nd->path); path_put(&nd->path);
res = ERR_PTR(-ELOOP); error = -ELOOP;
break; break;
} }
nd->flags |= LOOKUP_PARENT; nd->flags |= LOOKUP_PARENT;
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
error = follow_link(&link, nd, &cookie); error = follow_link(&link, nd, &cookie);
if (unlikely(error)) if (unlikely(error))
goto out_filp; break;
res = do_last(nd, &path, file, op, &opened, pathname); error = do_last(nd, &path, file, op, &opened, pathname);
put_link(nd, &link, cookie); put_link(nd, &link, cookie);
} }
out: out:
...@@ -2709,19 +2698,20 @@ static struct file *path_openat(int dfd, const char *pathname, ...@@ -2709,19 +2698,20 @@ static struct file *path_openat(int dfd, const char *pathname,
path_put(&nd->root); path_put(&nd->root);
if (base) if (base)
fput(base); fput(base);
if (!(opened & FILE_OPENED)) if (!(opened & FILE_OPENED)) {
BUG_ON(!error);
put_filp(file); put_filp(file);
if (res == ERR_PTR(-EOPENSTALE)) {
if (flags & LOOKUP_RCU)
res = ERR_PTR(-ECHILD);
else
res = ERR_PTR(-ESTALE);
} }
return res; if (unlikely(error)) {
if (error == -EOPENSTALE) {
out_filp: if (flags & LOOKUP_RCU)
res = ERR_PTR(error); error = -ECHILD;
goto out; else
error = -ESTALE;
}
file = ERR_PTR(error);
}
return file;
} }
struct file *do_filp_open(int dfd, const char *pathname, struct file *do_filp_open(int dfd, const char *pathname,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment