VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
b24413180f560 (Greg Kroah-Hartman      2017-11-01 15:07:57 +0100    1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    2) /*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    3)  *  linux/fs/read_write.c
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    4)  *
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    5)  *  Copyright (C) 1991, 1992  Linus Torvalds
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    6)  */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    7) 
b12fb7f46af7d (Ingo Molnar             2017-02-08 18:51:33 +0100    8) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    9) #include <linux/stat.h>
b12fb7f46af7d (Ingo Molnar             2017-02-08 18:51:33 +0100   10) #include <linux/sched/xacct.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   11) #include <linux/fcntl.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   12) #include <linux/file.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   13) #include <linux/uio.h>
0eeca28300df1 (Robert Love             2005-07-12 17:06:03 -0400   14) #include <linux/fsnotify.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   15) #include <linux/security.h>
630d9c47274aa (Paul Gortmaker          2011-11-16 23:57:37 -0500   16) #include <linux/export.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   17) #include <linux/syscalls.h>
e28cc71572da3 (Linus Torvalds          2006-01-04 16:20:40 -0800   18) #include <linux/pagemap.h>
d6b29d7cee064 (Jens Axboe              2007-06-04 09:59:47 +0200   19) #include <linux/splice.h>
561c6731978fa (Al Viro                 2013-02-24 10:52:26 -0500   20) #include <linux/compat.h>
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500   21) #include <linux/mount.h>
2feb55f89096b (Wouter van Kesteren     2016-02-16 22:20:59 +0100   22) #include <linux/fs.h>
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400   23) #include "internal.h"
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   24) 
7c0f6ba682b9c (Linus Torvalds          2016-12-24 11:46:01 -0800   25) #include <linux/uaccess.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   26) #include <asm/unistd.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   27) 
4b6f5d20b04dc (Arjan van de Ven        2006-03-28 01:56:42 -0800   28) const struct file_operations generic_ro_fops = {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   29) 	.llseek		= generic_file_llseek,
aad4f8bb42af0 (Al Viro                 2014-04-02 14:33:16 -0400   30) 	.read_iter	= generic_file_read_iter,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   31) 	.mmap		= generic_file_readonly_mmap,
534f2aaa6ab07 (Jens Axboe              2007-06-01 14:52:37 +0200   32) 	.splice_read	= generic_file_splice_read,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   33) };
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   34) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   35) EXPORT_SYMBOL(generic_ro_fops);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   36) 
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200   37) static inline bool unsigned_offsets(struct file *file)
4a3956c790290 (KAMEZAWA Hiroyuki       2010-10-01 14:20:22 -0700   38) {
cccb5a1e69853 (Al Viro                 2010-12-17 07:44:05 -0500   39) 	return file->f_mode & FMODE_UNSIGNED_OFFSET;
4a3956c790290 (KAMEZAWA Hiroyuki       2010-10-01 14:20:22 -0700   40) }
4a3956c790290 (KAMEZAWA Hiroyuki       2010-10-01 14:20:22 -0700   41) 
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   42) /**
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   43)  * vfs_setpos - update the file offset for lseek
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   44)  * @file:	file structure in question
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   45)  * @offset:	file offset to seek to
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   46)  * @maxsize:	maximum file size
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   47)  *
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   48)  * This is a low-level filesystem helper for updating the file offset to
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   49)  * the value specified by @offset if the given offset is valid and it is
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   50)  * not equal to the current file offset.
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   51)  *
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   52)  * Return the specified offset on success and -EINVAL on invalid offset.
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   53)  */
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   54) loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   55) {
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   56) 	if (offset < 0 && !unsigned_offsets(file))
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   57) 		return -EINVAL;
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   58) 	if (offset > maxsize)
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   59) 		return -EINVAL;
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   60) 
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   61) 	if (offset != file->f_pos) {
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   62) 		file->f_pos = offset;
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   63) 		file->f_version = 0;
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   64) 	}
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   65) 	return offset;
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   66) }
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800   67) EXPORT_SYMBOL(vfs_setpos);
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   68) 
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200   69) /**
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700   70)  * generic_file_llseek_size - generic llseek implementation for regular files
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200   71)  * @file:	file structure to seek on
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200   72)  * @offset:	file offset to seek to
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800   73)  * @whence:	type of seek
e8b96eb5034a0 (Eric Sandeen            2012-04-30 13:11:29 -0500   74)  * @size:	max size of this file in file system
e8b96eb5034a0 (Eric Sandeen            2012-04-30 13:11:29 -0500   75)  * @eof:	offset used for SEEK_END position
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200   76)  *
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700   77)  * This is a variant of generic_file_llseek that allows passing in a custom
e8b96eb5034a0 (Eric Sandeen            2012-04-30 13:11:29 -0500   78)  * maximum file size and a custom EOF position, for e.g. hashed directories
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   79)  *
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   80)  * Synchronization:
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700   81)  * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms)
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   82)  * SEEK_CUR is synchronized against other SEEK_CURs, but not read/writes.
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700   83)  * read/writes behave like SEEK_SET against seeks.
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200   84)  */
9465efc9e9613 (Andi Kleen              2008-06-27 11:05:24 +0200   85) loff_t
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800   86) generic_file_llseek_size(struct file *file, loff_t offset, int whence,
e8b96eb5034a0 (Eric Sandeen            2012-04-30 13:11:29 -0500   87) 		loff_t maxsize, loff_t eof)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   88) {
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800   89) 	switch (whence) {
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200   90) 	case SEEK_END:
e8b96eb5034a0 (Eric Sandeen            2012-04-30 13:11:29 -0500   91) 		offset += eof;
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200   92) 		break;
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200   93) 	case SEEK_CUR:
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800   94) 		/*
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800   95) 		 * Here we special-case the lseek(fd, 0, SEEK_CUR)
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800   96) 		 * position-querying operation.  Avoid rewriting the "same"
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800   97) 		 * f_pos value back to the file because a concurrent read(),
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800   98) 		 * write() or lseek() might have altered it
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800   99) 		 */
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800  100) 		if (offset == 0)
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800  101) 			return file->f_pos;
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700  102) 		/*
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700  103) 		 * f_lock protects against read/modify/write race with other
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700  104) 		 * SEEK_CURs. Note that parallel writes and reads behave
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700  105) 		 * like SEEK_SET.
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700  106) 		 */
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700  107) 		spin_lock(&file->f_lock);
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800  108) 		offset = vfs_setpos(file, file->f_pos + offset, maxsize);
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700  109) 		spin_unlock(&file->f_lock);
ef3d0fd27e90f (Andi Kleen              2011-09-15 16:06:48 -0700  110) 		return offset;
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  111) 	case SEEK_DATA:
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  112) 		/*
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  113) 		 * In the generic case the entire file is data, so as long as
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  114) 		 * offset isn't at the end of the file then the offset is data.
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  115) 		 */
fc46820b27a2d (Andreas Gruenbacher     2017-09-25 12:23:03 +0200  116) 		if ((unsigned long long)offset >= eof)
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  117) 			return -ENXIO;
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  118) 		break;
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  119) 	case SEEK_HOLE:
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  120) 		/*
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  121) 		 * There is a virtual hole at the end of the file, so as long as
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  122) 		 * offset isn't i_size or larger, return i_size.
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  123) 		 */
fc46820b27a2d (Andreas Gruenbacher     2017-09-25 12:23:03 +0200  124) 		if ((unsigned long long)offset >= eof)
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  125) 			return -ENXIO;
e8b96eb5034a0 (Eric Sandeen            2012-04-30 13:11:29 -0500  126) 		offset = eof;
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  127) 		break;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  128) 	}
3a8cff4f026c0 (Christoph Hellwig       2008-08-11 15:37:17 +0200  129) 
46a1c2c7ae53d (Jie Liu                 2013-06-25 12:02:13 +0800  130) 	return vfs_setpos(file, offset, maxsize);
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  131) }
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  132) EXPORT_SYMBOL(generic_file_llseek_size);
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  133) 
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  134) /**
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  135)  * generic_file_llseek - generic llseek implementation for regular files
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  136)  * @file:	file structure to seek on
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  137)  * @offset:	file offset to seek to
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  138)  * @whence:	type of seek
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  139)  *
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  140)  * This is a generic implemenation of ->llseek useable for all normal local
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  141)  * filesystems.  It just updates the file offset to the value specified by
546ae2d2f7172 (Ming Lei                2013-04-29 15:06:07 -0700  142)  * @offset and @whence.
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  143)  */
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  144) loff_t generic_file_llseek(struct file *file, loff_t offset, int whence)
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  145) {
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  146) 	struct inode *inode = file->f_mapping->host;
5760495a872d6 (Andi Kleen              2011-09-15 16:06:50 -0700  147) 
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  148) 	return generic_file_llseek_size(file, offset, whence,
e8b96eb5034a0 (Eric Sandeen            2012-04-30 13:11:29 -0500  149) 					inode->i_sb->s_maxbytes,
e8b96eb5034a0 (Eric Sandeen            2012-04-30 13:11:29 -0500  150) 					i_size_read(inode));
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  151) }
9465efc9e9613 (Andi Kleen              2008-06-27 11:05:24 +0200  152) EXPORT_SYMBOL(generic_file_llseek);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  153) 
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  154) /**
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  155)  * fixed_size_llseek - llseek implementation for fixed-sized devices
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  156)  * @file:	file structure to seek on
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  157)  * @offset:	file offset to seek to
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  158)  * @whence:	type of seek
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  159)  * @size:	size of the file
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  160)  *
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  161)  */
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  162) loff_t fixed_size_llseek(struct file *file, loff_t offset, int whence, loff_t size)
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  163) {
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  164) 	switch (whence) {
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  165) 	case SEEK_SET: case SEEK_CUR: case SEEK_END:
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  166) 		return generic_file_llseek_size(file, offset, whence,
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  167) 						size, size);
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  168) 	default:
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  169) 		return -EINVAL;
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  170) 	}
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  171) }
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  172) EXPORT_SYMBOL(fixed_size_llseek);
1bf9d14dff4a2 (Al Viro                 2013-06-16 20:27:42 +0400  173) 
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  174) /**
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  175)  * no_seek_end_llseek - llseek implementation for fixed-sized devices
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  176)  * @file:	file structure to seek on
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  177)  * @offset:	file offset to seek to
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  178)  * @whence:	type of seek
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  179)  *
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  180)  */
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  181) loff_t no_seek_end_llseek(struct file *file, loff_t offset, int whence)
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  182) {
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  183) 	switch (whence) {
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  184) 	case SEEK_SET: case SEEK_CUR:
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  185) 		return generic_file_llseek_size(file, offset, whence,
2feb55f89096b (Wouter van Kesteren     2016-02-16 22:20:59 +0100  186) 						OFFSET_MAX, 0);
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  187) 	default:
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  188) 		return -EINVAL;
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  189) 	}
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  190) }
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  191) EXPORT_SYMBOL(no_seek_end_llseek);
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  192) 
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  193) /**
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  194)  * no_seek_end_llseek_size - llseek implementation for fixed-sized devices
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  195)  * @file:	file structure to seek on
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  196)  * @offset:	file offset to seek to
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  197)  * @whence:	type of seek
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  198)  * @size:	maximal offset allowed
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  199)  *
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  200)  */
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  201) loff_t no_seek_end_llseek_size(struct file *file, loff_t offset, int whence, loff_t size)
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  202) {
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  203) 	switch (whence) {
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  204) 	case SEEK_SET: case SEEK_CUR:
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  205) 		return generic_file_llseek_size(file, offset, whence,
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  206) 						size, 0);
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  207) 	default:
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  208) 		return -EINVAL;
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  209) 	}
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  210) }
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  211) EXPORT_SYMBOL(no_seek_end_llseek_size);
b25472f9b9615 (Al Viro                 2015-12-05 22:04:48 -0500  212) 
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  213) /**
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  214)  * noop_llseek - No Operation Performed llseek implementation
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  215)  * @file:	file structure to seek on
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  216)  * @offset:	file offset to seek to
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  217)  * @whence:	type of seek
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  218)  *
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  219)  * This is an implementation of ->llseek useable for the rare special case when
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  220)  * userspace expects the seek to succeed but the (device) file is actually not
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  221)  * able to perform the seek. In this case you use noop_llseek() instead of
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  222)  * falling back to the default implementation of ->llseek.
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  223)  */
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  224) loff_t noop_llseek(struct file *file, loff_t offset, int whence)
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  225) {
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  226) 	return file->f_pos;
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  227) }
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  228) EXPORT_SYMBOL(noop_llseek);
ae6afc3f5cf53 (jan Blunck              2010-05-26 14:44:48 -0700  229) 
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  230) loff_t no_llseek(struct file *file, loff_t offset, int whence)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  231) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  232) 	return -ESPIPE;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  233) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  234) EXPORT_SYMBOL(no_llseek);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  235) 
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  236) loff_t default_llseek(struct file *file, loff_t offset, int whence)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  237) {
496ad9aa8ef44 (Al Viro                 2013-01-23 17:07:38 -0500  238) 	struct inode *inode = file_inode(file);
16abef0e9e796 (David Sterba            2008-04-22 15:09:22 +0200  239) 	loff_t retval;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  240) 
5955102c9984f (Al Viro                 2016-01-22 15:40:57 -0500  241) 	inode_lock(inode);
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  242) 	switch (whence) {
7b8e89249ba54 (Chris Snook             2007-05-08 00:24:13 -0700  243) 		case SEEK_END:
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  244) 			offset += i_size_read(inode);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  245) 			break;
7b8e89249ba54 (Chris Snook             2007-05-08 00:24:13 -0700  246) 		case SEEK_CUR:
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800  247) 			if (offset == 0) {
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800  248) 				retval = file->f_pos;
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800  249) 				goto out;
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800  250) 			}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  251) 			offset += file->f_pos;
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  252) 			break;
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  253) 		case SEEK_DATA:
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  254) 			/*
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  255) 			 * In the generic case the entire file is data, so as
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  256) 			 * long as offset isn't at the end of the file then the
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  257) 			 * offset is data.
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  258) 			 */
bacb2d816c77e (Dan Carpenter           2011-07-26 17:25:20 +0300  259) 			if (offset >= inode->i_size) {
bacb2d816c77e (Dan Carpenter           2011-07-26 17:25:20 +0300  260) 				retval = -ENXIO;
bacb2d816c77e (Dan Carpenter           2011-07-26 17:25:20 +0300  261) 				goto out;
bacb2d816c77e (Dan Carpenter           2011-07-26 17:25:20 +0300  262) 			}
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  263) 			break;
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  264) 		case SEEK_HOLE:
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  265) 			/*
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  266) 			 * There is a virtual hole at the end of the file, so
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  267) 			 * as long as offset isn't i_size or larger, return
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  268) 			 * i_size.
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  269) 			 */
bacb2d816c77e (Dan Carpenter           2011-07-26 17:25:20 +0300  270) 			if (offset >= inode->i_size) {
bacb2d816c77e (Dan Carpenter           2011-07-26 17:25:20 +0300  271) 				retval = -ENXIO;
bacb2d816c77e (Dan Carpenter           2011-07-26 17:25:20 +0300  272) 				goto out;
bacb2d816c77e (Dan Carpenter           2011-07-26 17:25:20 +0300  273) 			}
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  274) 			offset = inode->i_size;
982d816581eee (Josef Bacik             2011-07-18 13:21:35 -0400  275) 			break;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  276) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  277) 	retval = -EINVAL;
cccb5a1e69853 (Al Viro                 2010-12-17 07:44:05 -0500  278) 	if (offset >= 0 || unsigned_offsets(file)) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  279) 		if (offset != file->f_pos) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  280) 			file->f_pos = offset;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  281) 			file->f_version = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  282) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  283) 		retval = offset;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  284) 	}
5b6f1eb97d462 (Alain Knaff             2008-11-10 17:08:08 -0800  285) out:
5955102c9984f (Al Viro                 2016-01-22 15:40:57 -0500  286) 	inode_unlock(inode);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  287) 	return retval;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  288) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  289) EXPORT_SYMBOL(default_llseek);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  290) 
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  291) loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  292) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  293) 	loff_t (*fn)(struct file *, loff_t, int);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  294) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  295) 	fn = no_llseek;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  296) 	if (file->f_mode & FMODE_LSEEK) {
72c2d53192004 (Al Viro                 2013-09-22 16:27:52 -0400  297) 		if (file->f_op->llseek)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  298) 			fn = file->f_op->llseek;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  299) 	}
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  300) 	return fn(file, offset, whence);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  301) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  302) EXPORT_SYMBOL(vfs_llseek);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  303) 
bef1732996134 (Christoph Hellwig       2020-06-06 14:49:58 +0200  304) static off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  305) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  306) 	off_t retval;
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  307) 	struct fd f = fdget_pos(fd);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  308) 	if (!f.file)
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  309) 		return -EBADF;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  310) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  311) 	retval = -EINVAL;
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  312) 	if (whence <= SEEK_MAX) {
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  313) 		loff_t res = vfs_llseek(f.file, offset, whence);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  314) 		retval = res;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  315) 		if (res != (loff_t)retval)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  316) 			retval = -EOVERFLOW;	/* LFS: should only happen on 32 bit platforms */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  317) 	}
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  318) 	fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  319) 	return retval;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  320) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  321) 
76847e4344350 (Dominik Brodowski       2018-03-13 21:51:17 +0100  322) SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
76847e4344350 (Dominik Brodowski       2018-03-13 21:51:17 +0100  323) {
76847e4344350 (Dominik Brodowski       2018-03-13 21:51:17 +0100  324) 	return ksys_lseek(fd, offset, whence);
76847e4344350 (Dominik Brodowski       2018-03-13 21:51:17 +0100  325) }
76847e4344350 (Dominik Brodowski       2018-03-13 21:51:17 +0100  326) 
561c6731978fa (Al Viro                 2013-02-24 10:52:26 -0500  327) #ifdef CONFIG_COMPAT
561c6731978fa (Al Viro                 2013-02-24 10:52:26 -0500  328) COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned int, whence)
561c6731978fa (Al Viro                 2013-02-24 10:52:26 -0500  329) {
76847e4344350 (Dominik Brodowski       2018-03-13 21:51:17 +0100  330) 	return ksys_lseek(fd, offset, whence);
561c6731978fa (Al Viro                 2013-02-24 10:52:26 -0500  331) }
561c6731978fa (Al Viro                 2013-02-24 10:52:26 -0500  332) #endif
561c6731978fa (Al Viro                 2013-02-24 10:52:26 -0500  333) 
9e62ccec3ba0a (Michal Suchanek         2020-03-20 11:20:12 +0100  334) #if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) || \
9e62ccec3ba0a (Michal Suchanek         2020-03-20 11:20:12 +0100  335) 	defined(__ARCH_WANT_SYS_LLSEEK)
003d7ab479168 (Heiko Carstens          2009-01-14 14:14:21 +0100  336) SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
003d7ab479168 (Heiko Carstens          2009-01-14 14:14:21 +0100  337) 		unsigned long, offset_low, loff_t __user *, result,
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  338) 		unsigned int, whence)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  339) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  340) 	int retval;
d7a15f8d07779 (Eric Biggers            2014-03-16 14:24:08 -0500  341) 	struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  342) 	loff_t offset;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  343) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  344) 	if (!f.file)
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  345) 		return -EBADF;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  346) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  347) 	retval = -EINVAL;
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  348) 	if (whence > SEEK_MAX)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  349) 		goto out_putf;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  350) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  351) 	offset = vfs_llseek(f.file, ((loff_t) offset_high << 32) | offset_low,
965c8e59cfcf8 (Andrew Morton           2012-12-17 15:59:39 -0800  352) 			whence);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  353) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  354) 	retval = (int)offset;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  355) 	if (offset >= 0) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  356) 		retval = -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  357) 		if (!copy_to_user(result, &offset, sizeof(offset)))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  358) 			retval = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  359) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  360) out_putf:
d7a15f8d07779 (Eric Biggers            2014-03-16 14:24:08 -0500  361) 	fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  362) 	return retval;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  363) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  364) #endif
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  365) 
68d70d03f8f5b (Al Viro                 2013-06-19 15:26:04 +0400  366) int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  367) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  368) 	struct inode *inode;
c43e259cc756e (James Morris            2008-01-12 22:05:48 +1100  369) 	int retval = -EINVAL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  370) 
496ad9aa8ef44 (Al Viro                 2013-01-23 17:07:38 -0500  371) 	inode = file_inode(file);
e28cc71572da3 (Linus Torvalds          2006-01-04 16:20:40 -0800  372) 	if (unlikely((ssize_t) count < 0))
c43e259cc756e (James Morris            2008-01-12 22:05:48 +1100  373) 		return retval;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  374) 
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  375) 	/*
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  376) 	 * ranged mandatory locking does not apply to streams - it makes sense
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  377) 	 * only for files where position has a meaning.
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  378) 	 */
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  379) 	if (ppos) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  380) 		loff_t pos = *ppos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  381) 
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  382) 		if (unlikely(pos < 0)) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  383) 			if (!unsigned_offsets(file))
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  384) 				return retval;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  385) 			if (count >= -pos) /* both values are in 0..LLONG_MAX */
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  386) 				return -EOVERFLOW;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  387) 		} else if (unlikely((loff_t) (pos + count) < 0)) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  388) 			if (!unsigned_offsets(file))
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  389) 				return retval;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  390) 		}
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  391) 
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  392) 		if (unlikely(inode->i_flctx && mandatory_lock(inode))) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  393) 			retval = locks_mandatory_area(inode, file, pos, pos + count - 1,
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  394) 					read_write == READ ? F_RDLCK : F_WRLCK);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  395) 			if (retval < 0)
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  396) 				return retval;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  397) 		}
e28cc71572da3 (Linus Torvalds          2006-01-04 16:20:40 -0800  398) 	}
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  399) 
bc61384dcdd82 (Al Viro                 2016-03-31 21:48:20 -0400  400) 	return security_file_permission(file,
c43e259cc756e (James Morris            2008-01-12 22:05:48 +1100  401) 				read_write == READ ? MAY_READ : MAY_WRITE);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  402) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  403) 
5d5d568975307 (Al Viro                 2015-04-03 15:41:18 -0400  404) static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  405) {
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  406) 	struct iovec iov = { .iov_base = buf, .iov_len = len };
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  407) 	struct kiocb kiocb;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  408) 	struct iov_iter iter;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  409) 	ssize_t ret;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  410) 
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  411) 	init_sync_kiocb(&kiocb, filp);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  412) 	kiocb.ki_pos = (ppos ? *ppos : 0);
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  413) 	iov_iter_init(&iter, READ, &iov, 1, len);
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  414) 
bb7462b6fd64e (Miklos Szeredi          2017-02-20 16:51:23 +0100  415) 	ret = call_read_iter(filp, &kiocb, &iter);
599bd19bdc4c6 (Christoph Hellwig       2015-02-11 19:59:44 +0100  416) 	BUG_ON(ret == -EIOCBQUEUED);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  417) 	if (ppos)
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  418) 		*ppos = kiocb.ki_pos;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  419) 	return ret;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  420) }
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  421) 
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  422) static int warn_unsupported(struct file *file, const char *op)
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  423) {
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  424) 	pr_warn_ratelimited(
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  425) 		"kernel %s not supported for file %pD4 (pid: %d comm: %.20s)\n",
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  426) 		op, file, current->pid, current->comm);
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  427) 	return -EINVAL;
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  428) }
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  429) 
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  430) ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  431) {
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  432) 	struct kvec iov = {
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  433) 		.iov_base	= buf,
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  434) 		.iov_len	= min_t(size_t, count, MAX_RW_COUNT),
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  435) 	};
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  436) 	struct kiocb kiocb;
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  437) 	struct iov_iter iter;
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  438) 	ssize_t ret;
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  439) 
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  440) 	if (WARN_ON_ONCE(!(file->f_mode & FMODE_READ)))
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  441) 		return -EINVAL;
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  442) 	if (!(file->f_mode & FMODE_CAN_READ))
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  443) 		return -EINVAL;
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  444) 	/*
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  445) 	 * Also fail if ->read_iter and ->read are both wired up as that
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  446) 	 * implies very convoluted semantics.
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  447) 	 */
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  448) 	if (unlikely(!file->f_op->read_iter || file->f_op->read))
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  449) 		return warn_unsupported(file, "read");
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  450) 
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  451) 	init_sync_kiocb(&kiocb, file);
7b84b665c874f (Matthew Wilcox (Oracle) 2020-10-03 03:55:23 +0100  452) 	kiocb.ki_pos = pos ? *pos : 0;
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  453) 	iov_iter_kvec(&iter, READ, &iov, 1, iov.iov_len);
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  454) 	ret = file->f_op->read_iter(&kiocb, &iter);
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  455) 	if (ret > 0) {
7b84b665c874f (Matthew Wilcox (Oracle) 2020-10-03 03:55:23 +0100  456) 		if (pos)
7b84b665c874f (Matthew Wilcox (Oracle) 2020-10-03 03:55:23 +0100  457) 			*pos = kiocb.ki_pos;
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  458) 		fsnotify_access(file);
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  459) 		add_rchar(current, ret);
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  460) 	}
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  461) 	inc_syscr(current);
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  462) 	return ret;
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  463) }
61a707c543e2a (Christoph Hellwig       2020-05-08 08:54:16 +0200  464) 
bdd1d2d3d251c (Christoph Hellwig       2017-09-01 17:39:13 +0200  465) ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
c41fbad015dab (Christoph Hellwig       2017-09-01 17:39:12 +0200  466) {
6209dd9132e8e (Christoph Hellwig       2020-05-08 09:00:28 +0200  467) 	ssize_t ret;
c41fbad015dab (Christoph Hellwig       2017-09-01 17:39:12 +0200  468) 
6209dd9132e8e (Christoph Hellwig       2020-05-08 09:00:28 +0200  469) 	ret = rw_verify_area(READ, file, pos, count);
6209dd9132e8e (Christoph Hellwig       2020-05-08 09:00:28 +0200  470) 	if (ret)
6209dd9132e8e (Christoph Hellwig       2020-05-08 09:00:28 +0200  471) 		return ret;
6209dd9132e8e (Christoph Hellwig       2020-05-08 09:00:28 +0200  472) 	return __kernel_read(file, buf, count, pos);
c41fbad015dab (Christoph Hellwig       2017-09-01 17:39:12 +0200  473) }
c41fbad015dab (Christoph Hellwig       2017-09-01 17:39:12 +0200  474) EXPORT_SYMBOL(kernel_read);
6fb5032ebb1c5 (Dmitry Kasatkin         2014-11-05 17:01:17 +0200  475) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  476) ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  477) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  478) 	ssize_t ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  479) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  480) 	if (!(file->f_mode & FMODE_READ))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  481) 		return -EBADF;
7f7f25e82d548 (Al Viro                 2014-02-11 17:49:24 -0500  482) 	if (!(file->f_mode & FMODE_CAN_READ))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  483) 		return -EINVAL;
96d4f267e40f9 (Linus Torvalds          2019-01-03 18:57:57 -0800  484) 	if (unlikely(!access_ok(buf, count)))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  485) 		return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  486) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  487) 	ret = rw_verify_area(READ, file, pos, count);
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  488) 	if (ret)
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  489) 		return ret;
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  490) 	if (count > MAX_RW_COUNT)
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  491) 		count =  MAX_RW_COUNT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  492) 
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  493) 	if (file->f_op->read)
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  494) 		ret = file->f_op->read(file, buf, count, pos);
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  495) 	else if (file->f_op->read_iter)
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  496) 		ret = new_sync_read(file, buf, count, pos);
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  497) 	else
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  498) 		ret = -EINVAL;
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  499) 	if (ret > 0) {
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  500) 		fsnotify_access(file);
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  501) 		add_rchar(current, ret);
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  502) 	}
775802c0571fb (Christoph Hellwig       2020-05-08 11:17:46 +0200  503) 	inc_syscr(current);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  504) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  505) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  506) 
5d5d568975307 (Al Viro                 2015-04-03 15:41:18 -0400  507) static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  508) {
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  509) 	struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  510) 	struct kiocb kiocb;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  511) 	struct iov_iter iter;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  512) 	ssize_t ret;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  513) 
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  514) 	init_sync_kiocb(&kiocb, filp);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  515) 	kiocb.ki_pos = (ppos ? *ppos : 0);
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  516) 	iov_iter_init(&iter, WRITE, &iov, 1, len);
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  517) 
bb7462b6fd64e (Miklos Szeredi          2017-02-20 16:51:23 +0100  518) 	ret = call_write_iter(filp, &kiocb, &iter);
599bd19bdc4c6 (Christoph Hellwig       2015-02-11 19:59:44 +0100  519) 	BUG_ON(ret == -EIOCBQUEUED);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  520) 	if (ret > 0 && ppos)
f765b134c0d3f (Al Viro                 2015-04-06 20:50:38 -0400  521) 		*ppos = kiocb.ki_pos;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  522) 	return ret;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  523) }
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  524) 
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  525) /* caller is responsible for file_start_write/file_end_write */
73e18f7c0b3e1 (Christoph Hellwig       2017-09-01 17:39:15 +0200  526) ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  527) {
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  528) 	struct kvec iov = {
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  529) 		.iov_base	= (void *)buf,
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  530) 		.iov_len	= min_t(size_t, count, MAX_RW_COUNT),
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  531) 	};
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  532) 	struct kiocb kiocb;
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  533) 	struct iov_iter iter;
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  534) 	ssize_t ret;
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  535) 
a01ac27be4729 (Christoph Hellwig       2020-05-08 08:55:03 +0200  536) 	if (WARN_ON_ONCE(!(file->f_mode & FMODE_WRITE)))
a01ac27be4729 (Christoph Hellwig       2020-05-08 08:55:03 +0200  537) 		return -EBADF;
7f7f25e82d548 (Al Viro                 2014-02-11 17:49:24 -0500  538) 	if (!(file->f_mode & FMODE_CAN_WRITE))
3e84f48edfd33 (Al Viro                 2013-03-27 15:20:30 +0000  539) 		return -EINVAL;
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  540) 	/*
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  541) 	 * Also fail if ->write_iter and ->write are both wired up as that
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  542) 	 * implies very convoluted semantics.
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  543) 	 */
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  544) 	if (unlikely(!file->f_op->write_iter || file->f_op->write))
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  545) 		return warn_unsupported(file, "write");
3e84f48edfd33 (Al Viro                 2013-03-27 15:20:30 +0000  546) 
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  547) 	init_sync_kiocb(&kiocb, file);
4c207ef482693 (Matthew Wilcox (Oracle) 2020-10-03 03:55:22 +0100  548) 	kiocb.ki_pos = pos ? *pos : 0;
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  549) 	iov_iter_kvec(&iter, WRITE, &iov, 1, iov.iov_len);
4d03e3cc59828 (Christoph Hellwig       2020-09-03 16:22:33 +0200  550) 	ret = file->f_op->write_iter(&kiocb, &iter);
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  551) 	if (ret > 0) {
4c207ef482693 (Matthew Wilcox (Oracle) 2020-10-03 03:55:22 +0100  552) 		if (pos)
4c207ef482693 (Matthew Wilcox (Oracle) 2020-10-03 03:55:22 +0100  553) 			*pos = kiocb.ki_pos;
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  554) 		fsnotify_modify(file);
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  555) 		add_wchar(current, ret);
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  556) 	}
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  557) 	inc_syscw(current);
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  558) 	return ret;
06ae43f34bcc0 (Al Viro                 2013-03-20 13:19:30 -0400  559) }
90fb702791bf9 (Linus Torvalds          2020-09-29 17:18:34 -0700  560) /*
90fb702791bf9 (Linus Torvalds          2020-09-29 17:18:34 -0700  561)  * This "EXPORT_SYMBOL_GPL()" is more of a "EXPORT_SYMBOL_DONTUSE()",
90fb702791bf9 (Linus Torvalds          2020-09-29 17:18:34 -0700  562)  * but autofs is one of the few internal kernel users that actually
90fb702791bf9 (Linus Torvalds          2020-09-29 17:18:34 -0700  563)  * wants this _and_ can be built as a module. So we need to export
90fb702791bf9 (Linus Torvalds          2020-09-29 17:18:34 -0700  564)  * this symbol for autofs, even though it really isn't appropriate
90fb702791bf9 (Linus Torvalds          2020-09-29 17:18:34 -0700  565)  * for any other kernel modules.
90fb702791bf9 (Linus Torvalds          2020-09-29 17:18:34 -0700  566)  */
90fb702791bf9 (Linus Torvalds          2020-09-29 17:18:34 -0700  567) EXPORT_SYMBOL_GPL(__kernel_write);
2ec3a12a66784 (Al Viro                 2014-08-19 11:48:09 -0400  568) 
e13ec939e96b1 (Christoph Hellwig       2017-09-01 17:39:14 +0200  569) ssize_t kernel_write(struct file *file, const void *buf, size_t count,
e13ec939e96b1 (Christoph Hellwig       2017-09-01 17:39:14 +0200  570) 			    loff_t *pos)
ac452acae1caa (Christoph Hellwig       2017-09-01 17:39:11 +0200  571) {
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  572) 	ssize_t ret;
ac452acae1caa (Christoph Hellwig       2017-09-01 17:39:11 +0200  573) 
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  574) 	ret = rw_verify_area(WRITE, file, pos, count);
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  575) 	if (ret)
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  576) 		return ret;
ac452acae1caa (Christoph Hellwig       2017-09-01 17:39:11 +0200  577) 
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  578) 	file_start_write(file);
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  579) 	ret =  __kernel_write(file, buf, count, pos);
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  580) 	file_end_write(file);
81238b2cff146 (Christoph Hellwig       2020-05-07 19:33:03 +0200  581) 	return ret;
ac452acae1caa (Christoph Hellwig       2017-09-01 17:39:11 +0200  582) }
ac452acae1caa (Christoph Hellwig       2017-09-01 17:39:11 +0200  583) EXPORT_SYMBOL(kernel_write);
ac452acae1caa (Christoph Hellwig       2017-09-01 17:39:11 +0200  584) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  585) ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  586) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  587) 	ssize_t ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  588) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  589) 	if (!(file->f_mode & FMODE_WRITE))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  590) 		return -EBADF;
7f7f25e82d548 (Al Viro                 2014-02-11 17:49:24 -0500  591) 	if (!(file->f_mode & FMODE_CAN_WRITE))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  592) 		return -EINVAL;
96d4f267e40f9 (Linus Torvalds          2019-01-03 18:57:57 -0800  593) 	if (unlikely(!access_ok(buf, count)))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  594) 		return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  595) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  596) 	ret = rw_verify_area(WRITE, file, pos, count);
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  597) 	if (ret)
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  598) 		return ret;
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  599) 	if (count > MAX_RW_COUNT)
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  600) 		count =  MAX_RW_COUNT;
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  601) 	file_start_write(file);
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  602) 	if (file->f_op->write)
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  603) 		ret = file->f_op->write(file, buf, count, pos);
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  604) 	else if (file->f_op->write_iter)
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  605) 		ret = new_sync_write(file, buf, count, pos);
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  606) 	else
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  607) 		ret = -EINVAL;
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  608) 	if (ret > 0) {
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  609) 		fsnotify_modify(file);
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  610) 		add_wchar(current, ret);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  611) 	}
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  612) 	inc_syscw(current);
53ad86266bda9 (Christoph Hellwig       2020-05-13 08:51:46 +0200  613) 	file_end_write(file);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  614) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  615) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  616) 
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  617) /* file_ppos returns &file->f_pos or NULL if file is stream */
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  618) static inline loff_t *file_ppos(struct file *file)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  619) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  620) 	return file->f_mode & FMODE_STREAM ? NULL : &file->f_pos;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  621) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  622) 
3ce4a7bf66263 (Dominik Brodowski       2018-03-13 21:56:26 +0100  623) ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  624) {
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  625) 	struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  626) 	ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  627) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  628) 	if (f.file) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  629) 		loff_t pos, *ppos = file_ppos(f.file);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  630) 		if (ppos) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  631) 			pos = *ppos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  632) 			ppos = &pos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  633) 		}
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  634) 		ret = vfs_read(f.file, buf, count, ppos);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  635) 		if (ret >= 0 && ppos)
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  636) 			f.file->f_pos = pos;
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  637) 		fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  638) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  639) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  640) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  641) 
3ce4a7bf66263 (Dominik Brodowski       2018-03-13 21:56:26 +0100  642) SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
3ce4a7bf66263 (Dominik Brodowski       2018-03-13 21:56:26 +0100  643) {
3ce4a7bf66263 (Dominik Brodowski       2018-03-13 21:56:26 +0100  644) 	return ksys_read(fd, buf, count);
3ce4a7bf66263 (Dominik Brodowski       2018-03-13 21:56:26 +0100  645) }
3ce4a7bf66263 (Dominik Brodowski       2018-03-13 21:56:26 +0100  646) 
e7a3e8b2edf54 (Dominik Brodowski       2018-03-11 11:34:41 +0100  647) ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  648) {
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  649) 	struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  650) 	ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  651) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  652) 	if (f.file) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  653) 		loff_t pos, *ppos = file_ppos(f.file);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  654) 		if (ppos) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  655) 			pos = *ppos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  656) 			ppos = &pos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  657) 		}
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  658) 		ret = vfs_write(f.file, buf, count, ppos);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  659) 		if (ret >= 0 && ppos)
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  660) 			f.file->f_pos = pos;
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  661) 		fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  662) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  663) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  664) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  665) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  666) 
e7a3e8b2edf54 (Dominik Brodowski       2018-03-11 11:34:41 +0100  667) SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
e7a3e8b2edf54 (Dominik Brodowski       2018-03-11 11:34:41 +0100  668) 		size_t, count)
e7a3e8b2edf54 (Dominik Brodowski       2018-03-11 11:34:41 +0100  669) {
e7a3e8b2edf54 (Dominik Brodowski       2018-03-11 11:34:41 +0100  670) 	return ksys_write(fd, buf, count);
e7a3e8b2edf54 (Dominik Brodowski       2018-03-11 11:34:41 +0100  671) }
e7a3e8b2edf54 (Dominik Brodowski       2018-03-11 11:34:41 +0100  672) 
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  673) ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count,
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  674) 		     loff_t pos)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  675) {
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  676) 	struct fd f;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  677) 	ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  678) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  679) 	if (pos < 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  680) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  681) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  682) 	f = fdget(fd);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  683) 	if (f.file) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  684) 		ret = -ESPIPE;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  685) 		if (f.file->f_mode & FMODE_PREAD)
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  686) 			ret = vfs_read(f.file, buf, count, &pos);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  687) 		fdput(f);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  688) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  689) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  690) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  691) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  692) 
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  693) SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  694) 			size_t, count, loff_t, pos)
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  695) {
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  696) 	return ksys_pread64(fd, buf, count, pos);
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  697) }
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  698) 
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  699) ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf,
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  700) 		      size_t count, loff_t pos)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  701) {
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  702) 	struct fd f;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  703) 	ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  704) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  705) 	if (pos < 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  706) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  707) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  708) 	f = fdget(fd);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  709) 	if (f.file) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  710) 		ret = -ESPIPE;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  711) 		if (f.file->f_mode & FMODE_PWRITE)  
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  712) 			ret = vfs_write(f.file, buf, count, &pos);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  713) 		fdput(f);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  714) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  715) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  716) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  717) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  718) 
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  719) SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  720) 			 size_t, count, loff_t, pos)
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  721) {
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  722) 	return ksys_pwrite64(fd, buf, count, pos);
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  723) }
36028d5dd7117 (Dominik Brodowski       2018-03-19 17:38:31 +0100  724) 
ac15ac0669d5f (Al Viro                 2015-03-20 20:10:21 -0400  725) static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  726) 		loff_t *ppos, int type, rwf_t flags)
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  727) {
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  728) 	struct kiocb kiocb;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  729) 	ssize_t ret;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  730) 
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  731) 	init_sync_kiocb(&kiocb, filp);
fdd2f5b7de2af (Goldwyn Rodrigues       2017-06-20 07:05:40 -0500  732) 	ret = kiocb_set_rw_flags(&kiocb, flags);
fdd2f5b7de2af (Goldwyn Rodrigues       2017-06-20 07:05:40 -0500  733) 	if (ret)
fdd2f5b7de2af (Goldwyn Rodrigues       2017-06-20 07:05:40 -0500  734) 		return ret;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  735) 	kiocb.ki_pos = (ppos ? *ppos : 0);
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  736) 
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  737) 	if (type == READ)
bb7462b6fd64e (Miklos Szeredi          2017-02-20 16:51:23 +0100  738) 		ret = call_read_iter(filp, &kiocb, iter);
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  739) 	else
bb7462b6fd64e (Miklos Szeredi          2017-02-20 16:51:23 +0100  740) 		ret = call_write_iter(filp, &kiocb, iter);
599bd19bdc4c6 (Christoph Hellwig       2015-02-11 19:59:44 +0100  741) 	BUG_ON(ret == -EIOCBQUEUED);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  742) 	if (ppos)
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  743) 		*ppos = kiocb.ki_pos;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  744) 	return ret;
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  745) }
293bc9822fa9b (Al Viro                 2014-02-11 18:37:41 -0500  746) 
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  747) /* Do it by hand, with file-ops */
ac15ac0669d5f (Al Viro                 2015-03-20 20:10:21 -0400  748) static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  749) 		loff_t *ppos, int type, rwf_t flags)
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  750) {
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  751) 	ssize_t ret = 0;
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  752) 
97be7ebe53915 (Christoph Hellwig       2016-03-03 16:04:01 +0100  753) 	if (flags & ~RWF_HIPRI)
793b80ef14af5 (Christoph Hellwig       2016-03-03 16:03:58 +0100  754) 		return -EOPNOTSUPP;
793b80ef14af5 (Christoph Hellwig       2016-03-03 16:03:58 +0100  755) 
ac15ac0669d5f (Al Viro                 2015-03-20 20:10:21 -0400  756) 	while (iov_iter_count(iter)) {
ac15ac0669d5f (Al Viro                 2015-03-20 20:10:21 -0400  757) 		struct iovec iovec = iov_iter_iovec(iter);
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  758) 		ssize_t nr;
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  759) 
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  760) 		if (type == READ) {
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  761) 			nr = filp->f_op->read(filp, iovec.iov_base,
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  762) 					      iovec.iov_len, ppos);
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  763) 		} else {
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  764) 			nr = filp->f_op->write(filp, iovec.iov_base,
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  765) 					       iovec.iov_len, ppos);
0f78d06ac1e9b (Miklos Szeredi          2017-02-20 16:51:23 +0100  766) 		}
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  767) 
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  768) 		if (nr < 0) {
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  769) 			if (!ret)
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  770) 				ret = nr;
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  771) 			break;
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  772) 		}
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  773) 		ret += nr;
ac15ac0669d5f (Al Viro                 2015-03-20 20:10:21 -0400  774) 		if (nr != iovec.iov_len)
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  775) 			break;
ac15ac0669d5f (Al Viro                 2015-03-20 20:10:21 -0400  776) 		iov_iter_advance(iter, nr);
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  777) 	}
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  778) 
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  779) 	return ret;
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  780) }
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  781) 
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  782) static ssize_t do_iter_read(struct file *file, struct iov_iter *iter,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  783) 		loff_t *pos, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  784) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  785) 	size_t tot_len;
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  786) 	ssize_t ret = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  787) 
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  788) 	if (!(file->f_mode & FMODE_READ))
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  789) 		return -EBADF;
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  790) 	if (!(file->f_mode & FMODE_CAN_READ))
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  791) 		return -EINVAL;
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  792) 
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  793) 	tot_len = iov_iter_count(iter);
0504c074b5466 (Al Viro                 2015-03-21 19:40:11 -0400  794) 	if (!tot_len)
0504c074b5466 (Al Viro                 2015-03-21 19:40:11 -0400  795) 		goto out;
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  796) 	ret = rw_verify_area(READ, file, pos, tot_len);
e28cc71572da3 (Linus Torvalds          2006-01-04 16:20:40 -0800  797) 	if (ret < 0)
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  798) 		return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  799) 
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  800) 	if (file->f_op->read_iter)
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  801) 		ret = do_iter_readv_writev(file, iter, pos, READ, flags);
ee0b3e671baff (Badari Pulavarty        2006-09-30 23:28:47 -0700  802) 	else
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  803) 		ret = do_loop_readv_writev(file, iter, pos, READ, flags);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  804) out:
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  805) 	if (ret >= 0)
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  806) 		fsnotify_access(file);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  807) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  808) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  809) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  810) ssize_t vfs_iocb_iter_read(struct file *file, struct kiocb *iocb,
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  811) 			   struct iov_iter *iter)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  812) {
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  813) 	size_t tot_len;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  814) 	ssize_t ret = 0;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  815) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  816) 	if (!file->f_op->read_iter)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  817) 		return -EINVAL;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  818) 	if (!(file->f_mode & FMODE_READ))
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  819) 		return -EBADF;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  820) 	if (!(file->f_mode & FMODE_CAN_READ))
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  821) 		return -EINVAL;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  822) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  823) 	tot_len = iov_iter_count(iter);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  824) 	if (!tot_len)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  825) 		goto out;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  826) 	ret = rw_verify_area(READ, file, &iocb->ki_pos, tot_len);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  827) 	if (ret < 0)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  828) 		return ret;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  829) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  830) 	ret = call_read_iter(file, iocb, iter);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  831) out:
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  832) 	if (ret >= 0)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  833) 		fsnotify_access(file);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  834) 	return ret;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  835) }
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  836) EXPORT_SYMBOL(vfs_iocb_iter_read);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  837) 
18e9710ee59ce (Christoph Hellwig       2017-05-27 11:16:51 +0300  838) ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  839) 		rwf_t flags)
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  840) {
18e9710ee59ce (Christoph Hellwig       2017-05-27 11:16:51 +0300  841) 	if (!file->f_op->read_iter)
18e9710ee59ce (Christoph Hellwig       2017-05-27 11:16:51 +0300  842) 		return -EINVAL;
18e9710ee59ce (Christoph Hellwig       2017-05-27 11:16:51 +0300  843) 	return do_iter_read(file, iter, ppos, flags);
18e9710ee59ce (Christoph Hellwig       2017-05-27 11:16:51 +0300  844) }
18e9710ee59ce (Christoph Hellwig       2017-05-27 11:16:51 +0300  845) EXPORT_SYMBOL(vfs_iter_read);
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  846) 
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  847) static ssize_t do_iter_write(struct file *file, struct iov_iter *iter,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  848) 		loff_t *pos, rwf_t flags)
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  849) {
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  850) 	size_t tot_len;
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  851) 	ssize_t ret = 0;
03d95eb2f2578 (Al Viro                 2013-03-20 13:04:20 -0400  852) 
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  853) 	if (!(file->f_mode & FMODE_WRITE))
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  854) 		return -EBADF;
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  855) 	if (!(file->f_mode & FMODE_CAN_WRITE))
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  856) 		return -EINVAL;
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  857) 
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  858) 	tot_len = iov_iter_count(iter);
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  859) 	if (!tot_len)
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  860) 		return 0;
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  861) 	ret = rw_verify_area(WRITE, file, pos, tot_len);
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  862) 	if (ret < 0)
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  863) 		return ret;
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  864) 
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  865) 	if (file->f_op->write_iter)
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  866) 		ret = do_iter_readv_writev(file, iter, pos, WRITE, flags);
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  867) 	else
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  868) 		ret = do_loop_readv_writev(file, iter, pos, WRITE, flags);
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  869) 	if (ret > 0)
19c735868dd01 (Christoph Hellwig       2017-05-27 11:16:48 +0300  870) 		fsnotify_modify(file);
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  871) 	return ret;
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  872) }
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  873) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  874) ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  875) 			    struct iov_iter *iter)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  876) {
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  877) 	size_t tot_len;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  878) 	ssize_t ret = 0;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  879) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  880) 	if (!file->f_op->write_iter)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  881) 		return -EINVAL;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  882) 	if (!(file->f_mode & FMODE_WRITE))
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  883) 		return -EBADF;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  884) 	if (!(file->f_mode & FMODE_CAN_WRITE))
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  885) 		return -EINVAL;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  886) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  887) 	tot_len = iov_iter_count(iter);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  888) 	if (!tot_len)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  889) 		return 0;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  890) 	ret = rw_verify_area(WRITE, file, &iocb->ki_pos, tot_len);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  891) 	if (ret < 0)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  892) 		return ret;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  893) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  894) 	ret = call_write_iter(file, iocb, iter);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  895) 	if (ret > 0)
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  896) 		fsnotify_modify(file);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  897) 
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  898) 	return ret;
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  899) }
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  900) EXPORT_SYMBOL(vfs_iocb_iter_write);
5dcdc43e24a18 (Jiufei Xue              2019-11-20 17:45:25 +0800  901) 
abbb65899aecf (Christoph Hellwig       2017-05-27 11:16:52 +0300  902) ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  903) 		rwf_t flags)
abbb65899aecf (Christoph Hellwig       2017-05-27 11:16:52 +0300  904) {
abbb65899aecf (Christoph Hellwig       2017-05-27 11:16:52 +0300  905) 	if (!file->f_op->write_iter)
abbb65899aecf (Christoph Hellwig       2017-05-27 11:16:52 +0300  906) 		return -EINVAL;
abbb65899aecf (Christoph Hellwig       2017-05-27 11:16:52 +0300  907) 	return do_iter_write(file, iter, ppos, flags);
abbb65899aecf (Christoph Hellwig       2017-05-27 11:16:52 +0300  908) }
abbb65899aecf (Christoph Hellwig       2017-05-27 11:16:52 +0300  909) EXPORT_SYMBOL(vfs_iter_write);
abbb65899aecf (Christoph Hellwig       2017-05-27 11:16:52 +0300  910) 
36e2c7421f02a (Christoph Hellwig       2020-09-03 16:22:34 +0200  911) static ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  912) 		  unsigned long vlen, loff_t *pos, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  913) {
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  914) 	struct iovec iovstack[UIO_FASTIOV];
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  915) 	struct iovec *iov = iovstack;
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  916) 	struct iov_iter iter;
7687a7a4435f4 (Miklos Szeredi          2017-02-20 16:51:23 +0100  917) 	ssize_t ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  918) 
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  919) 	ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  920) 	if (ret >= 0) {
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  921) 		ret = do_iter_read(file, &iter, pos, flags);
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  922) 		kfree(iov);
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  923) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  924) 
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  925) 	return ret;
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  926) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  927) 
9725d4cef6222 (Christoph Hellwig       2017-09-01 17:39:25 +0200  928) static ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  929) 		   unsigned long vlen, loff_t *pos, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  930) {
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  931) 	struct iovec iovstack[UIO_FASTIOV];
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  932) 	struct iovec *iov = iovstack;
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  933) 	struct iov_iter iter;
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  934) 	ssize_t ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  935) 
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  936) 	ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  937) 	if (ret >= 0) {
62473a2d6f513 (Al Viro                 2017-07-06 09:15:47 -0400  938) 		file_start_write(file);
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  939) 		ret = do_iter_write(file, &iter, pos, flags);
62473a2d6f513 (Al Viro                 2017-07-06 09:15:47 -0400  940) 		file_end_write(file);
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  941) 		kfree(iov);
edab5fe38c2c1 (Christoph Hellwig       2017-05-27 11:16:49 +0300  942) 	}
251b42a1dc641 (Christoph Hellwig       2017-05-27 11:16:46 +0300  943) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  944) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  945) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100  946) static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  947) 			unsigned long vlen, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  948) {
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  949) 	struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  950) 	ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  951) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  952) 	if (f.file) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  953) 		loff_t pos, *ppos = file_ppos(f.file);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  954) 		if (ppos) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  955) 			pos = *ppos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  956) 			ppos = &pos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  957) 		}
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  958) 		ret = vfs_readv(f.file, vec, vlen, ppos, flags);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  959) 		if (ret >= 0 && ppos)
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  960) 			f.file->f_pos = pos;
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  961) 		fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  962) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  963) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  964) 	if (ret > 0)
4b98d11b40f03 (Alexey Dobriyan         2007-02-10 01:46:45 -0800  965) 		add_rchar(current, ret);
4b98d11b40f03 (Alexey Dobriyan         2007-02-10 01:46:45 -0800  966) 	inc_syscr(current);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  967) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  968) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  969) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100  970) static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200  971) 			 unsigned long vlen, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  972) {
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  973) 	struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  974) 	ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  975) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400  976) 	if (f.file) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  977) 		loff_t pos, *ppos = file_ppos(f.file);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  978) 		if (ppos) {
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  979) 			pos = *ppos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  980) 			ppos = &pos;
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  981) 		}
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  982) 		ret = vfs_writev(f.file, vec, vlen, ppos, flags);
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  983) 		if (ret >= 0 && ppos)
438ab720c675a (Kirill Smelkov          2019-04-12 12:31:57 +0300  984) 			f.file->f_pos = pos;
9c225f2655e36 (Linus Torvalds          2014-03-03 09:36:58 -0800  985) 		fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  986) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  987) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  988) 	if (ret > 0)
4b98d11b40f03 (Alexey Dobriyan         2007-02-10 01:46:45 -0800  989) 		add_wchar(current, ret);
4b98d11b40f03 (Alexey Dobriyan         2007-02-10 01:46:45 -0800  990) 	inc_syscw(current);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  991) 	return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  992) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  993) 
601cc11d054ae (Linus Torvalds          2009-04-03 08:03:22 -0700  994) static inline loff_t pos_from_hilo(unsigned long high, unsigned long low)
601cc11d054ae (Linus Torvalds          2009-04-03 08:03:22 -0700  995) {
601cc11d054ae (Linus Torvalds          2009-04-03 08:03:22 -0700  996) #define HALF_LONG_BITS (BITS_PER_LONG / 2)
601cc11d054ae (Linus Torvalds          2009-04-03 08:03:22 -0700  997) 	return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low;
601cc11d054ae (Linus Torvalds          2009-04-03 08:03:22 -0700  998) }
601cc11d054ae (Linus Torvalds          2009-04-03 08:03:22 -0700  999) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1000) static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200 1001) 			 unsigned long vlen, loff_t pos, rwf_t flags)
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1002) {
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1003) 	struct fd f;
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1004) 	ssize_t ret = -EBADF;
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1005) 
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1006) 	if (pos < 0)
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1007) 		return -EINVAL;
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1008) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1009) 	f = fdget(fd);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1010) 	if (f.file) {
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1011) 		ret = -ESPIPE;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1012) 		if (f.file->f_mode & FMODE_PREAD)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1013) 			ret = vfs_readv(f.file, vec, vlen, &pos, flags);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1014) 		fdput(f);
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1015) 	}
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1016) 
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1017) 	if (ret > 0)
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1018) 		add_rchar(current, ret);
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1019) 	inc_syscr(current);
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1020) 	return ret;
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1021) }
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1022) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1023) static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200 1024) 			  unsigned long vlen, loff_t pos, rwf_t flags)
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1025) {
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1026) 	struct fd f;
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1027) 	ssize_t ret = -EBADF;
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1028) 
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1029) 	if (pos < 0)
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1030) 		return -EINVAL;
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1031) 
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1032) 	f = fdget(fd);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1033) 	if (f.file) {
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1034) 		ret = -ESPIPE;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1035) 		if (f.file->f_mode & FMODE_PWRITE)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1036) 			ret = vfs_writev(f.file, vec, vlen, &pos, flags);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1037) 		fdput(f);
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1038) 	}
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1039) 
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1040) 	if (ret > 0)
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1041) 		add_wchar(current, ret);
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1042) 	inc_syscw(current);
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1043) 	return ret;
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1044) }
f3554f4bc6980 (Gerd Hoffmann           2009-04-02 16:59:23 -0700 1045) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1046) SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1047) 		unsigned long, vlen)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1048) {
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1049) 	return do_readv(fd, vec, vlen, 0);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1050) }
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1051) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1052) SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1053) 		unsigned long, vlen)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1054) {
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1055) 	return do_writev(fd, vec, vlen, 0);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1056) }
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1057) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1058) SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1059) 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1060) {
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1061) 	loff_t pos = pos_from_hilo(pos_h, pos_l);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1062) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1063) 	return do_preadv(fd, vec, vlen, pos, 0);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1064) }
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1065) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1066) SYSCALL_DEFINE6(preadv2, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1067) 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200 1068) 		rwf_t, flags)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1069) {
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1070) 	loff_t pos = pos_from_hilo(pos_h, pos_l);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1071) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1072) 	if (pos == -1)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1073) 		return do_readv(fd, vec, vlen, flags);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1074) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1075) 	return do_preadv(fd, vec, vlen, pos, flags);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1076) }
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1077) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1078) SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1079) 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1080) {
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1081) 	loff_t pos = pos_from_hilo(pos_h, pos_l);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1082) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1083) 	return do_pwritev(fd, vec, vlen, pos, 0);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1084) }
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1085) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1086) SYSCALL_DEFINE6(pwritev2, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1087) 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200 1088) 		rwf_t, flags)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1089) {
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1090) 	loff_t pos = pos_from_hilo(pos_h, pos_l);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1091) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1092) 	if (pos == -1)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1093) 		return do_writev(fd, vec, vlen, flags);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1094) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1095) 	return do_pwritev(fd, vec, vlen, pos, flags);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1096) }
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1097) 
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1098) /*
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1099)  * Various compat syscalls.  Note that they all pretend to take a native
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1100)  * iovec - import_iovec will properly treat those as compat_iovecs based on
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1101)  * in_compat_syscall().
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1102)  */
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1103) #ifdef CONFIG_COMPAT
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1104) #ifdef __ARCH_WANT_COMPAT_SYS_PREADV64
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1105) COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1106) 		const struct iovec __user *, vec,
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1107) 		unsigned long, vlen, loff_t, pos)
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1108) {
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1109) 	return do_preadv(fd, vec, vlen, pos, 0);
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1110) }
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1111) #endif
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1112) 
dfd948e32af2e (Heiko Carstens          2014-01-29 14:05:44 -0800 1113) COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1114) 		const struct iovec __user *, vec,
dfd948e32af2e (Heiko Carstens          2014-01-29 14:05:44 -0800 1115) 		compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1116) {
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1117) 	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1118) 
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1119) 	return do_preadv(fd, vec, vlen, pos, 0);
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1120) }
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1121) 
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1122) #ifdef __ARCH_WANT_COMPAT_SYS_PREADV64V2
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1123) COMPAT_SYSCALL_DEFINE5(preadv64v2, unsigned long, fd,
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1124) 		const struct iovec __user *, vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200 1125) 		unsigned long, vlen, loff_t, pos, rwf_t, flags)
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1126) {
cc4b1242d7e3b (Aurelien Jarno          2018-12-06 20:05:34 +0100 1127) 	if (pos == -1)
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1128) 		return do_readv(fd, vec, vlen, flags);
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1129) 	return do_preadv(fd, vec, vlen, pos, flags);
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1130) }
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1131) #endif
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1132) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1133) COMPAT_SYSCALL_DEFINE6(preadv2, compat_ulong_t, fd,
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1134) 		const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1135) 		compat_ulong_t, vlen, u32, pos_low, u32, pos_high,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200 1136) 		rwf_t, flags)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1137) {
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1138) 	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1139) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1140) 	if (pos == -1)
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1141) 		return do_readv(fd, vec, vlen, flags);
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1142) 	return do_preadv(fd, vec, vlen, pos, flags);
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1143) }
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1144) 
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1145) #ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1146) COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1147) 		const struct iovec __user *, vec,
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1148) 		unsigned long, vlen, loff_t, pos)
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1149) {
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1150) 	return do_pwritev(fd, vec, vlen, pos, 0);
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1151) }
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1152) #endif
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1153) 
dfd948e32af2e (Heiko Carstens          2014-01-29 14:05:44 -0800 1154) COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1155) 		const struct iovec __user *,vec,
dfd948e32af2e (Heiko Carstens          2014-01-29 14:05:44 -0800 1156) 		compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1157) {
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1158) 	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
378a10f3ae2e8 (Heiko Carstens          2014-03-05 10:43:51 +0100 1159) 
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1160) 	return do_pwritev(fd, vec, vlen, pos, 0);
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1161) }
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1162) 
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1163) #ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64V2
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1164) COMPAT_SYSCALL_DEFINE5(pwritev64v2, unsigned long, fd,
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1165) 		const struct iovec __user *, vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200 1166) 		unsigned long, vlen, loff_t, pos, rwf_t, flags)
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1167) {
cc4b1242d7e3b (Aurelien Jarno          2018-12-06 20:05:34 +0100 1168) 	if (pos == -1)
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1169) 		return do_writev(fd, vec, vlen, flags);
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1170) 	return do_pwritev(fd, vec, vlen, pos, flags);
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1171) }
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1172) #endif
3ebfd81f7fb3e (H.J. Lu                 2016-07-14 12:31:53 -0700 1173) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1174) COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd,
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1175) 		const struct iovec __user *,vec,
ddef7ed2b5cba (Christoph Hellwig       2017-07-06 18:58:37 +0200 1176) 		compat_ulong_t, vlen, u32, pos_low, u32, pos_high, rwf_t, flags)
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1177) {
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1178) 	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1179) 
f17d8b35452ca (Milosz Tanski           2016-03-03 16:03:59 +0100 1180) 	if (pos == -1)
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1181) 		return do_writev(fd, vec, vlen, flags);
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1182) 	return do_pwritev(fd, vec, vlen, pos, flags);
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1183) }
3523a9d454789 (Christoph Hellwig       2020-09-25 06:51:42 +0200 1184) #endif /* CONFIG_COMPAT */
72ec35163f9f7 (Al Viro                 2013-03-20 10:42:10 -0400 1185) 
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1186) static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1187) 		  	   size_t count, loff_t max)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1188) {
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1189) 	struct fd in, out;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1190) 	struct inode *in_inode, *out_inode;
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1191) 	struct pipe_inode_info *opipe;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1192) 	loff_t pos;
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1193) 	loff_t out_pos;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1194) 	ssize_t retval;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1195) 	int fl;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1196) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1197) 	/*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1198) 	 * Get input file, and verify that it is ok..
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1199) 	 */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1200) 	retval = -EBADF;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1201) 	in = fdget(in_fd);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1202) 	if (!in.file)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1203) 		goto out;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1204) 	if (!(in.file->f_mode & FMODE_READ))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1205) 		goto fput_in;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1206) 	retval = -ESPIPE;
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1207) 	if (!ppos) {
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1208) 		pos = in.file->f_pos;
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1209) 	} else {
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1210) 		pos = *ppos;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1211) 		if (!(in.file->f_mode & FMODE_PREAD))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1212) 			goto fput_in;
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1213) 	}
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1214) 	retval = rw_verify_area(READ, in.file, &pos, count);
e28cc71572da3 (Linus Torvalds          2006-01-04 16:20:40 -0800 1215) 	if (retval < 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1216) 		goto fput_in;
bc61384dcdd82 (Al Viro                 2016-03-31 21:48:20 -0400 1217) 	if (count > MAX_RW_COUNT)
bc61384dcdd82 (Al Viro                 2016-03-31 21:48:20 -0400 1218) 		count =  MAX_RW_COUNT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1219) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1220) 	/*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1221) 	 * Get output file, and verify that it is ok..
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1222) 	 */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1223) 	retval = -EBADF;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1224) 	out = fdget(out_fd);
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1225) 	if (!out.file)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1226) 		goto fput_in;
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1227) 	if (!(out.file->f_mode & FMODE_WRITE))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1228) 		goto fput_out;
496ad9aa8ef44 (Al Viro                 2013-01-23 17:07:38 -0500 1229) 	in_inode = file_inode(in.file);
496ad9aa8ef44 (Al Viro                 2013-01-23 17:07:38 -0500 1230) 	out_inode = file_inode(out.file);
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1231) 	out_pos = out.file->f_pos;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1232) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1233) 	if (!max)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1234) 		max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1235) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1236) 	if (unlikely(pos + count > max)) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1237) 		retval = -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1238) 		if (pos >= max)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1239) 			goto fput_out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1240) 		count = max - pos;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1241) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1242) 
d96e6e7164784 (Jens Axboe              2007-06-11 12:18:52 +0200 1243) 	fl = 0;
534f2aaa6ab07 (Jens Axboe              2007-06-01 14:52:37 +0200 1244) #if 0
d96e6e7164784 (Jens Axboe              2007-06-11 12:18:52 +0200 1245) 	/*
d96e6e7164784 (Jens Axboe              2007-06-11 12:18:52 +0200 1246) 	 * We need to debate whether we can enable this or not. The
d96e6e7164784 (Jens Axboe              2007-06-11 12:18:52 +0200 1247) 	 * man page documents EAGAIN return for the output at least,
d96e6e7164784 (Jens Axboe              2007-06-11 12:18:52 +0200 1248) 	 * and the application is arguably buggy if it doesn't expect
d96e6e7164784 (Jens Axboe              2007-06-11 12:18:52 +0200 1249) 	 * EAGAIN on a non-blocking file descriptor.
d96e6e7164784 (Jens Axboe              2007-06-11 12:18:52 +0200 1250) 	 */
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1251) 	if (in.file->f_flags & O_NONBLOCK)
d96e6e7164784 (Jens Axboe              2007-06-11 12:18:52 +0200 1252) 		fl = SPLICE_F_NONBLOCK;
534f2aaa6ab07 (Jens Axboe              2007-06-01 14:52:37 +0200 1253) #endif
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1254) 	opipe = get_pipe_info(out.file, true);
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1255) 	if (!opipe) {
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1256) 		retval = rw_verify_area(WRITE, out.file, &out_pos, count);
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1257) 		if (retval < 0)
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1258) 			goto fput_out;
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1259) 		file_start_write(out.file);
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1260) 		retval = do_splice_direct(in.file, &pos, out.file, &out_pos,
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1261) 					  count, fl);
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1262) 		file_end_write(out.file);
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1263) 	} else {
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1264) 		retval = splice_file_to_pipe(in.file, opipe, &pos, count, fl);
b964bf53e5402 (Al Viro                 2021-01-25 22:24:28 -0500 1265) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1266) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1267) 	if (retval > 0) {
4b98d11b40f03 (Alexey Dobriyan         2007-02-10 01:46:45 -0800 1268) 		add_rchar(current, retval);
4b98d11b40f03 (Alexey Dobriyan         2007-02-10 01:46:45 -0800 1269) 		add_wchar(current, retval);
a68c2f12b4b28 (Scott Wolchok           2012-12-20 15:05:52 -0800 1270) 		fsnotify_access(in.file);
a68c2f12b4b28 (Scott Wolchok           2012-12-20 15:05:52 -0800 1271) 		fsnotify_modify(out.file);
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1272) 		out.file->f_pos = out_pos;
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1273) 		if (ppos)
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1274) 			*ppos = pos;
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1275) 		else
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1276) 			in.file->f_pos = pos;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1277) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1278) 
4b98d11b40f03 (Alexey Dobriyan         2007-02-10 01:46:45 -0800 1279) 	inc_syscr(current);
4b98d11b40f03 (Alexey Dobriyan         2007-02-10 01:46:45 -0800 1280) 	inc_syscw(current);
7995bd287134f (Al Viro                 2013-06-20 18:58:36 +0400 1281) 	if (pos > max)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1282) 		retval = -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1283) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1284) fput_out:
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1285) 	fdput(out);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1286) fput_in:
2903ff019b346 (Al Viro                 2012-08-28 12:52:22 -0400 1287) 	fdput(in);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1288) out:
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1289) 	return retval;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1290) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1291) 
002c8976ee537 (Heiko Carstens          2009-01-14 14:14:18 +0100 1292) SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd, off_t __user *, offset, size_t, count)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1293) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1294) 	loff_t pos;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1295) 	off_t off;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1296) 	ssize_t ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1297) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1298) 	if (offset) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1299) 		if (unlikely(get_user(off, offset)))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1300) 			return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1301) 		pos = off;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1302) 		ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1303) 		if (unlikely(put_user(pos, offset)))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1304) 			return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1305) 		return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1306) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1307) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1308) 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1309) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1310) 
002c8976ee537 (Heiko Carstens          2009-01-14 14:14:18 +0100 1311) SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, size_t, count)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1312) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1313) 	loff_t pos;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1314) 	ssize_t ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1315) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1316) 	if (offset) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1317) 		if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1318) 			return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1319) 		ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1320) 		if (unlikely(put_user(pos, offset)))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1321) 			return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1322) 		return ret;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1323) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1324) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1325) 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1326) }
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1327) 
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1328) #ifdef CONFIG_COMPAT
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1329) COMPAT_SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd,
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1330) 		compat_off_t __user *, offset, compat_size_t, count)
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1331) {
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1332) 	loff_t pos;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1333) 	off_t off;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1334) 	ssize_t ret;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1335) 
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1336) 	if (offset) {
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1337) 		if (unlikely(get_user(off, offset)))
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1338) 			return -EFAULT;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1339) 		pos = off;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1340) 		ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1341) 		if (unlikely(put_user(pos, offset)))
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1342) 			return -EFAULT;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1343) 		return ret;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1344) 	}
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1345) 
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1346) 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1347) }
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1348) 
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1349) COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd,
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1350) 		compat_loff_t __user *, offset, compat_size_t, count)
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1351) {
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1352) 	loff_t pos;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1353) 	ssize_t ret;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1354) 
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1355) 	if (offset) {
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1356) 		if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1357) 			return -EFAULT;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1358) 		ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1359) 		if (unlikely(put_user(pos, offset)))
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1360) 			return -EFAULT;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1361) 		return ret;
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1362) 	}
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1363) 
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1364) 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1365) }
19f4fc3aee180 (Al Viro                 2013-02-24 02:17:03 -0500 1366) #endif
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1367) 
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1368) /**
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1369)  * generic_copy_file_range - copy data between two files
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1370)  * @file_in:	file structure to read from
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1371)  * @pos_in:	file offset to read from
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1372)  * @file_out:	file structure to write data to
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1373)  * @pos_out:	file offset to write data to
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1374)  * @len:	amount of data to copy
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1375)  * @flags:	copy flags
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1376)  *
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1377)  * This is a generic filesystem helper to copy data from one file to another.
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1378)  * It has no constraints on the source or destination file owners - the files
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1379)  * can belong to different superblocks and different filesystem types. Short
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1380)  * copies are allowed.
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1381)  *
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1382)  * This should be called from the @file_out filesystem, as per the
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1383)  * ->copy_file_range() method.
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1384)  *
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1385)  * Returns the number of bytes copied or a negative error indicating the
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1386)  * failure.
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1387)  */
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1388) 
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1389) ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1390) 				struct file *file_out, loff_t pos_out,
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1391) 				size_t len, unsigned int flags)
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1392) {
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1393) 	return do_splice_direct(file_in, &pos_in, file_out, &pos_out,
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1394) 				len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1395) }
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1396) EXPORT_SYMBOL(generic_copy_file_range);
f16acc9d9b376 (Dave Chinner            2019-06-05 08:04:47 -0700 1397) 
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1398) static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in,
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1399) 				  struct file *file_out, loff_t pos_out,
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1400) 				  size_t len, unsigned int flags)
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1401) {
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1402) 	/*
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1403) 	 * Although we now allow filesystems to handle cross sb copy, passing
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1404) 	 * a file of the wrong filesystem type to filesystem driver can result
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1405) 	 * in an attempt to dereference the wrong type of ->private_data, so
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1406) 	 * avoid doing that until we really have a good reason.  NFS defines
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1407) 	 * several different file_system_type structures, but they all end up
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1408) 	 * using the same ->copy_file_range() function pointer.
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1409) 	 */
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1410) 	if (file_out->f_op->copy_file_range &&
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1411) 	    file_out->f_op->copy_file_range == file_in->f_op->copy_file_range)
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1412) 		return file_out->f_op->copy_file_range(file_in, pos_in,
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1413) 						       file_out, pos_out,
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1414) 						       len, flags);
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1415) 
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1416) 	return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1417) 				       flags);
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1418) }
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1419) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1420) /*
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1421)  * Performs necessary checks before doing a file copy
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1422)  *
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1423)  * Can adjust amount of bytes to copy via @req_count argument.
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1424)  * Returns appropriate error code that caller should return or
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1425)  * zero in case the copy should be allowed.
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1426)  */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1427) static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1428) 				    struct file *file_out, loff_t pos_out,
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1429) 				    size_t *req_count, unsigned int flags)
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1430) {
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1431) 	struct inode *inode_in = file_inode(file_in);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1432) 	struct inode *inode_out = file_inode(file_out);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1433) 	uint64_t count = *req_count;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1434) 	loff_t size_in;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1435) 	int ret;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1436) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1437) 	ret = generic_file_rw_checks(file_in, file_out);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1438) 	if (ret)
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1439) 		return ret;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1440) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1441) 	/* Don't touch certain kinds of inodes */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1442) 	if (IS_IMMUTABLE(inode_out))
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1443) 		return -EPERM;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1444) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1445) 	if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out))
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1446) 		return -ETXTBSY;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1447) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1448) 	/* Ensure offsets don't wrap. */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1449) 	if (pos_in + count < pos_in || pos_out + count < pos_out)
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1450) 		return -EOVERFLOW;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1451) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1452) 	/* Shorten the copy to EOF */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1453) 	size_in = i_size_read(inode_in);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1454) 	if (pos_in >= size_in)
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1455) 		count = 0;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1456) 	else
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1457) 		count = min(count, size_in - (uint64_t)pos_in);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1458) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1459) 	ret = generic_write_check_limits(file_out, pos_out, &count);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1460) 	if (ret)
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1461) 		return ret;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1462) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1463) 	/* Don't allow overlapped copying within the same file. */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1464) 	if (inode_in == inode_out &&
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1465) 	    pos_out + count > pos_in &&
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1466) 	    pos_out < pos_in + count)
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1467) 		return -EINVAL;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1468) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1469) 	*req_count = count;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1470) 	return 0;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1471) }
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1472) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1473) /*
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1474)  * copy_file_range() differs from regular file read and write in that it
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1475)  * specifically allows return partial success.  When it does so is up to
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1476)  * the copy_file_range method.
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1477)  */
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1478) ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1479) 			    struct file *file_out, loff_t pos_out,
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1480) 			    size_t len, unsigned int flags)
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1481) {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1482) 	ssize_t ret;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1483) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1484) 	if (flags != 0)
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1485) 		return -EINVAL;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1486) 
96e6e8f4a68df (Amir Goldstein          2019-06-05 08:04:49 -0700 1487) 	ret = generic_copy_file_checks(file_in, pos_in, file_out, pos_out, &len,
96e6e8f4a68df (Amir Goldstein          2019-06-05 08:04:49 -0700 1488) 				       flags);
a31713517dac0 (Amir Goldstein          2019-06-05 08:04:48 -0700 1489) 	if (unlikely(ret))
a31713517dac0 (Amir Goldstein          2019-06-05 08:04:48 -0700 1490) 		return ret;
11cbfb10775aa (Amir Goldstein          2017-01-31 10:34:56 +0200 1491) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1492) 	ret = rw_verify_area(READ, file_in, &pos_in, len);
bc61384dcdd82 (Al Viro                 2016-03-31 21:48:20 -0400 1493) 	if (unlikely(ret))
bc61384dcdd82 (Al Viro                 2016-03-31 21:48:20 -0400 1494) 		return ret;
bc61384dcdd82 (Al Viro                 2016-03-31 21:48:20 -0400 1495) 
bc61384dcdd82 (Al Viro                 2016-03-31 21:48:20 -0400 1496) 	ret = rw_verify_area(WRITE, file_out, &pos_out, len);
bc61384dcdd82 (Al Viro                 2016-03-31 21:48:20 -0400 1497) 	if (unlikely(ret))
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1498) 		return ret;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1499) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1500) 	if (len == 0)
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1501) 		return 0;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1502) 
bfe219d373cad (Amir Goldstein          2017-01-31 10:34:57 +0200 1503) 	file_start_write(file_out);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1504) 
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1505) 	/*
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1506) 	 * Try cloning first, this is supported by more file systems, and
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1507) 	 * more efficient if both clone and copy are supported (e.g. NFS).
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1508) 	 */
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1509) 	if (file_in->f_op->remap_file_range &&
5dae222a5ff0c (Amir Goldstein          2019-06-05 08:04:50 -0700 1510) 	    file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) {
42ec3d4c02187 (Darrick J. Wong         2018-10-30 10:41:49 +1100 1511) 		loff_t cloned;
42ec3d4c02187 (Darrick J. Wong         2018-10-30 10:41:49 +1100 1512) 
42ec3d4c02187 (Darrick J. Wong         2018-10-30 10:41:49 +1100 1513) 		cloned = file_in->f_op->remap_file_range(file_in, pos_in,
42ec3d4c02187 (Darrick J. Wong         2018-10-30 10:41:49 +1100 1514) 				file_out, pos_out,
eca3654e3cc7d (Darrick J. Wong         2018-10-30 10:42:10 +1100 1515) 				min_t(loff_t, MAX_RW_COUNT, len),
eca3654e3cc7d (Darrick J. Wong         2018-10-30 10:42:10 +1100 1516) 				REMAP_FILE_CAN_SHORTEN);
42ec3d4c02187 (Darrick J. Wong         2018-10-30 10:41:49 +1100 1517) 		if (cloned > 0) {
42ec3d4c02187 (Darrick J. Wong         2018-10-30 10:41:49 +1100 1518) 			ret = cloned;
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1519) 			goto done;
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1520) 		}
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1521) 	}
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1522) 
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1523) 	ret = do_copy_file_range(file_in, pos_in, file_out, pos_out, len,
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1524) 				flags);
64bf5ff58dff7 (Dave Chinner            2019-06-05 08:04:47 -0700 1525) 	WARN_ON_ONCE(ret == -EOPNOTSUPP);
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1526) done:
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1527) 	if (ret > 0) {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1528) 		fsnotify_access(file_in);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1529) 		add_rchar(current, ret);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1530) 		fsnotify_modify(file_out);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1531) 		add_wchar(current, ret);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1532) 	}
a76b5b04375f9 (Christoph Hellwig       2016-12-09 16:17:19 -0800 1533) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1534) 	inc_syscr(current);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1535) 	inc_syscw(current);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1536) 
bfe219d373cad (Amir Goldstein          2017-01-31 10:34:57 +0200 1537) 	file_end_write(file_out);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1538) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1539) 	return ret;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1540) }
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1541) EXPORT_SYMBOL(vfs_copy_file_range);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1542) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1543) SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in,
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1544) 		int, fd_out, loff_t __user *, off_out,
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1545) 		size_t, len, unsigned int, flags)
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1546) {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1547) 	loff_t pos_in;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1548) 	loff_t pos_out;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1549) 	struct fd f_in;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1550) 	struct fd f_out;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1551) 	ssize_t ret = -EBADF;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1552) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1553) 	f_in = fdget(fd_in);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1554) 	if (!f_in.file)
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1555) 		goto out2;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1556) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1557) 	f_out = fdget(fd_out);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1558) 	if (!f_out.file)
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1559) 		goto out1;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1560) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1561) 	ret = -EFAULT;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1562) 	if (off_in) {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1563) 		if (copy_from_user(&pos_in, off_in, sizeof(loff_t)))
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1564) 			goto out;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1565) 	} else {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1566) 		pos_in = f_in.file->f_pos;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1567) 	}
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1568) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1569) 	if (off_out) {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1570) 		if (copy_from_user(&pos_out, off_out, sizeof(loff_t)))
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1571) 			goto out;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1572) 	} else {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1573) 		pos_out = f_out.file->f_pos;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1574) 	}
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1575) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1576) 	ret = vfs_copy_file_range(f_in.file, pos_in, f_out.file, pos_out, len,
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1577) 				  flags);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1578) 	if (ret > 0) {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1579) 		pos_in += ret;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1580) 		pos_out += ret;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1581) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1582) 		if (off_in) {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1583) 			if (copy_to_user(off_in, &pos_in, sizeof(loff_t)))
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1584) 				ret = -EFAULT;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1585) 		} else {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1586) 			f_in.file->f_pos = pos_in;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1587) 		}
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1588) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1589) 		if (off_out) {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1590) 			if (copy_to_user(off_out, &pos_out, sizeof(loff_t)))
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1591) 				ret = -EFAULT;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1592) 		} else {
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1593) 			f_out.file->f_pos = pos_out;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1594) 		}
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1595) 	}
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1596) 
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1597) out:
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1598) 	fdput(f_out);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1599) out1:
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1600) 	fdput(f_in);
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1601) out2:
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1602) 	return ret;
29732938a6289 (Zach Brown              2015-11-10 16:53:30 -0500 1603) }
04b38d601239b (Christoph Hellwig       2015-12-03 12:59:50 +0100 1604) 
edc58dd0123b5 (Darrick J. Wong         2019-08-11 15:52:25 -0700 1605) /*
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1606)  * Don't operate on ranges the page cache doesn't support, and don't exceed the
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1607)  * LFS limits.  If pos is under the limit it becomes a short access.  If it
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1608)  * exceeds the limit we return -EFBIG.
edc58dd0123b5 (Darrick J. Wong         2019-08-11 15:52:25 -0700 1609)  */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1610) int generic_write_check_limits(struct file *file, loff_t pos, loff_t *count)
edc58dd0123b5 (Darrick J. Wong         2019-08-11 15:52:25 -0700 1611) {
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1612) 	struct inode *inode = file->f_mapping->host;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1613) 	loff_t max_size = inode->i_sb->s_maxbytes;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1614) 	loff_t limit = rlimit(RLIMIT_FSIZE);
edc58dd0123b5 (Darrick J. Wong         2019-08-11 15:52:25 -0700 1615) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1616) 	if (limit != RLIM_INFINITY) {
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1617) 		if (pos >= limit) {
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1618) 			send_sig(SIGXFSZ, current, 0);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1619) 			return -EFBIG;
edc58dd0123b5 (Darrick J. Wong         2019-08-11 15:52:25 -0700 1620) 		}
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1621) 		*count = min(*count, limit - pos);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1622) 	}
edc58dd0123b5 (Darrick J. Wong         2019-08-11 15:52:25 -0700 1623) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1624) 	if (!(file->f_flags & O_LARGEFILE))
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1625) 		max_size = MAX_NON_LFS;
c32e5f39953fa (Darrick J. Wong         2018-10-30 10:42:17 +1100 1626) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1627) 	if (unlikely(pos >= max_size))
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1628) 		return -EFBIG;
c32e5f39953fa (Darrick J. Wong         2018-10-30 10:42:17 +1100 1629) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1630) 	*count = min(*count, max_size - pos);
c32e5f39953fa (Darrick J. Wong         2018-10-30 10:42:17 +1100 1631) 
c32e5f39953fa (Darrick J. Wong         2018-10-30 10:42:17 +1100 1632) 	return 0;
c32e5f39953fa (Darrick J. Wong         2018-10-30 10:42:17 +1100 1633) }
04b38d601239b (Christoph Hellwig       2015-12-03 12:59:50 +0100 1634) 
876bec6f9bbfc (Darrick J. Wong         2016-12-09 16:18:30 -0800 1635) /*
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1636)  * Performs necessary checks before doing a write
22725ce4e4a00 (Darrick J. Wong         2016-12-19 15:13:26 -0800 1637)  *
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1638)  * Can adjust writing position or amount of bytes to write.
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1639)  * Returns appropriate error code that caller should return or
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1640)  * zero in case that write should be allowed.
876bec6f9bbfc (Darrick J. Wong         2016-12-09 16:18:30 -0800 1641)  */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1642) ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
876bec6f9bbfc (Darrick J. Wong         2016-12-09 16:18:30 -0800 1643) {
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1644) 	struct file *file = iocb->ki_filp;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1645) 	struct inode *inode = file->f_mapping->host;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1646) 	loff_t count;
876bec6f9bbfc (Darrick J. Wong         2016-12-09 16:18:30 -0800 1647) 	int ret;
876bec6f9bbfc (Darrick J. Wong         2016-12-09 16:18:30 -0800 1648) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1649) 	if (IS_SWAPFILE(inode))
876bec6f9bbfc (Darrick J. Wong         2016-12-09 16:18:30 -0800 1650) 		return -ETXTBSY;
876bec6f9bbfc (Darrick J. Wong         2016-12-09 16:18:30 -0800 1651) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1652) 	if (!iov_iter_count(from))
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1653) 		return 0;
5de4480ae7f8f (Mark Fasheh             2018-09-10 16:21:17 -0700 1654) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1655) 	/* FIXME: this is for backwards compatibility with 2.4 */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1656) 	if (iocb->ki_flags & IOCB_APPEND)
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1657) 		iocb->ki_pos = i_size_read(inode);
1b4f42a1e33fe (Miklos Szeredi          2018-07-06 23:57:03 +0200 1658) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1659) 	if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1660) 		return -EINVAL;
1b4f42a1e33fe (Miklos Szeredi          2018-07-06 23:57:03 +0200 1661) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1662) 	count = iov_iter_count(from);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1663) 	ret = generic_write_check_limits(file, iocb->ki_pos, &count);
1b4f42a1e33fe (Miklos Szeredi          2018-07-06 23:57:03 +0200 1664) 	if (ret)
1b4f42a1e33fe (Miklos Szeredi          2018-07-06 23:57:03 +0200 1665) 		return ret;
1b4f42a1e33fe (Miklos Szeredi          2018-07-06 23:57:03 +0200 1666) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1667) 	iov_iter_truncate(from, count);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1668) 	return iov_iter_count(from);
1b4f42a1e33fe (Miklos Szeredi          2018-07-06 23:57:03 +0200 1669) }
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1670) EXPORT_SYMBOL(generic_write_checks);
1b4f42a1e33fe (Miklos Szeredi          2018-07-06 23:57:03 +0200 1671) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1672) /*
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1673)  * Performs common checks before doing a file copy/clone
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1674)  * from @file_in to @file_out.
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1675)  */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1676) int generic_file_rw_checks(struct file *file_in, struct file *file_out)
54dbc15172375 (Darrick J. Wong         2015-12-19 00:55:59 -0800 1677) {
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1678) 	struct inode *inode_in = file_inode(file_in);
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1679) 	struct inode *inode_out = file_inode(file_out);
54dbc15172375 (Darrick J. Wong         2015-12-19 00:55:59 -0800 1680) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1681) 	/* Don't copy dirs, pipes, sockets... */
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1682) 	if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
494633fac7896 (Dave Chinner            2018-11-19 13:31:12 -0800 1683) 		return -EISDIR;
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1684) 	if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
22725ce4e4a00 (Darrick J. Wong         2016-12-19 15:13:26 -0800 1685) 		return -EINVAL;
22725ce4e4a00 (Darrick J. Wong         2016-12-19 15:13:26 -0800 1686) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1687) 	if (!(file_in->f_mode & FMODE_READ) ||
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1688) 	    !(file_out->f_mode & FMODE_WRITE) ||
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1689) 	    (file_out->f_flags & O_APPEND))
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1690) 		return -EBADF;
1b4f42a1e33fe (Miklos Szeredi          2018-07-06 23:57:03 +0200 1691) 
407e9c63ee571 (Darrick J. Wong         2020-10-15 09:21:17 -0700 1692) 	return 0;
54dbc15172375 (Darrick J. Wong         2015-12-19 00:55:59 -0800 1693) }