Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+4 −33
Original line number Diff line number Diff line
@@ -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;
+1 −3
Original line number Diff line number Diff line
@@ -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);
+4 −5
Original line number Diff line number Diff line
@@ -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,12 +716,10 @@ 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)) {
	if (f->f_mode & FMODE_WRITER) {
		put_write_access(inode);
		__mnt_drop_write(f->f_path.mnt);
	}
	}
cleanup_file:
	path_put(&f->f_path);
	f->f_path.mnt = NULL;
+2 −0
Original line number Diff line number Diff line
@@ -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)