propagate error from get_empty_filp() to its callers
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 15 Feb 2013 01:41:04 +0000 (20:41 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 23 Feb 2013 04:31:32 +0000 (23:31 -0500)
Based on parts from Anatol's patch (the rest is the next commit).

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/file_table.c
fs/namei.c
fs/open.c

index 0f607ce89acc43f5cebc1b025ffe45a8a5e352b2..cd76d4fdf4a497c5653267affd1e79bff250c791 100644 (file)
@@ -94,8 +94,8 @@ int proc_nr_files(ctl_table *table, int write,
 #endif
 
 /* Find an unused file structure and return a pointer to it.
- * Returns NULL, if there are no more free file structures or
- * we run out of memory.
+ * Returns an error pointer if some error happend e.g. we over file
+ * structures limit, run out of memory or operation is not permitted.
  *
  * Be very careful using this.  You are responsible for
  * getting write access to any mount that you might assign
@@ -107,7 +107,8 @@ struct file *get_empty_filp(void)
 {
        const struct cred *cred = current_cred();
        static long old_max;
-       struct file * f;
+       struct file *f;
+       int error;
 
        /*
         * Privileged users can go above max_files
@@ -122,13 +123,16 @@ struct file *get_empty_filp(void)
        }
 
        f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL);
-       if (f == NULL)
-               goto fail;
+       if (unlikely(!f))
+               return ERR_PTR(-ENOMEM);
 
        percpu_counter_inc(&nr_files);
        f->f_cred = get_cred(cred);
-       if (security_file_alloc(f))
-               goto fail_sec;
+       error = security_file_alloc(f);
+       if (unlikely(error)) {
+               file_free(f);
+               return ERR_PTR(error);
+       }
 
        INIT_LIST_HEAD(&f->f_u.fu_list);
        atomic_long_set(&f->f_count, 1);
@@ -144,12 +148,7 @@ over:
                pr_info("VFS: file-max limit %lu reached\n", get_max_files());
                old_max = get_nr_files();
        }
-       goto fail;
-
-fail_sec:
-       file_free(f);
-fail:
-       return NULL;
+       return ERR_PTR(-ENFILE);
 }
 
 /**
@@ -173,7 +172,7 @@ struct file *alloc_file(struct path *path, fmode_t mode,
        struct file *file;
 
        file = get_empty_filp();
-       if (!file)
+       if (IS_ERR(file))
                return NULL;
 
        file->f_path = *path;
index df00b754631d43faf39fdedc17dc5f8d0fe733b4..e0a33f598cdf18e651d29d82939f6243bef38036 100644 (file)
@@ -2941,8 +2941,8 @@ static struct file *path_openat(int dfd, struct filename *pathname,
        int error;
 
        file = get_empty_filp();
-       if (!file)
-               return ERR_PTR(-ENFILE);
+       if (IS_ERR(file))
+               return file;
 
        file->f_flags = op->open_flag;
 
index e08643feb57402b7cdb8e05997739e7652c82dec..97a237f67b7215a0f5fe44847a930a282da6175f 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -810,23 +810,22 @@ struct file *dentry_open(const struct path *path, int flags,
        /* We must always pass in a valid mount pointer. */
        BUG_ON(!path->mnt);
 
-       error = -ENFILE;
        f = get_empty_filp();
-       if (f == NULL)
-               return ERR_PTR(error);
-
-       f->f_flags = flags;
-       f->f_path = *path;
-       error = do_dentry_open(f, NULL, cred);
-       if (!error) {
-               error = open_check_o_direct(f);
-               if (error) {
-                       fput(f);
+       if (!IS_ERR(f)) {
+               f->f_flags = flags;
+               f->f_path = *path;
+               error = do_dentry_open(f, NULL, cred);
+               if (!error) {
+                       /* from now on we need fput() to dispose of f */
+                       error = open_check_o_direct(f);
+                       if (error) {
+                               fput(f);
+                               f = ERR_PTR(error);
+                       }
+               } else { 
+                       put_filp(f);
                        f = ERR_PTR(error);
                }
-       } else { 
-               put_filp(f);
-               f = ERR_PTR(error);
        }
        return f;
 }