mark struct file that had write access grabbed by open()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 14 Mar 2014 16:02:47 +0000 (12:02 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 2 Apr 2014 03:19:12 +0000 (23:19 -0400)
new flag in ->f_mode - FMODE_WRITER.  Set by do_dentry_open() in case
when it has grabbed write access, checked by __fput() to decide whether
it wants to drop the sucker.  Allows to stop bothering with mnt_clone_write()
in alloc_file(), along with fewer special_file() checks.

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

index ee20658..ce1504f 100644 (file)
@@ -177,43 +177,12 @@ struct file *alloc_file(struct path *path, fmode_t mode,
        file->f_mapping = path->dentry->d_inode->i_mapping;
        file->f_mode = mode;
        file->f_op = fop;
-
-       /*
-        * These mounts don't really matter in practice
-        * for r/o bind mounts.  They aren't userspace-
-        * visible.  We do this for consistency, and so
-        * that we can do debugging checks at __fput()
-        */
-       if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) {
-               WARN_ON(mnt_clone_write(path->mnt));
-       }
        if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
                i_readcount_inc(path->dentry->d_inode);
        return file;
 }
 EXPORT_SYMBOL(alloc_file);
 
-/**
- * drop_file_write_access - give up ability to write to a file
- * @file: the file to which we will stop writing
- *
- * This is a central place which will give up the ability
- * to write to @file, along with access to write through
- * its vfsmount.
- */
-static void drop_file_write_access(struct file *file)
-{
-       struct vfsmount *mnt = file->f_path.mnt;
-       struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
-
-       if (special_file(inode->i_mode))
-               return;
-
-       put_write_access(inode);
-       __mnt_drop_write(mnt);
-}
-
 /* the real guts of fput() - releasing the last reference to file
  */
 static void __fput(struct file *file)
@@ -248,8 +217,10 @@ static void __fput(struct file *file)
        put_pid(file->f_owner.pid);
        if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
                i_readcount_dec(inode);
-       if (file->f_mode & FMODE_WRITE)
-               drop_file_write_access(file);
+       if (file->f_mode & FMODE_WRITER) {
+               put_write_access(inode);
+               __mnt_drop_write(mnt);
+       }
        file->f_path.dentry = NULL;
        file->f_path.mnt = NULL;
        file->f_inode = NULL;
index a66aff5..20e8696 100644 (file)
@@ -414,9 +414,7 @@ EXPORT_SYMBOL_GPL(mnt_clone_write);
  */
 int __mnt_want_write_file(struct file *file)
 {
-       struct inode *inode = file_inode(file);
-
-       if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode))
+       if (!(file->f_mode & FMODE_WRITER))
                return __mnt_want_write(file->f_path.mnt);
        else
                return mnt_clone_write(file->f_path.mnt);
index ebef0c5..dcefb2f 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -670,6 +670,7 @@ static int do_dentry_open(struct file *f,
                        put_write_access(inode);
                        goto cleanup_file;
                }
+               f->f_mode |= FMODE_WRITER;
        }
 
        f->f_mapping = inode->i_mapping;
@@ -715,11 +716,9 @@ static int do_dentry_open(struct file *f,
 
 cleanup_all:
        fops_put(f->f_op);
-       if (f->f_mode & FMODE_WRITE) {
-               if (!special_file(inode->i_mode)) {
-                       put_write_access(inode);
-                       __mnt_drop_write(f->f_path.mnt);
-               }
+       if (f->f_mode & FMODE_WRITER) {
+               put_write_access(inode);
+               __mnt_drop_write(f->f_path.mnt);
        }
 cleanup_file:
        path_put(&f->f_path);
index e80659e..d9d88a0 100644 (file)
@@ -125,6 +125,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 
 /* File needs atomic accesses to f_pos */
 #define FMODE_ATOMIC_POS       ((__force fmode_t)0x8000)
+/* Write access to underlying fs */
+#define FMODE_WRITER           ((__force fmode_t)0x10000)
 
 /* File was opened by fanotify and shouldn't generate fanotify events */
 #define FMODE_NONOTIFY         ((__force fmode_t)0x1000000)