diff options
Diffstat (limited to 'fs/read_write.c')
| -rw-r--r-- | fs/read_write.c | 40 | 
1 files changed, 26 insertions, 14 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index edc5746a902a..54e19b9392dc 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -264,10 +264,22 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence)  }  EXPORT_SYMBOL(vfs_llseek); +static inline struct fd fdget_pos(int fd) +{ +	return __to_fd(__fdget_pos(fd)); +} + +static inline void fdput_pos(struct fd f) +{ +	if (f.flags & FDPUT_POS_UNLOCK) +		mutex_unlock(&f.file->f_pos_lock); +	fdput(f); +} +  SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)  {  	off_t retval; -	struct fd f = fdget(fd); +	struct fd f = fdget_pos(fd);  	if (!f.file)  		return -EBADF; @@ -278,7 +290,7 @@ SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)  		if (res != (loff_t)retval)  			retval = -EOVERFLOW;	/* LFS: should only happen on 32 bit platforms */  	} -	fdput(f); +	fdput_pos(f);  	return retval;  } @@ -498,7 +510,7 @@ static inline void file_pos_write(struct file *file, loff_t pos)  SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)  { -	struct fd f = fdget(fd); +	struct fd f = fdget_pos(fd);  	ssize_t ret = -EBADF;  	if (f.file) { @@ -506,7 +518,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)  		ret = vfs_read(f.file, buf, count, &pos);  		if (ret >= 0)  			file_pos_write(f.file, pos); -		fdput(f); +		fdput_pos(f);  	}  	return ret;  } @@ -514,7 +526,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)  SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,  		size_t, count)  { -	struct fd f = fdget(fd); +	struct fd f = fdget_pos(fd);  	ssize_t ret = -EBADF;  	if (f.file) { @@ -522,7 +534,7 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,  		ret = vfs_write(f.file, buf, count, &pos);  		if (ret >= 0)  			file_pos_write(f.file, pos); -		fdput(f); +		fdput_pos(f);  	}  	return ret; @@ -797,7 +809,7 @@ EXPORT_SYMBOL(vfs_writev);  SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,  		unsigned long, vlen)  { -	struct fd f = fdget(fd); +	struct fd f = fdget_pos(fd);  	ssize_t ret = -EBADF;  	if (f.file) { @@ -805,7 +817,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,  		ret = vfs_readv(f.file, vec, vlen, &pos);  		if (ret >= 0)  			file_pos_write(f.file, pos); -		fdput(f); +		fdput_pos(f);  	}  	if (ret > 0) @@ -817,7 +829,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,  SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,  		unsigned long, vlen)  { -	struct fd f = fdget(fd); +	struct fd f = fdget_pos(fd);  	ssize_t ret = -EBADF;  	if (f.file) { @@ -825,7 +837,7 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,  		ret = vfs_writev(f.file, vec, vlen, &pos);  		if (ret >= 0)  			file_pos_write(f.file, pos); -		fdput(f); +		fdput_pos(f);  	}  	if (ret > 0) @@ -968,7 +980,7 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,  		const struct compat_iovec __user *,vec,  		compat_ulong_t, vlen)  { -	struct fd f = fdget(fd); +	struct fd f = fdget_pos(fd);  	ssize_t ret;  	loff_t pos; @@ -978,7 +990,7 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,  	ret = compat_readv(f.file, vec, vlen, &pos);  	if (ret >= 0)  		f.file->f_pos = pos; -	fdput(f); +	fdput_pos(f);  	return ret;  } @@ -1035,7 +1047,7 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,  		const struct compat_iovec __user *, vec,  		compat_ulong_t, vlen)  { -	struct fd f = fdget(fd); +	struct fd f = fdget_pos(fd);  	ssize_t ret;  	loff_t pos; @@ -1045,7 +1057,7 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,  	ret = compat_writev(f.file, vec, vlen, &pos);  	if (ret >= 0)  		f.file->f_pos = pos; -	fdput(f); +	fdput_pos(f);  	return ret;  }  | 
