Commit 83f936c7 authored by Al Viro's avatar Al Viro

mark struct file that had write access grabbed by open()

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 0ccb2863
...@@ -177,43 +177,12 @@ struct file *alloc_file(struct path *path, fmode_t mode, ...@@ -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_mapping = path->dentry->d_inode->i_mapping;
file->f_mode = mode; file->f_mode = mode;
file->f_op = fop; 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) if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
i_readcount_inc(path->dentry->d_inode); i_readcount_inc(path->dentry->d_inode);
return file; return file;
} }
EXPORT_SYMBOL(alloc_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 /* the real guts of fput() - releasing the last reference to file
*/ */
static void __fput(struct file *file) static void __fput(struct file *file)
...@@ -248,8 +217,10 @@ static void __fput(struct file *file) ...@@ -248,8 +217,10 @@ static void __fput(struct file *file)
put_pid(file->f_owner.pid); put_pid(file->f_owner.pid);
if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
i_readcount_dec(inode); i_readcount_dec(inode);
if (file->f_mode & FMODE_WRITE) if (file->f_mode & FMODE_WRITER) {
drop_file_write_access(file); put_write_access(inode);
__mnt_drop_write(mnt);
}
file->f_path.dentry = NULL; file->f_path.dentry = NULL;
file->f_path.mnt = NULL; file->f_path.mnt = NULL;
file->f_inode = NULL; file->f_inode = NULL;
......
...@@ -414,9 +414,7 @@ EXPORT_SYMBOL_GPL(mnt_clone_write); ...@@ -414,9 +414,7 @@ EXPORT_SYMBOL_GPL(mnt_clone_write);
*/ */
int __mnt_want_write_file(struct file *file) int __mnt_want_write_file(struct file *file)
{ {
struct inode *inode = file_inode(file); if (!(file->f_mode & FMODE_WRITER))
if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode))
return __mnt_want_write(file->f_path.mnt); return __mnt_want_write(file->f_path.mnt);
else else
return mnt_clone_write(file->f_path.mnt); return mnt_clone_write(file->f_path.mnt);
......
...@@ -670,6 +670,7 @@ static int do_dentry_open(struct file *f, ...@@ -670,6 +670,7 @@ static int do_dentry_open(struct file *f,
put_write_access(inode); put_write_access(inode);
goto cleanup_file; goto cleanup_file;
} }
f->f_mode |= FMODE_WRITER;
} }
f->f_mapping = inode->i_mapping; f->f_mapping = inode->i_mapping;
...@@ -715,12 +716,10 @@ static int do_dentry_open(struct file *f, ...@@ -715,12 +716,10 @@ static int do_dentry_open(struct file *f,
cleanup_all: cleanup_all:
fops_put(f->f_op); fops_put(f->f_op);
if (f->f_mode & FMODE_WRITE) { if (f->f_mode & FMODE_WRITER) {
if (!special_file(inode->i_mode)) {
put_write_access(inode); put_write_access(inode);
__mnt_drop_write(f->f_path.mnt); __mnt_drop_write(f->f_path.mnt);
} }
}
cleanup_file: cleanup_file:
path_put(&f->f_path); path_put(&f->f_path);
f->f_path.mnt = NULL; f->f_path.mnt = NULL;
......
...@@ -125,6 +125,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, ...@@ -125,6 +125,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
/* File needs atomic accesses to f_pos */ /* File needs atomic accesses to f_pos */
#define FMODE_ATOMIC_POS ((__force fmode_t)0x8000) #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 */ /* File was opened by fanotify and shouldn't generate fanotify events */
#define FMODE_NONOTIFY ((__force fmode_t)0x1000000) #define FMODE_NONOTIFY ((__force fmode_t)0x1000000)
......
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