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

Commit e6a4b6f5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull vfs fixes from Al Viro.

Clean up file table accesses (get rid of fget_light() in favor of the
fdget() interface), add proper file position locking.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  get rid of fget_light()
  sockfd_lookup_light(): switch to fdget^W^Waway from fget_light
  vfs: atomic f_pos accesses as per POSIX
  ocfs2 syncs the wrong range...
parents 2b64c543 bd2a31d5
Loading
Loading
Loading
Loading
+43 −13
Original line number Diff line number Diff line
@@ -683,35 +683,65 @@ EXPORT_SYMBOL(fget_raw);
 * The fput_needed flag returned by fget_light should be passed to the
 * corresponding fput_light.
 */
struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed)
static unsigned long __fget_light(unsigned int fd, fmode_t mask)
{
	struct files_struct *files = current->files;
	struct file *file;

	*fput_needed = 0;
	if (atomic_read(&files->count) == 1) {
		file = __fcheck_files(files, fd);
		if (file && (file->f_mode & mask))
			file = NULL;
		if (!file || unlikely(file->f_mode & mask))
			return 0;
		return (unsigned long)file;
	} else {
		file = __fget(fd, mask);
		if (file)
			*fput_needed = 1;
		if (!file)
			return 0;
		return FDPUT_FPUT | (unsigned long)file;
	}

	return file;
}
struct file *fget_light(unsigned int fd, int *fput_needed)
unsigned long __fdget(unsigned int fd)
{
	return __fget_light(fd, FMODE_PATH, fput_needed);
	return __fget_light(fd, FMODE_PATH);
}
EXPORT_SYMBOL(fget_light);
EXPORT_SYMBOL(__fdget);

struct file *fget_raw_light(unsigned int fd, int *fput_needed)
unsigned long __fdget_raw(unsigned int fd)
{
	return __fget_light(fd, 0, fput_needed);
	return __fget_light(fd, 0);
}

unsigned long __fdget_pos(unsigned int fd)
{
	struct files_struct *files = current->files;
	struct file *file;
	unsigned long v;

	if (atomic_read(&files->count) == 1) {
		file = __fcheck_files(files, fd);
		v = 0;
	} else {
		file = __fget(fd, 0);
		v = FDPUT_FPUT;
	}
	if (!file)
		return 0;

	if (file->f_mode & FMODE_ATOMIC_POS) {
		if (file_count(file) > 1) {
			v |= FDPUT_POS_UNLOCK;
			mutex_lock(&file->f_pos_lock);
		}
	}
	return v | (unsigned long)file;
}

/*
 * We only lock f_pos if we have threads or if the file might be
 * shared with another process. In both cases we'll have an elevated
 * file count (done either by fdget() or by fork()).
 */

void set_close_on_exec(unsigned int fd, int flag)
{
	struct files_struct *files = current->files;
+1 −0
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ struct file *get_empty_filp(void)
	atomic_long_set(&f->f_count, 1);
	rwlock_init(&f->f_owner.lock);
	spin_lock_init(&f->f_lock);
	mutex_init(&f->f_pos_lock);
	eventpoll_init_file(f);
	/* f->f_version: 0 */
	return f;
+1 −1
Original line number Diff line number Diff line
@@ -1884,7 +1884,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,

		nd->path = f.file->f_path;
		if (flags & LOOKUP_RCU) {
			if (f.need_put)
			if (f.flags & FDPUT_FPUT)
				*fp = f.file;
			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
			rcu_read_lock();
+4 −4
Original line number Diff line number Diff line
@@ -2393,8 +2393,8 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,

	if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) ||
	    ((file->f_flags & O_DIRECT) && !direct_io)) {
		ret = filemap_fdatawrite_range(file->f_mapping, pos,
					       pos + count - 1);
		ret = filemap_fdatawrite_range(file->f_mapping, *ppos,
					       *ppos + count - 1);
		if (ret < 0)
			written = ret;

@@ -2407,8 +2407,8 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
		}

		if (!ret)
			ret = filemap_fdatawait_range(file->f_mapping, pos,
						      pos + count - 1);
			ret = filemap_fdatawait_range(file->f_mapping, *ppos,
						      *ppos + count - 1);
	}

	/*
+4 −0
Original line number Diff line number Diff line
@@ -705,6 +705,10 @@ static int do_dentry_open(struct file *f,
		return 0;
	}

	/* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
	if (S_ISREG(inode->i_mode))
		f->f_mode |= FMODE_ATOMIC_POS;

	f->f_op = fops_get(inode->i_fop);
	if (unlikely(WARN_ON(!f->f_op))) {
		error = -ENODEV;
Loading