If open_namei() succeeds, there is potentially a mnt_want_write()
that needs to get balanced.  If the caller doesn't create a
'struct file' and eventually __fput() it, or manually drop the
write count on an error, we have a bug.

Forcing open_namei() to return a filp fixes this.  Any caller
getting a 'struct file' back must consider that filp instantiated
and fput() it normally.  The callers no longer have to worry about
ever manually releasing a mnt write count.

Signed-off-by: Dave Hansen <[EMAIL PROTECTED]>
---

 lxc-dave/fs/namei.c         |   16 ++++++++--------
 lxc-dave/fs/open.c          |    7 +------
 lxc-dave/include/linux/fs.h |    2 +-
 3 files changed, 10 insertions(+), 15 deletions(-)

diff -puN fs/namei.c~make-open_namei-return-a-filp fs/namei.c
--- lxc/fs/namei.c~make-open_namei-return-a-filp        2007-10-03 
09:01:45.000000000 -0700
+++ lxc-dave/fs/namei.c 2007-10-03 09:01:45.000000000 -0700
@@ -1728,8 +1728,8 @@ static inline int sys_open_flags_to_name
  * system call.  See sys_open_flags_to_namei_flags().
  * SMP-safe
  */
-int open_namei(int dfd, const char *pathname, int sys_open_flag,
-               int mode, struct nameidata *nd)
+struct file *open_namei(int dfd, const char *pathname, int sys_open_flag,
+                       int mode, struct nameidata *nd)
 {
        int acc_mode, error;
        struct path path;
@@ -1755,7 +1755,7 @@ int open_namei(int dfd, const char *path
                error = path_lookup_open(dfd, pathname, lookup_flags(flag),
                                         nd, flag);
                if (error)
-                       return error;
+                       return ERR_PTR(error);
                goto ok;
        }
 
@@ -1764,7 +1764,7 @@ int open_namei(int dfd, const char *path
         */
        error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
        if (error)
-               return error;
+               return ERR_PTR(error);
 
        /*
         * We have the parent and last component. First of all, check
@@ -1798,7 +1798,7 @@ do_last:
                error = __open_namei_create(nd, &path, flag, mode);
                if (error)
                        goto exit;
-               return 0;
+               return nameidata_to_filp(nd, sys_open_flag);
        }
 
        /*
@@ -1831,7 +1831,7 @@ ok:
        error = may_open(nd, acc_mode, flag);
        if (error)
                goto exit;
-       return 0;
+       return nameidata_to_filp(nd, sys_open_flag);
 
 exit_mutex_unlock:
        mutex_unlock(&dir->d_inode->i_mutex);
@@ -1841,7 +1841,7 @@ exit:
        if (!IS_ERR(nd->intent.open.file))
                release_open_intent(nd);
        path_release(nd);
-       return error;
+       return ERR_PTR(error);
 
 do_link:
        error = -ELOOP;
@@ -1868,7 +1868,7 @@ do_link:
                 * with "intent.open".
                 */
                release_open_intent(nd);
-               return error;
+               return ERR_PTR(error);
        }
        nd->flags &= ~LOOKUP_PARENT;
        if (nd->last_type == LAST_BIND)
diff -puN fs/open.c~make-open_namei-return-a-filp fs/open.c
--- lxc/fs/open.c~make-open_namei-return-a-filp 2007-10-03 09:01:45.000000000 
-0700
+++ lxc-dave/fs/open.c  2007-10-03 09:01:45.000000000 -0700
@@ -846,14 +846,9 @@ cleanup_file:
 static struct file *do_filp_open(int dfd, const char *filename, int flags,
                                 int mode)
 {
-       int error;
        struct nameidata nd;
 
-       error = open_namei(dfd, filename, flags, mode, &nd);
-       if (!error)
-               return nameidata_to_filp(&nd, flags);
-
-       return ERR_PTR(error);
+       return open_namei(dfd, filename, flags, mode, &nd);
 }
 
 struct file *filp_open(const char *filename, int flags, int mode)
diff -puN include/linux/fs.h~make-open_namei-return-a-filp include/linux/fs.h
--- lxc/include/linux/fs.h~make-open_namei-return-a-filp        2007-10-03 
09:01:45.000000000 -0700
+++ lxc-dave/include/linux/fs.h 2007-10-03 09:01:45.000000000 -0700
@@ -1721,7 +1721,7 @@ extern struct file *create_read_pipe(str
 extern struct file *create_write_pipe(void);
 extern void free_write_pipe(struct file *);
 
-extern int open_namei(int dfd, const char *, int, int, struct nameidata *);
+extern struct file *open_namei(int dfd, const char *, int, int, struct 
nameidata *);
 extern int may_open(struct nameidata *, int, int);
 
 extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to