xref: /linux-6.15/fs/read_write.c (revision da06e3c5)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  linux/fs/read_write.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  Copyright (C) 1991, 1992  Linus Torvalds
61da177e4SLinus Torvalds  */
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds #include <linux/slab.h>
91da177e4SLinus Torvalds #include <linux/stat.h>
10b12fb7f4SIngo Molnar #include <linux/sched/xacct.h>
111da177e4SLinus Torvalds #include <linux/fcntl.h>
121da177e4SLinus Torvalds #include <linux/file.h>
131da177e4SLinus Torvalds #include <linux/uio.h>
140eeca283SRobert Love #include <linux/fsnotify.h>
151da177e4SLinus Torvalds #include <linux/security.h>
16630d9c47SPaul Gortmaker #include <linux/export.h>
171da177e4SLinus Torvalds #include <linux/syscalls.h>
18e28cc715SLinus Torvalds #include <linux/pagemap.h>
19d6b29d7cSJens Axboe #include <linux/splice.h>
20561c6731SAl Viro #include <linux/compat.h>
2129732938SZach Brown #include <linux/mount.h>
222feb55f8SWouter van Kesteren #include <linux/fs.h>
2306ae43f3SAl Viro #include "internal.h"
241da177e4SLinus Torvalds 
257c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
261da177e4SLinus Torvalds #include <asm/unistd.h>
271da177e4SLinus Torvalds 
284b6f5d20SArjan van de Ven const struct file_operations generic_ro_fops = {
291da177e4SLinus Torvalds 	.llseek		= generic_file_llseek,
30aad4f8bbSAl Viro 	.read_iter	= generic_file_read_iter,
311da177e4SLinus Torvalds 	.mmap		= generic_file_readonly_mmap,
322cb1e089SDavid Howells 	.splice_read	= filemap_splice_read,
331da177e4SLinus Torvalds };
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds EXPORT_SYMBOL(generic_ro_fops);
361da177e4SLinus Torvalds 
unsigned_offsets(struct file * file)37ddef7ed2SChristoph Hellwig static inline bool unsigned_offsets(struct file *file)
384a3956c7SKAMEZAWA Hiroyuki {
39641bb439SChristian Brauner 	return file->f_op->fop_flags & FOP_UNSIGNED_OFFSET;
404a3956c7SKAMEZAWA Hiroyuki }
414a3956c7SKAMEZAWA Hiroyuki 
4246a1c2c7SJie Liu /**
43d095a5beSChristian Brauner  * vfs_setpos_cookie - update the file offset for lseek and reset cookie
44d095a5beSChristian Brauner  * @file:	file structure in question
45d095a5beSChristian Brauner  * @offset:	file offset to seek to
46d095a5beSChristian Brauner  * @maxsize:	maximum file size
47d095a5beSChristian Brauner  * @cookie:	cookie to reset
48d095a5beSChristian Brauner  *
49d095a5beSChristian Brauner  * Update the file offset to the value specified by @offset if the given
50d095a5beSChristian Brauner  * offset is valid and it is not equal to the current file offset and
51d095a5beSChristian Brauner  * reset the specified cookie to indicate that a seek happened.
52d095a5beSChristian Brauner  *
53d095a5beSChristian Brauner  * Return the specified offset on success and -EINVAL on invalid offset.
54d095a5beSChristian Brauner  */
vfs_setpos_cookie(struct file * file,loff_t offset,loff_t maxsize,u64 * cookie)55d095a5beSChristian Brauner static loff_t vfs_setpos_cookie(struct file *file, loff_t offset,
56d095a5beSChristian Brauner 				loff_t maxsize, u64 *cookie)
57d095a5beSChristian Brauner {
58d095a5beSChristian Brauner 	if (offset < 0 && !unsigned_offsets(file))
59d095a5beSChristian Brauner 		return -EINVAL;
60d095a5beSChristian Brauner 	if (offset > maxsize)
61d095a5beSChristian Brauner 		return -EINVAL;
62d095a5beSChristian Brauner 
63d095a5beSChristian Brauner 	if (offset != file->f_pos) {
64d095a5beSChristian Brauner 		file->f_pos = offset;
6511068e0bSChristian Brauner 		if (cookie)
66d095a5beSChristian Brauner 			*cookie = 0;
67d095a5beSChristian Brauner 	}
68d095a5beSChristian Brauner 	return offset;
69d095a5beSChristian Brauner }
70d095a5beSChristian Brauner 
71d095a5beSChristian Brauner /**
7246a1c2c7SJie Liu  * vfs_setpos - update the file offset for lseek
7346a1c2c7SJie Liu  * @file:	file structure in question
7446a1c2c7SJie Liu  * @offset:	file offset to seek to
7546a1c2c7SJie Liu  * @maxsize:	maximum file size
7646a1c2c7SJie Liu  *
7746a1c2c7SJie Liu  * This is a low-level filesystem helper for updating the file offset to
7846a1c2c7SJie Liu  * the value specified by @offset if the given offset is valid and it is
7946a1c2c7SJie Liu  * not equal to the current file offset.
8046a1c2c7SJie Liu  *
8146a1c2c7SJie Liu  * Return the specified offset on success and -EINVAL on invalid offset.
8246a1c2c7SJie Liu  */
vfs_setpos(struct file * file,loff_t offset,loff_t maxsize)8346a1c2c7SJie Liu loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
84ef3d0fd2SAndi Kleen {
8511068e0bSChristian Brauner 	return vfs_setpos_cookie(file, offset, maxsize, NULL);
86ef3d0fd2SAndi Kleen }
8746a1c2c7SJie Liu EXPORT_SYMBOL(vfs_setpos);
88ef3d0fd2SAndi Kleen 
893a8cff4fSChristoph Hellwig /**
90b8c74519SChristian Brauner  * must_set_pos - check whether f_pos has to be updated
91b8c74519SChristian Brauner  * @file: file to seek on
92b8c74519SChristian Brauner  * @offset: offset to use
93b8c74519SChristian Brauner  * @whence: type of seek operation
94b8c74519SChristian Brauner  * @eof: end of file
95b8c74519SChristian Brauner  *
96b8c74519SChristian Brauner  * Check whether f_pos needs to be updated and update @offset according
97b8c74519SChristian Brauner  * to @whence.
98b8c74519SChristian Brauner  *
99b8c74519SChristian Brauner  * Return: 0 if f_pos doesn't need to be updated, 1 if f_pos has to be
100b8c74519SChristian Brauner  * updated, and negative error code on failure.
101b8c74519SChristian Brauner  */
must_set_pos(struct file * file,loff_t * offset,int whence,loff_t eof)102ed904935SChristian Brauner static int must_set_pos(struct file *file, loff_t *offset, int whence, loff_t eof)
103b8c74519SChristian Brauner {
104b8c74519SChristian Brauner 	switch (whence) {
105b8c74519SChristian Brauner 	case SEEK_END:
106b8c74519SChristian Brauner 		*offset += eof;
107b8c74519SChristian Brauner 		break;
108b8c74519SChristian Brauner 	case SEEK_CUR:
109b8c74519SChristian Brauner 		/*
110b8c74519SChristian Brauner 		 * Here we special-case the lseek(fd, 0, SEEK_CUR)
111b8c74519SChristian Brauner 		 * position-querying operation.  Avoid rewriting the "same"
112b8c74519SChristian Brauner 		 * f_pos value back to the file because a concurrent read(),
113b8c74519SChristian Brauner 		 * write() or lseek() might have altered it
114b8c74519SChristian Brauner 		 */
115b8c74519SChristian Brauner 		if (*offset == 0) {
116b8c74519SChristian Brauner 			*offset = file->f_pos;
117b8c74519SChristian Brauner 			return 0;
118b8c74519SChristian Brauner 		}
119b8c74519SChristian Brauner 		break;
120b8c74519SChristian Brauner 	case SEEK_DATA:
121b8c74519SChristian Brauner 		/*
122b8c74519SChristian Brauner 		 * In the generic case the entire file is data, so as long as
123b8c74519SChristian Brauner 		 * offset isn't at the end of the file then the offset is data.
124b8c74519SChristian Brauner 		 */
125b8c74519SChristian Brauner 		if ((unsigned long long)*offset >= eof)
126b8c74519SChristian Brauner 			return -ENXIO;
127b8c74519SChristian Brauner 		break;
128b8c74519SChristian Brauner 	case SEEK_HOLE:
129b8c74519SChristian Brauner 		/*
130b8c74519SChristian Brauner 		 * There is a virtual hole at the end of the file, so as long as
131b8c74519SChristian Brauner 		 * offset isn't i_size or larger, return i_size.
132b8c74519SChristian Brauner 		 */
133b8c74519SChristian Brauner 		if ((unsigned long long)*offset >= eof)
134b8c74519SChristian Brauner 			return -ENXIO;
135b8c74519SChristian Brauner 		*offset = eof;
136b8c74519SChristian Brauner 		break;
137b8c74519SChristian Brauner 	}
138b8c74519SChristian Brauner 
139b8c74519SChristian Brauner 	return 1;
140b8c74519SChristian Brauner }
141b8c74519SChristian Brauner 
142b8c74519SChristian Brauner /**
1435760495aSAndi Kleen  * generic_file_llseek_size - generic llseek implementation for regular files
1443a8cff4fSChristoph Hellwig  * @file:	file structure to seek on
1453a8cff4fSChristoph Hellwig  * @offset:	file offset to seek to
146965c8e59SAndrew Morton  * @whence:	type of seek
14789cbd4c0SYang Li  * @maxsize:	max size of this file in file system
148e8b96eb5SEric Sandeen  * @eof:	offset used for SEEK_END position
1493a8cff4fSChristoph Hellwig  *
1505760495aSAndi Kleen  * This is a variant of generic_file_llseek that allows passing in a custom
151e8b96eb5SEric Sandeen  * maximum file size and a custom EOF position, for e.g. hashed directories
152ef3d0fd2SAndi Kleen  *
153ef3d0fd2SAndi Kleen  * Synchronization:
1545760495aSAndi Kleen  * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms)
155ef3d0fd2SAndi Kleen  * SEEK_CUR is synchronized against other SEEK_CURs, but not read/writes.
156ef3d0fd2SAndi Kleen  * read/writes behave like SEEK_SET against seeks.
1573a8cff4fSChristoph Hellwig  */
1589465efc9SAndi Kleen loff_t
generic_file_llseek_size(struct file * file,loff_t offset,int whence,loff_t maxsize,loff_t eof)159965c8e59SAndrew Morton generic_file_llseek_size(struct file *file, loff_t offset, int whence,
160e8b96eb5SEric Sandeen 		loff_t maxsize, loff_t eof)
1611da177e4SLinus Torvalds {
162ed904935SChristian Brauner 	int ret;
163ed904935SChristian Brauner 
164ed904935SChristian Brauner 	ret = must_set_pos(file, &offset, whence, eof);
165ed904935SChristian Brauner 	if (ret < 0)
166ed904935SChristian Brauner 		return ret;
167ed904935SChristian Brauner 	if (ret == 0)
168ef3d0fd2SAndi Kleen 		return offset;
169ed904935SChristian Brauner 
170ed904935SChristian Brauner 	if (whence == SEEK_CUR) {
171982d8165SJosef Bacik 		/*
172*da06e3c5SChristian Brauner 		 * If the file requires locking via f_pos_lock we know
173*da06e3c5SChristian Brauner 		 * that mutual exclusion for SEEK_CUR on the same file
174*da06e3c5SChristian Brauner 		 * is guaranteed. If the file isn't locked, we take
175*da06e3c5SChristian Brauner 		 * f_lock to protect against f_pos races with other
176*da06e3c5SChristian Brauner 		 * SEEK_CURs.
177982d8165SJosef Bacik 		 */
178*da06e3c5SChristian Brauner 		if (file_seek_cur_needs_f_lock(file)) {
179ed904935SChristian Brauner 			guard(spinlock)(&file->f_lock);
180ed904935SChristian Brauner 			return vfs_setpos(file, file->f_pos + offset, maxsize);
1811da177e4SLinus Torvalds 		}
182*da06e3c5SChristian Brauner 		return vfs_setpos(file, file->f_pos + offset, maxsize);
183*da06e3c5SChristian Brauner 	}
1843a8cff4fSChristoph Hellwig 
18546a1c2c7SJie Liu 	return vfs_setpos(file, offset, maxsize);
1865760495aSAndi Kleen }
1875760495aSAndi Kleen EXPORT_SYMBOL(generic_file_llseek_size);
1885760495aSAndi Kleen 
1895760495aSAndi Kleen /**
190d688d65aSChristian Brauner  * generic_llseek_cookie - versioned llseek implementation
191d688d65aSChristian Brauner  * @file:	file structure to seek on
192d688d65aSChristian Brauner  * @offset:	file offset to seek to
193d688d65aSChristian Brauner  * @whence:	type of seek
194d688d65aSChristian Brauner  * @cookie:	cookie to update
195d688d65aSChristian Brauner  *
196d688d65aSChristian Brauner  * See generic_file_llseek for a general description and locking assumptions.
197d688d65aSChristian Brauner  *
198d688d65aSChristian Brauner  * In contrast to generic_file_llseek, this function also resets a
199d688d65aSChristian Brauner  * specified cookie to indicate a seek took place.
200d688d65aSChristian Brauner  */
generic_llseek_cookie(struct file * file,loff_t offset,int whence,u64 * cookie)201d688d65aSChristian Brauner loff_t generic_llseek_cookie(struct file *file, loff_t offset, int whence,
202d688d65aSChristian Brauner 			     u64 *cookie)
203d688d65aSChristian Brauner {
204d688d65aSChristian Brauner 	struct inode *inode = file->f_mapping->host;
205d688d65aSChristian Brauner 	loff_t maxsize = inode->i_sb->s_maxbytes;
206d688d65aSChristian Brauner 	loff_t eof = i_size_read(inode);
207d688d65aSChristian Brauner 	int ret;
208d688d65aSChristian Brauner 
209d688d65aSChristian Brauner 	if (WARN_ON_ONCE(!cookie))
210d688d65aSChristian Brauner 		return -EINVAL;
211d688d65aSChristian Brauner 
212d688d65aSChristian Brauner 	/*
213d688d65aSChristian Brauner 	 * Require that this is only used for directories that guarantee
214d688d65aSChristian Brauner 	 * synchronization between readdir and seek so that an update to
215d688d65aSChristian Brauner 	 * @cookie is correctly synchronized with concurrent readdir.
216d688d65aSChristian Brauner 	 */
217d688d65aSChristian Brauner 	if (WARN_ON_ONCE(!(file->f_mode & FMODE_ATOMIC_POS)))
218d688d65aSChristian Brauner 		return -EINVAL;
219d688d65aSChristian Brauner 
220d688d65aSChristian Brauner 	ret = must_set_pos(file, &offset, whence, eof);
221d688d65aSChristian Brauner 	if (ret < 0)
222d688d65aSChristian Brauner 		return ret;
223d688d65aSChristian Brauner 	if (ret == 0)
224d688d65aSChristian Brauner 		return offset;
225d688d65aSChristian Brauner 
226d688d65aSChristian Brauner 	/* No need to hold f_lock because we know that f_pos_lock is held. */
227d688d65aSChristian Brauner 	if (whence == SEEK_CUR)
228d688d65aSChristian Brauner 		return vfs_setpos_cookie(file, file->f_pos + offset, maxsize, cookie);
229d688d65aSChristian Brauner 
230d688d65aSChristian Brauner 	return vfs_setpos_cookie(file, offset, maxsize, cookie);
231d688d65aSChristian Brauner }
232d688d65aSChristian Brauner EXPORT_SYMBOL(generic_llseek_cookie);
233d688d65aSChristian Brauner 
234d688d65aSChristian Brauner /**
2355760495aSAndi Kleen  * generic_file_llseek - generic llseek implementation for regular files
2365760495aSAndi Kleen  * @file:	file structure to seek on
2375760495aSAndi Kleen  * @offset:	file offset to seek to
238965c8e59SAndrew Morton  * @whence:	type of seek
2395760495aSAndi Kleen  *
2405760495aSAndi Kleen  * This is a generic implemenation of ->llseek useable for all normal local
2415760495aSAndi Kleen  * filesystems.  It just updates the file offset to the value specified by
242546ae2d2SMing Lei  * @offset and @whence.
2435760495aSAndi Kleen  */
generic_file_llseek(struct file * file,loff_t offset,int whence)244965c8e59SAndrew Morton loff_t generic_file_llseek(struct file *file, loff_t offset, int whence)
2455760495aSAndi Kleen {
2465760495aSAndi Kleen 	struct inode *inode = file->f_mapping->host;
2475760495aSAndi Kleen 
248965c8e59SAndrew Morton 	return generic_file_llseek_size(file, offset, whence,
249e8b96eb5SEric Sandeen 					inode->i_sb->s_maxbytes,
250e8b96eb5SEric Sandeen 					i_size_read(inode));
2511da177e4SLinus Torvalds }
2529465efc9SAndi Kleen EXPORT_SYMBOL(generic_file_llseek);
2531da177e4SLinus Torvalds 
254ae6afc3fSjan Blunck /**
2551bf9d14dSAl Viro  * fixed_size_llseek - llseek implementation for fixed-sized devices
2561bf9d14dSAl Viro  * @file:	file structure to seek on
2571bf9d14dSAl Viro  * @offset:	file offset to seek to
2581bf9d14dSAl Viro  * @whence:	type of seek
2591bf9d14dSAl Viro  * @size:	size of the file
2601bf9d14dSAl Viro  *
2611bf9d14dSAl Viro  */
fixed_size_llseek(struct file * file,loff_t offset,int whence,loff_t size)2621bf9d14dSAl Viro loff_t fixed_size_llseek(struct file *file, loff_t offset, int whence, loff_t size)
2631bf9d14dSAl Viro {
2641bf9d14dSAl Viro 	switch (whence) {
2651bf9d14dSAl Viro 	case SEEK_SET: case SEEK_CUR: case SEEK_END:
2661bf9d14dSAl Viro 		return generic_file_llseek_size(file, offset, whence,
2671bf9d14dSAl Viro 						size, size);
2681bf9d14dSAl Viro 	default:
2691bf9d14dSAl Viro 		return -EINVAL;
2701bf9d14dSAl Viro 	}
2711bf9d14dSAl Viro }
2721bf9d14dSAl Viro EXPORT_SYMBOL(fixed_size_llseek);
2731bf9d14dSAl Viro 
2741bf9d14dSAl Viro /**
275b25472f9SAl Viro  * no_seek_end_llseek - llseek implementation for fixed-sized devices
276b25472f9SAl Viro  * @file:	file structure to seek on
277b25472f9SAl Viro  * @offset:	file offset to seek to
278b25472f9SAl Viro  * @whence:	type of seek
279b25472f9SAl Viro  *
280b25472f9SAl Viro  */
no_seek_end_llseek(struct file * file,loff_t offset,int whence)281b25472f9SAl Viro loff_t no_seek_end_llseek(struct file *file, loff_t offset, int whence)
282b25472f9SAl Viro {
283b25472f9SAl Viro 	switch (whence) {
284b25472f9SAl Viro 	case SEEK_SET: case SEEK_CUR:
285b25472f9SAl Viro 		return generic_file_llseek_size(file, offset, whence,
2862feb55f8SWouter van Kesteren 						OFFSET_MAX, 0);
287b25472f9SAl Viro 	default:
288b25472f9SAl Viro 		return -EINVAL;
289b25472f9SAl Viro 	}
290b25472f9SAl Viro }
291b25472f9SAl Viro EXPORT_SYMBOL(no_seek_end_llseek);
292b25472f9SAl Viro 
293b25472f9SAl Viro /**
294b25472f9SAl Viro  * no_seek_end_llseek_size - llseek implementation for fixed-sized devices
295b25472f9SAl Viro  * @file:	file structure to seek on
296b25472f9SAl Viro  * @offset:	file offset to seek to
297b25472f9SAl Viro  * @whence:	type of seek
298b25472f9SAl Viro  * @size:	maximal offset allowed
299b25472f9SAl Viro  *
300b25472f9SAl Viro  */
no_seek_end_llseek_size(struct file * file,loff_t offset,int whence,loff_t size)301b25472f9SAl Viro loff_t no_seek_end_llseek_size(struct file *file, loff_t offset, int whence, loff_t size)
302b25472f9SAl Viro {
303b25472f9SAl Viro 	switch (whence) {
304b25472f9SAl Viro 	case SEEK_SET: case SEEK_CUR:
305b25472f9SAl Viro 		return generic_file_llseek_size(file, offset, whence,
306b25472f9SAl Viro 						size, 0);
307b25472f9SAl Viro 	default:
308b25472f9SAl Viro 		return -EINVAL;
309b25472f9SAl Viro 	}
310b25472f9SAl Viro }
311b25472f9SAl Viro EXPORT_SYMBOL(no_seek_end_llseek_size);
312b25472f9SAl Viro 
313b25472f9SAl Viro /**
314ae6afc3fSjan Blunck  * noop_llseek - No Operation Performed llseek implementation
315ae6afc3fSjan Blunck  * @file:	file structure to seek on
316ae6afc3fSjan Blunck  * @offset:	file offset to seek to
317965c8e59SAndrew Morton  * @whence:	type of seek
318ae6afc3fSjan Blunck  *
319ae6afc3fSjan Blunck  * This is an implementation of ->llseek useable for the rare special case when
320ae6afc3fSjan Blunck  * userspace expects the seek to succeed but the (device) file is actually not
321ae6afc3fSjan Blunck  * able to perform the seek. In this case you use noop_llseek() instead of
322ae6afc3fSjan Blunck  * falling back to the default implementation of ->llseek.
323ae6afc3fSjan Blunck  */
noop_llseek(struct file * file,loff_t offset,int whence)324965c8e59SAndrew Morton loff_t noop_llseek(struct file *file, loff_t offset, int whence)
325ae6afc3fSjan Blunck {
326ae6afc3fSjan Blunck 	return file->f_pos;
327ae6afc3fSjan Blunck }
328ae6afc3fSjan Blunck EXPORT_SYMBOL(noop_llseek);
329ae6afc3fSjan Blunck 
default_llseek(struct file * file,loff_t offset,int whence)330965c8e59SAndrew Morton loff_t default_llseek(struct file *file, loff_t offset, int whence)
3311da177e4SLinus Torvalds {
332496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
33316abef0eSDavid Sterba 	loff_t retval;
3341da177e4SLinus Torvalds 
3355955102cSAl Viro 	inode_lock(inode);
336965c8e59SAndrew Morton 	switch (whence) {
3377b8e8924SChris Snook 		case SEEK_END:
338982d8165SJosef Bacik 			offset += i_size_read(inode);
3391da177e4SLinus Torvalds 			break;
3407b8e8924SChris Snook 		case SEEK_CUR:
3415b6f1eb9SAlain Knaff 			if (offset == 0) {
3425b6f1eb9SAlain Knaff 				retval = file->f_pos;
3435b6f1eb9SAlain Knaff 				goto out;
3445b6f1eb9SAlain Knaff 			}
3451da177e4SLinus Torvalds 			offset += file->f_pos;
346982d8165SJosef Bacik 			break;
347982d8165SJosef Bacik 		case SEEK_DATA:
348982d8165SJosef Bacik 			/*
349982d8165SJosef Bacik 			 * In the generic case the entire file is data, so as
350982d8165SJosef Bacik 			 * long as offset isn't at the end of the file then the
351982d8165SJosef Bacik 			 * offset is data.
352982d8165SJosef Bacik 			 */
353bacb2d81SDan Carpenter 			if (offset >= inode->i_size) {
354bacb2d81SDan Carpenter 				retval = -ENXIO;
355bacb2d81SDan Carpenter 				goto out;
356bacb2d81SDan Carpenter 			}
357982d8165SJosef Bacik 			break;
358982d8165SJosef Bacik 		case SEEK_HOLE:
359982d8165SJosef Bacik 			/*
360982d8165SJosef Bacik 			 * There is a virtual hole at the end of the file, so
361982d8165SJosef Bacik 			 * as long as offset isn't i_size or larger, return
362982d8165SJosef Bacik 			 * i_size.
363982d8165SJosef Bacik 			 */
364bacb2d81SDan Carpenter 			if (offset >= inode->i_size) {
365bacb2d81SDan Carpenter 				retval = -ENXIO;
366bacb2d81SDan Carpenter 				goto out;
367bacb2d81SDan Carpenter 			}
368982d8165SJosef Bacik 			offset = inode->i_size;
369982d8165SJosef Bacik 			break;
3701da177e4SLinus Torvalds 	}
3711da177e4SLinus Torvalds 	retval = -EINVAL;
372cccb5a1eSAl Viro 	if (offset >= 0 || unsigned_offsets(file)) {
37311068e0bSChristian Brauner 		if (offset != file->f_pos)
3741da177e4SLinus Torvalds 			file->f_pos = offset;
3751da177e4SLinus Torvalds 		retval = offset;
3761da177e4SLinus Torvalds 	}
3775b6f1eb9SAlain Knaff out:
3785955102cSAl Viro 	inode_unlock(inode);
3791da177e4SLinus Torvalds 	return retval;
3801da177e4SLinus Torvalds }
3811da177e4SLinus Torvalds EXPORT_SYMBOL(default_llseek);
3821da177e4SLinus Torvalds 
vfs_llseek(struct file * file,loff_t offset,int whence)383965c8e59SAndrew Morton loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
3841da177e4SLinus Torvalds {
3854e3299eaSJason A. Donenfeld 	if (!(file->f_mode & FMODE_LSEEK))
3864e3299eaSJason A. Donenfeld 		return -ESPIPE;
3874e3299eaSJason A. Donenfeld 	return file->f_op->llseek(file, offset, whence);
3881da177e4SLinus Torvalds }
3891da177e4SLinus Torvalds EXPORT_SYMBOL(vfs_llseek);
3901da177e4SLinus Torvalds 
ksys_lseek(unsigned int fd,off_t offset,unsigned int whence)391bef17329SChristoph Hellwig static off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence)
3921da177e4SLinus Torvalds {
3931da177e4SLinus Torvalds 	off_t retval;
394d7a9616cSAl Viro 	CLASS(fd_pos, f)(fd);
395d7a9616cSAl Viro 	if (fd_empty(f))
3962903ff01SAl Viro 		return -EBADF;
3971da177e4SLinus Torvalds 
3981da177e4SLinus Torvalds 	retval = -EINVAL;
399965c8e59SAndrew Morton 	if (whence <= SEEK_MAX) {
4001da91ea8SAl Viro 		loff_t res = vfs_llseek(fd_file(f), offset, whence);
4011da177e4SLinus Torvalds 		retval = res;
4021da177e4SLinus Torvalds 		if (res != (loff_t)retval)
4031da177e4SLinus Torvalds 			retval = -EOVERFLOW;	/* LFS: should only happen on 32 bit platforms */
4041da177e4SLinus Torvalds 	}
4051da177e4SLinus Torvalds 	return retval;
4061da177e4SLinus Torvalds }
4071da177e4SLinus Torvalds 
SYSCALL_DEFINE3(lseek,unsigned int,fd,off_t,offset,unsigned int,whence)40876847e43SDominik Brodowski SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
40976847e43SDominik Brodowski {
41076847e43SDominik Brodowski 	return ksys_lseek(fd, offset, whence);
41176847e43SDominik Brodowski }
41276847e43SDominik Brodowski 
413561c6731SAl Viro #ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE3(lseek,unsigned int,fd,compat_off_t,offset,unsigned int,whence)414561c6731SAl Viro COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned int, whence)
415561c6731SAl Viro {
41676847e43SDominik Brodowski 	return ksys_lseek(fd, offset, whence);
417561c6731SAl Viro }
418561c6731SAl Viro #endif
419561c6731SAl Viro 
4209e62ccecSMichal Suchanek #if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) || \
4219e62ccecSMichal Suchanek 	defined(__ARCH_WANT_SYS_LLSEEK)
SYSCALL_DEFINE5(llseek,unsigned int,fd,unsigned long,offset_high,unsigned long,offset_low,loff_t __user *,result,unsigned int,whence)422003d7ab4SHeiko Carstens SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
423003d7ab4SHeiko Carstens 		unsigned long, offset_low, loff_t __user *, result,
424965c8e59SAndrew Morton 		unsigned int, whence)
4251da177e4SLinus Torvalds {
4261da177e4SLinus Torvalds 	int retval;
427d7a9616cSAl Viro 	CLASS(fd_pos, f)(fd);
4281da177e4SLinus Torvalds 	loff_t offset;
4291da177e4SLinus Torvalds 
430d7a9616cSAl Viro 	if (fd_empty(f))
4312903ff01SAl Viro 		return -EBADF;
4321da177e4SLinus Torvalds 
433965c8e59SAndrew Morton 	if (whence > SEEK_MAX)
434d7a9616cSAl Viro 		return -EINVAL;
4351da177e4SLinus Torvalds 
4361da91ea8SAl Viro 	offset = vfs_llseek(fd_file(f), ((loff_t) offset_high << 32) | offset_low,
437965c8e59SAndrew Morton 			whence);
4381da177e4SLinus Torvalds 
4391da177e4SLinus Torvalds 	retval = (int)offset;
4401da177e4SLinus Torvalds 	if (offset >= 0) {
4411da177e4SLinus Torvalds 		retval = -EFAULT;
4421da177e4SLinus Torvalds 		if (!copy_to_user(result, &offset, sizeof(offset)))
4431da177e4SLinus Torvalds 			retval = 0;
4441da177e4SLinus Torvalds 	}
4451da177e4SLinus Torvalds 	return retval;
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds #endif
4481da177e4SLinus Torvalds 
rw_verify_area(int read_write,struct file * file,const loff_t * ppos,size_t count)44968d70d03SAl Viro int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
4501da177e4SLinus Torvalds {
451d9e5d310SAmir Goldstein 	int mask = read_write == READ ? MAY_READ : MAY_WRITE;
452d9e5d310SAmir Goldstein 	int ret;
453d9e5d310SAmir Goldstein 
454e28cc715SLinus Torvalds 	if (unlikely((ssize_t) count < 0))
4552949e842SLukas Bulwahn 		return -EINVAL;
456438ab720SKirill Smelkov 
457438ab720SKirill Smelkov 	if (ppos) {
458438ab720SKirill Smelkov 		loff_t pos = *ppos;
459438ab720SKirill Smelkov 
460cccb5a1eSAl Viro 		if (unlikely(pos < 0)) {
461cccb5a1eSAl Viro 			if (!unsigned_offsets(file))
4622949e842SLukas Bulwahn 				return -EINVAL;
463cccb5a1eSAl Viro 			if (count >= -pos) /* both values are in 0..LLONG_MAX */
464cccb5a1eSAl Viro 				return -EOVERFLOW;
465cccb5a1eSAl Viro 		} else if (unlikely((loff_t) (pos + count) < 0)) {
466cccb5a1eSAl Viro 			if (!unsigned_offsets(file))
4672949e842SLukas Bulwahn 				return -EINVAL;
4684a3956c7SKAMEZAWA Hiroyuki 		}
469438ab720SKirill Smelkov 	}
470438ab720SKirill Smelkov 
471d9e5d310SAmir Goldstein 	ret = security_file_permission(file, mask);
472d9e5d310SAmir Goldstein 	if (ret)
473d9e5d310SAmir Goldstein 		return ret;
474d9e5d310SAmir Goldstein 
475d9e5d310SAmir Goldstein 	return fsnotify_file_area_perm(file, mask, ppos, count);
4761da177e4SLinus Torvalds }
47787112933SOmar Sandoval EXPORT_SYMBOL(rw_verify_area);
4781da177e4SLinus Torvalds 
new_sync_read(struct file * filp,char __user * buf,size_t len,loff_t * ppos)4795d5d5689SAl Viro static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
480293bc982SAl Viro {
481293bc982SAl Viro 	struct kiocb kiocb;
482293bc982SAl Viro 	struct iov_iter iter;
483293bc982SAl Viro 	ssize_t ret;
484293bc982SAl Viro 
485293bc982SAl Viro 	init_sync_kiocb(&kiocb, filp);
486438ab720SKirill Smelkov 	kiocb.ki_pos = (ppos ? *ppos : 0);
487de4eda9dSAl Viro 	iov_iter_ubuf(&iter, ITER_DEST, buf, len);
488293bc982SAl Viro 
4897c98f7cbSMiklos Szeredi 	ret = filp->f_op->read_iter(&kiocb, &iter);
490599bd19bSChristoph Hellwig 	BUG_ON(ret == -EIOCBQUEUED);
491438ab720SKirill Smelkov 	if (ppos)
492293bc982SAl Viro 		*ppos = kiocb.ki_pos;
493293bc982SAl Viro 	return ret;
494293bc982SAl Viro }
495293bc982SAl Viro 
warn_unsupported(struct file * file,const char * op)4964d03e3ccSChristoph Hellwig static int warn_unsupported(struct file *file, const char *op)
4974d03e3ccSChristoph Hellwig {
4984d03e3ccSChristoph Hellwig 	pr_warn_ratelimited(
4994d03e3ccSChristoph Hellwig 		"kernel %s not supported for file %pD4 (pid: %d comm: %.20s)\n",
5004d03e3ccSChristoph Hellwig 		op, file, current->pid, current->comm);
5014d03e3ccSChristoph Hellwig 	return -EINVAL;
5024d03e3ccSChristoph Hellwig }
5034d03e3ccSChristoph Hellwig 
__kernel_read(struct file * file,void * buf,size_t count,loff_t * pos)50461a707c5SChristoph Hellwig ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
50561a707c5SChristoph Hellwig {
5064d03e3ccSChristoph Hellwig 	struct kvec iov = {
5074d03e3ccSChristoph Hellwig 		.iov_base	= buf,
5084d03e3ccSChristoph Hellwig 		.iov_len	= min_t(size_t, count, MAX_RW_COUNT),
5094d03e3ccSChristoph Hellwig 	};
5104d03e3ccSChristoph Hellwig 	struct kiocb kiocb;
5114d03e3ccSChristoph Hellwig 	struct iov_iter iter;
51261a707c5SChristoph Hellwig 	ssize_t ret;
51361a707c5SChristoph Hellwig 
51461a707c5SChristoph Hellwig 	if (WARN_ON_ONCE(!(file->f_mode & FMODE_READ)))
51561a707c5SChristoph Hellwig 		return -EINVAL;
51661a707c5SChristoph Hellwig 	if (!(file->f_mode & FMODE_CAN_READ))
51761a707c5SChristoph Hellwig 		return -EINVAL;
5184d03e3ccSChristoph Hellwig 	/*
5194d03e3ccSChristoph Hellwig 	 * Also fail if ->read_iter and ->read are both wired up as that
5204d03e3ccSChristoph Hellwig 	 * implies very convoluted semantics.
5214d03e3ccSChristoph Hellwig 	 */
5224d03e3ccSChristoph Hellwig 	if (unlikely(!file->f_op->read_iter || file->f_op->read))
5234d03e3ccSChristoph Hellwig 		return warn_unsupported(file, "read");
52461a707c5SChristoph Hellwig 
5254d03e3ccSChristoph Hellwig 	init_sync_kiocb(&kiocb, file);
5267b84b665SMatthew Wilcox (Oracle) 	kiocb.ki_pos = pos ? *pos : 0;
527de4eda9dSAl Viro 	iov_iter_kvec(&iter, ITER_DEST, &iov, 1, iov.iov_len);
5284d03e3ccSChristoph Hellwig 	ret = file->f_op->read_iter(&kiocb, &iter);
52961a707c5SChristoph Hellwig 	if (ret > 0) {
5307b84b665SMatthew Wilcox (Oracle) 		if (pos)
5314d03e3ccSChristoph Hellwig 			*pos = kiocb.ki_pos;
53261a707c5SChristoph Hellwig 		fsnotify_access(file);
53361a707c5SChristoph Hellwig 		add_rchar(current, ret);
53461a707c5SChristoph Hellwig 	}
53561a707c5SChristoph Hellwig 	inc_syscr(current);
53661a707c5SChristoph Hellwig 	return ret;
53761a707c5SChristoph Hellwig }
53861a707c5SChristoph Hellwig 
kernel_read(struct file * file,void * buf,size_t count,loff_t * pos)539bdd1d2d3SChristoph Hellwig ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
540c41fbad0SChristoph Hellwig {
5416209dd91SChristoph Hellwig 	ssize_t ret;
542c41fbad0SChristoph Hellwig 
5436209dd91SChristoph Hellwig 	ret = rw_verify_area(READ, file, pos, count);
5446209dd91SChristoph Hellwig 	if (ret)
5456209dd91SChristoph Hellwig 		return ret;
5466209dd91SChristoph Hellwig 	return __kernel_read(file, buf, count, pos);
547c41fbad0SChristoph Hellwig }
548c41fbad0SChristoph Hellwig EXPORT_SYMBOL(kernel_read);
5496fb5032eSDmitry Kasatkin 
vfs_read(struct file * file,char __user * buf,size_t count,loff_t * pos)5501da177e4SLinus Torvalds ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
5511da177e4SLinus Torvalds {
5521da177e4SLinus Torvalds 	ssize_t ret;
5531da177e4SLinus Torvalds 
5541da177e4SLinus Torvalds 	if (!(file->f_mode & FMODE_READ))
5551da177e4SLinus Torvalds 		return -EBADF;
5567f7f25e8SAl Viro 	if (!(file->f_mode & FMODE_CAN_READ))
5571da177e4SLinus Torvalds 		return -EINVAL;
55896d4f267SLinus Torvalds 	if (unlikely(!access_ok(buf, count)))
5591da177e4SLinus Torvalds 		return -EFAULT;
5601da177e4SLinus Torvalds 
5611da177e4SLinus Torvalds 	ret = rw_verify_area(READ, file, pos, count);
562775802c0SChristoph Hellwig 	if (ret)
563775802c0SChristoph Hellwig 		return ret;
564bc61384dSAl Viro 	if (count > MAX_RW_COUNT)
565bc61384dSAl Viro 		count =  MAX_RW_COUNT;
566775802c0SChristoph Hellwig 
567775802c0SChristoph Hellwig 	if (file->f_op->read)
568775802c0SChristoph Hellwig 		ret = file->f_op->read(file, buf, count, pos);
569775802c0SChristoph Hellwig 	else if (file->f_op->read_iter)
570775802c0SChristoph Hellwig 		ret = new_sync_read(file, buf, count, pos);
571775802c0SChristoph Hellwig 	else
572775802c0SChristoph Hellwig 		ret = -EINVAL;
5731da177e4SLinus Torvalds 	if (ret > 0) {
5742a12a9d7SEric Paris 		fsnotify_access(file);
5754b98d11bSAlexey Dobriyan 		add_rchar(current, ret);
5761da177e4SLinus Torvalds 	}
5774b98d11bSAlexey Dobriyan 	inc_syscr(current);
5781da177e4SLinus Torvalds 	return ret;
5791da177e4SLinus Torvalds }
5801da177e4SLinus Torvalds 
new_sync_write(struct file * filp,const char __user * buf,size_t len,loff_t * ppos)5815d5d5689SAl Viro static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
582293bc982SAl Viro {
583293bc982SAl Viro 	struct kiocb kiocb;
584293bc982SAl Viro 	struct iov_iter iter;
585293bc982SAl Viro 	ssize_t ret;
586293bc982SAl Viro 
587293bc982SAl Viro 	init_sync_kiocb(&kiocb, filp);
588438ab720SKirill Smelkov 	kiocb.ki_pos = (ppos ? *ppos : 0);
589de4eda9dSAl Viro 	iov_iter_ubuf(&iter, ITER_SOURCE, (void __user *)buf, len);
590293bc982SAl Viro 
5917c98f7cbSMiklos Szeredi 	ret = filp->f_op->write_iter(&kiocb, &iter);
592599bd19bSChristoph Hellwig 	BUG_ON(ret == -EIOCBQUEUED);
593438ab720SKirill Smelkov 	if (ret > 0 && ppos)
594293bc982SAl Viro 		*ppos = kiocb.ki_pos;
595293bc982SAl Viro 	return ret;
596293bc982SAl Viro }
597293bc982SAl Viro 
59881238b2cSChristoph Hellwig /* caller is responsible for file_start_write/file_end_write */
__kernel_write_iter(struct file * file,struct iov_iter * from,loff_t * pos)59906bbaa6dSAl Viro ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *pos)
60006ae43f3SAl Viro {
6014d03e3ccSChristoph Hellwig 	struct kiocb kiocb;
60206ae43f3SAl Viro 	ssize_t ret;
60306ae43f3SAl Viro 
604a01ac27bSChristoph Hellwig 	if (WARN_ON_ONCE(!(file->f_mode & FMODE_WRITE)))
605a01ac27bSChristoph Hellwig 		return -EBADF;
6067f7f25e8SAl Viro 	if (!(file->f_mode & FMODE_CAN_WRITE))
6073e84f48eSAl Viro 		return -EINVAL;
6084d03e3ccSChristoph Hellwig 	/*
6094d03e3ccSChristoph Hellwig 	 * Also fail if ->write_iter and ->write are both wired up as that
6104d03e3ccSChristoph Hellwig 	 * implies very convoluted semantics.
6114d03e3ccSChristoph Hellwig 	 */
6124d03e3ccSChristoph Hellwig 	if (unlikely(!file->f_op->write_iter || file->f_op->write))
6134d03e3ccSChristoph Hellwig 		return warn_unsupported(file, "write");
6143e84f48eSAl Viro 
6154d03e3ccSChristoph Hellwig 	init_sync_kiocb(&kiocb, file);
6164c207ef4SMatthew Wilcox (Oracle) 	kiocb.ki_pos = pos ? *pos : 0;
61706bbaa6dSAl Viro 	ret = file->f_op->write_iter(&kiocb, from);
61806ae43f3SAl Viro 	if (ret > 0) {
6194c207ef4SMatthew Wilcox (Oracle) 		if (pos)
6204d03e3ccSChristoph Hellwig 			*pos = kiocb.ki_pos;
62106ae43f3SAl Viro 		fsnotify_modify(file);
62206ae43f3SAl Viro 		add_wchar(current, ret);
62306ae43f3SAl Viro 	}
62406ae43f3SAl Viro 	inc_syscw(current);
62506ae43f3SAl Viro 	return ret;
62606ae43f3SAl Viro }
62706bbaa6dSAl Viro 
62806bbaa6dSAl Viro /* caller is responsible for file_start_write/file_end_write */
__kernel_write(struct file * file,const void * buf,size_t count,loff_t * pos)62906bbaa6dSAl Viro ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
63006bbaa6dSAl Viro {
63106bbaa6dSAl Viro 	struct kvec iov = {
63206bbaa6dSAl Viro 		.iov_base	= (void *)buf,
63306bbaa6dSAl Viro 		.iov_len	= min_t(size_t, count, MAX_RW_COUNT),
63406bbaa6dSAl Viro 	};
63506bbaa6dSAl Viro 	struct iov_iter iter;
636de4eda9dSAl Viro 	iov_iter_kvec(&iter, ITER_SOURCE, &iov, 1, iov.iov_len);
63706bbaa6dSAl Viro 	return __kernel_write_iter(file, &iter, pos);
63806bbaa6dSAl Viro }
63990fb7027SLinus Torvalds /*
64090fb7027SLinus Torvalds  * This "EXPORT_SYMBOL_GPL()" is more of a "EXPORT_SYMBOL_DONTUSE()",
64190fb7027SLinus Torvalds  * but autofs is one of the few internal kernel users that actually
64290fb7027SLinus Torvalds  * wants this _and_ can be built as a module. So we need to export
64390fb7027SLinus Torvalds  * this symbol for autofs, even though it really isn't appropriate
64490fb7027SLinus Torvalds  * for any other kernel modules.
64590fb7027SLinus Torvalds  */
64690fb7027SLinus Torvalds EXPORT_SYMBOL_GPL(__kernel_write);
6472ec3a12aSAl Viro 
kernel_write(struct file * file,const void * buf,size_t count,loff_t * pos)648e13ec939SChristoph Hellwig ssize_t kernel_write(struct file *file, const void *buf, size_t count,
649e13ec939SChristoph Hellwig 			    loff_t *pos)
650ac452acaSChristoph Hellwig {
65181238b2cSChristoph Hellwig 	ssize_t ret;
652ac452acaSChristoph Hellwig 
65381238b2cSChristoph Hellwig 	ret = rw_verify_area(WRITE, file, pos, count);
65481238b2cSChristoph Hellwig 	if (ret)
65581238b2cSChristoph Hellwig 		return ret;
656ac452acaSChristoph Hellwig 
65781238b2cSChristoph Hellwig 	file_start_write(file);
65881238b2cSChristoph Hellwig 	ret =  __kernel_write(file, buf, count, pos);
65981238b2cSChristoph Hellwig 	file_end_write(file);
66081238b2cSChristoph Hellwig 	return ret;
661ac452acaSChristoph Hellwig }
662ac452acaSChristoph Hellwig EXPORT_SYMBOL(kernel_write);
663ac452acaSChristoph Hellwig 
vfs_write(struct file * file,const char __user * buf,size_t count,loff_t * pos)6641da177e4SLinus Torvalds ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
6651da177e4SLinus Torvalds {
6661da177e4SLinus Torvalds 	ssize_t ret;
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds 	if (!(file->f_mode & FMODE_WRITE))
6691da177e4SLinus Torvalds 		return -EBADF;
6707f7f25e8SAl Viro 	if (!(file->f_mode & FMODE_CAN_WRITE))
6711da177e4SLinus Torvalds 		return -EINVAL;
67296d4f267SLinus Torvalds 	if (unlikely(!access_ok(buf, count)))
6731da177e4SLinus Torvalds 		return -EFAULT;
6741da177e4SLinus Torvalds 
6751da177e4SLinus Torvalds 	ret = rw_verify_area(WRITE, file, pos, count);
67653ad8626SChristoph Hellwig 	if (ret)
67753ad8626SChristoph Hellwig 		return ret;
678bc61384dSAl Viro 	if (count > MAX_RW_COUNT)
679bc61384dSAl Viro 		count =  MAX_RW_COUNT;
68003d95eb2SAl Viro 	file_start_write(file);
68153ad8626SChristoph Hellwig 	if (file->f_op->write)
68253ad8626SChristoph Hellwig 		ret = file->f_op->write(file, buf, count, pos);
68353ad8626SChristoph Hellwig 	else if (file->f_op->write_iter)
68453ad8626SChristoph Hellwig 		ret = new_sync_write(file, buf, count, pos);
68553ad8626SChristoph Hellwig 	else
68653ad8626SChristoph Hellwig 		ret = -EINVAL;
6871da177e4SLinus Torvalds 	if (ret > 0) {
6882a12a9d7SEric Paris 		fsnotify_modify(file);
6894b98d11bSAlexey Dobriyan 		add_wchar(current, ret);
6901da177e4SLinus Torvalds 	}
6914b98d11bSAlexey Dobriyan 	inc_syscw(current);
69203d95eb2SAl Viro 	file_end_write(file);
6931da177e4SLinus Torvalds 	return ret;
6941da177e4SLinus Torvalds }
6951da177e4SLinus Torvalds 
696438ab720SKirill Smelkov /* file_ppos returns &file->f_pos or NULL if file is stream */
file_ppos(struct file * file)697438ab720SKirill Smelkov static inline loff_t *file_ppos(struct file *file)
6981da177e4SLinus Torvalds {
699438ab720SKirill Smelkov 	return file->f_mode & FMODE_STREAM ? NULL : &file->f_pos;
7001da177e4SLinus Torvalds }
7011da177e4SLinus Torvalds 
ksys_read(unsigned int fd,char __user * buf,size_t count)7023ce4a7bfSDominik Brodowski ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
7031da177e4SLinus Torvalds {
704d7a9616cSAl Viro 	CLASS(fd_pos, f)(fd);
7051da177e4SLinus Torvalds 	ssize_t ret = -EBADF;
7061da177e4SLinus Torvalds 
707d7a9616cSAl Viro 	if (!fd_empty(f)) {
7081da91ea8SAl Viro 		loff_t pos, *ppos = file_ppos(fd_file(f));
709438ab720SKirill Smelkov 		if (ppos) {
710438ab720SKirill Smelkov 			pos = *ppos;
711438ab720SKirill Smelkov 			ppos = &pos;
712438ab720SKirill Smelkov 		}
7131da91ea8SAl Viro 		ret = vfs_read(fd_file(f), buf, count, ppos);
714438ab720SKirill Smelkov 		if (ret >= 0 && ppos)
7151da91ea8SAl Viro 			fd_file(f)->f_pos = pos;
7161da177e4SLinus Torvalds 	}
7171da177e4SLinus Torvalds 	return ret;
7181da177e4SLinus Torvalds }
7191da177e4SLinus Torvalds 
SYSCALL_DEFINE3(read,unsigned int,fd,char __user *,buf,size_t,count)7203ce4a7bfSDominik Brodowski SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
7213ce4a7bfSDominik Brodowski {
7223ce4a7bfSDominik Brodowski 	return ksys_read(fd, buf, count);
7233ce4a7bfSDominik Brodowski }
7243ce4a7bfSDominik Brodowski 
ksys_write(unsigned int fd,const char __user * buf,size_t count)725e7a3e8b2SDominik Brodowski ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count)
7261da177e4SLinus Torvalds {
727d7a9616cSAl Viro 	CLASS(fd_pos, f)(fd);
7281da177e4SLinus Torvalds 	ssize_t ret = -EBADF;
7291da177e4SLinus Torvalds 
730d7a9616cSAl Viro 	if (!fd_empty(f)) {
7311da91ea8SAl Viro 		loff_t pos, *ppos = file_ppos(fd_file(f));
732438ab720SKirill Smelkov 		if (ppos) {
733438ab720SKirill Smelkov 			pos = *ppos;
734438ab720SKirill Smelkov 			ppos = &pos;
735438ab720SKirill Smelkov 		}
7361da91ea8SAl Viro 		ret = vfs_write(fd_file(f), buf, count, ppos);
737438ab720SKirill Smelkov 		if (ret >= 0 && ppos)
7381da91ea8SAl Viro 			fd_file(f)->f_pos = pos;
7391da177e4SLinus Torvalds 	}
7401da177e4SLinus Torvalds 
7411da177e4SLinus Torvalds 	return ret;
7421da177e4SLinus Torvalds }
7431da177e4SLinus Torvalds 
SYSCALL_DEFINE3(write,unsigned int,fd,const char __user *,buf,size_t,count)744e7a3e8b2SDominik Brodowski SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
745e7a3e8b2SDominik Brodowski 		size_t, count)
746e7a3e8b2SDominik Brodowski {
747e7a3e8b2SDominik Brodowski 	return ksys_write(fd, buf, count);
748e7a3e8b2SDominik Brodowski }
749e7a3e8b2SDominik Brodowski 
ksys_pread64(unsigned int fd,char __user * buf,size_t count,loff_t pos)75036028d5dSDominik Brodowski ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count,
75136028d5dSDominik Brodowski 		     loff_t pos)
7521da177e4SLinus Torvalds {
7531da177e4SLinus Torvalds 	if (pos < 0)
7541da177e4SLinus Torvalds 		return -EINVAL;
7551da177e4SLinus Torvalds 
7568152f820SAl Viro 	CLASS(fd, f)(fd);
7578152f820SAl Viro 	if (fd_empty(f))
7588152f820SAl Viro 		return -EBADF;
7591da177e4SLinus Torvalds 
7608152f820SAl Viro 	if (fd_file(f)->f_mode & FMODE_PREAD)
7618152f820SAl Viro 		return vfs_read(fd_file(f), buf, count, &pos);
7628152f820SAl Viro 
7638152f820SAl Viro 	return -ESPIPE;
7641da177e4SLinus Torvalds }
7651da177e4SLinus Torvalds 
SYSCALL_DEFINE4(pread64,unsigned int,fd,char __user *,buf,size_t,count,loff_t,pos)76636028d5dSDominik Brodowski SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
7674a0fd5bfSAl Viro 			size_t, count, loff_t, pos)
7681da177e4SLinus Torvalds {
76936028d5dSDominik Brodowski 	return ksys_pread64(fd, buf, count, pos);
77036028d5dSDominik Brodowski }
77136028d5dSDominik Brodowski 
77259c10c52SGuo Ren #if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_PREAD64)
COMPAT_SYSCALL_DEFINE5(pread64,unsigned int,fd,char __user *,buf,size_t,count,compat_arg_u64_dual (pos))77359c10c52SGuo Ren COMPAT_SYSCALL_DEFINE5(pread64, unsigned int, fd, char __user *, buf,
77459c10c52SGuo Ren 		       size_t, count, compat_arg_u64_dual(pos))
77559c10c52SGuo Ren {
77659c10c52SGuo Ren 	return ksys_pread64(fd, buf, count, compat_arg_u64_glue(pos));
77759c10c52SGuo Ren }
77859c10c52SGuo Ren #endif
77959c10c52SGuo Ren 
ksys_pwrite64(unsigned int fd,const char __user * buf,size_t count,loff_t pos)78036028d5dSDominik Brodowski ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf,
78136028d5dSDominik Brodowski 		      size_t count, loff_t pos)
78236028d5dSDominik Brodowski {
7831da177e4SLinus Torvalds 	if (pos < 0)
7841da177e4SLinus Torvalds 		return -EINVAL;
7851da177e4SLinus Torvalds 
7868152f820SAl Viro 	CLASS(fd, f)(fd);
7878152f820SAl Viro 	if (fd_empty(f))
7888152f820SAl Viro 		return -EBADF;
7891da177e4SLinus Torvalds 
7908152f820SAl Viro 	if (fd_file(f)->f_mode & FMODE_PWRITE)
7918152f820SAl Viro 		return vfs_write(fd_file(f), buf, count, &pos);
7928152f820SAl Viro 
7938152f820SAl Viro 	return -ESPIPE;
7941da177e4SLinus Torvalds }
7951da177e4SLinus Torvalds 
SYSCALL_DEFINE4(pwrite64,unsigned int,fd,const char __user *,buf,size_t,count,loff_t,pos)79636028d5dSDominik Brodowski SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
79736028d5dSDominik Brodowski 			 size_t, count, loff_t, pos)
79836028d5dSDominik Brodowski {
79936028d5dSDominik Brodowski 	return ksys_pwrite64(fd, buf, count, pos);
80036028d5dSDominik Brodowski }
80136028d5dSDominik Brodowski 
80259c10c52SGuo Ren #if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_PWRITE64)
COMPAT_SYSCALL_DEFINE5(pwrite64,unsigned int,fd,const char __user *,buf,size_t,count,compat_arg_u64_dual (pos))80359c10c52SGuo Ren COMPAT_SYSCALL_DEFINE5(pwrite64, unsigned int, fd, const char __user *, buf,
80459c10c52SGuo Ren 		       size_t, count, compat_arg_u64_dual(pos))
80559c10c52SGuo Ren {
80659c10c52SGuo Ren 	return ksys_pwrite64(fd, buf, count, compat_arg_u64_glue(pos));
80759c10c52SGuo Ren }
80859c10c52SGuo Ren #endif
80959c10c52SGuo Ren 
do_iter_readv_writev(struct file * filp,struct iov_iter * iter,loff_t * ppos,int type,rwf_t flags)810ac15ac06SAl Viro static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
811ddef7ed2SChristoph Hellwig 		loff_t *ppos, int type, rwf_t flags)
812293bc982SAl Viro {
813293bc982SAl Viro 	struct kiocb kiocb;
814293bc982SAl Viro 	ssize_t ret;
815293bc982SAl Viro 
816293bc982SAl Viro 	init_sync_kiocb(&kiocb, filp);
817c34fc6f2SPrasad Singamsetty 	ret = kiocb_set_rw_flags(&kiocb, flags, type);
818fdd2f5b7SGoldwyn Rodrigues 	if (ret)
819fdd2f5b7SGoldwyn Rodrigues 		return ret;
820438ab720SKirill Smelkov 	kiocb.ki_pos = (ppos ? *ppos : 0);
821293bc982SAl Viro 
8220f78d06aSMiklos Szeredi 	if (type == READ)
8237c98f7cbSMiklos Szeredi 		ret = filp->f_op->read_iter(&kiocb, iter);
8240f78d06aSMiklos Szeredi 	else
8257c98f7cbSMiklos Szeredi 		ret = filp->f_op->write_iter(&kiocb, iter);
826599bd19bSChristoph Hellwig 	BUG_ON(ret == -EIOCBQUEUED);
827438ab720SKirill Smelkov 	if (ppos)
828293bc982SAl Viro 		*ppos = kiocb.ki_pos;
829293bc982SAl Viro 	return ret;
830293bc982SAl Viro }
831293bc982SAl Viro 
832ee0b3e67SBadari Pulavarty /* Do it by hand, with file-ops */
do_loop_readv_writev(struct file * filp,struct iov_iter * iter,loff_t * ppos,int type,rwf_t flags)833ac15ac06SAl Viro static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
834ddef7ed2SChristoph Hellwig 		loff_t *ppos, int type, rwf_t flags)
835ee0b3e67SBadari Pulavarty {
836ee0b3e67SBadari Pulavarty 	ssize_t ret = 0;
837ee0b3e67SBadari Pulavarty 
83897be7ebeSChristoph Hellwig 	if (flags & ~RWF_HIPRI)
839793b80efSChristoph Hellwig 		return -EOPNOTSUPP;
840793b80efSChristoph Hellwig 
841ac15ac06SAl Viro 	while (iov_iter_count(iter)) {
842ee0b3e67SBadari Pulavarty 		ssize_t nr;
843ee0b3e67SBadari Pulavarty 
8440f78d06aSMiklos Szeredi 		if (type == READ) {
84595e49cf8SJens Axboe 			nr = filp->f_op->read(filp, iter_iov_addr(iter),
84695e49cf8SJens Axboe 						iter_iov_len(iter), ppos);
8470f78d06aSMiklos Szeredi 		} else {
84895e49cf8SJens Axboe 			nr = filp->f_op->write(filp, iter_iov_addr(iter),
84995e49cf8SJens Axboe 						iter_iov_len(iter), ppos);
8500f78d06aSMiklos Szeredi 		}
851ee0b3e67SBadari Pulavarty 
852ee0b3e67SBadari Pulavarty 		if (nr < 0) {
853ee0b3e67SBadari Pulavarty 			if (!ret)
854ee0b3e67SBadari Pulavarty 				ret = nr;
855ee0b3e67SBadari Pulavarty 			break;
856ee0b3e67SBadari Pulavarty 		}
857ee0b3e67SBadari Pulavarty 		ret += nr;
85895e49cf8SJens Axboe 		if (nr != iter_iov_len(iter))
859ee0b3e67SBadari Pulavarty 			break;
860ac15ac06SAl Viro 		iov_iter_advance(iter, nr);
861ee0b3e67SBadari Pulavarty 	}
862ee0b3e67SBadari Pulavarty 
863ee0b3e67SBadari Pulavarty 	return ret;
864ee0b3e67SBadari Pulavarty }
865ee0b3e67SBadari Pulavarty 
vfs_iocb_iter_read(struct file * file,struct kiocb * iocb,struct iov_iter * iter)8665dcdc43eSJiufei Xue ssize_t vfs_iocb_iter_read(struct file *file, struct kiocb *iocb,
8675dcdc43eSJiufei Xue 			   struct iov_iter *iter)
8685dcdc43eSJiufei Xue {
8695dcdc43eSJiufei Xue 	size_t tot_len;
8705dcdc43eSJiufei Xue 	ssize_t ret = 0;
8715dcdc43eSJiufei Xue 
8725dcdc43eSJiufei Xue 	if (!file->f_op->read_iter)
8735dcdc43eSJiufei Xue 		return -EINVAL;
8745dcdc43eSJiufei Xue 	if (!(file->f_mode & FMODE_READ))
8755dcdc43eSJiufei Xue 		return -EBADF;
8765dcdc43eSJiufei Xue 	if (!(file->f_mode & FMODE_CAN_READ))
8775dcdc43eSJiufei Xue 		return -EINVAL;
8785dcdc43eSJiufei Xue 
8795dcdc43eSJiufei Xue 	tot_len = iov_iter_count(iter);
8805dcdc43eSJiufei Xue 	if (!tot_len)
8815dcdc43eSJiufei Xue 		goto out;
8825dcdc43eSJiufei Xue 	ret = rw_verify_area(READ, file, &iocb->ki_pos, tot_len);
8835dcdc43eSJiufei Xue 	if (ret < 0)
8845dcdc43eSJiufei Xue 		return ret;
8855dcdc43eSJiufei Xue 
8867c98f7cbSMiklos Szeredi 	ret = file->f_op->read_iter(iocb, iter);
8875dcdc43eSJiufei Xue out:
8885dcdc43eSJiufei Xue 	if (ret >= 0)
8895dcdc43eSJiufei Xue 		fsnotify_access(file);
8905dcdc43eSJiufei Xue 	return ret;
8915dcdc43eSJiufei Xue }
8925dcdc43eSJiufei Xue EXPORT_SYMBOL(vfs_iocb_iter_read);
8935dcdc43eSJiufei Xue 
vfs_iter_read(struct file * file,struct iov_iter * iter,loff_t * ppos,rwf_t flags)89418e9710eSChristoph Hellwig ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos,
895ddef7ed2SChristoph Hellwig 		      rwf_t flags)
8967687a7a4SMiklos Szeredi {
897b8e1425bSAmir Goldstein 	size_t tot_len;
898b8e1425bSAmir Goldstein 	ssize_t ret = 0;
899b8e1425bSAmir Goldstein 
90018e9710eSChristoph Hellwig 	if (!file->f_op->read_iter)
90118e9710eSChristoph Hellwig 		return -EINVAL;
902b8e1425bSAmir Goldstein 	if (!(file->f_mode & FMODE_READ))
903b8e1425bSAmir Goldstein 		return -EBADF;
904b8e1425bSAmir Goldstein 	if (!(file->f_mode & FMODE_CAN_READ))
905b8e1425bSAmir Goldstein 		return -EINVAL;
906b8e1425bSAmir Goldstein 
907b8e1425bSAmir Goldstein 	tot_len = iov_iter_count(iter);
908b8e1425bSAmir Goldstein 	if (!tot_len)
909b8e1425bSAmir Goldstein 		goto out;
910b8e1425bSAmir Goldstein 	ret = rw_verify_area(READ, file, ppos, tot_len);
911b8e1425bSAmir Goldstein 	if (ret < 0)
912b8e1425bSAmir Goldstein 		return ret;
913b8e1425bSAmir Goldstein 
914b8e1425bSAmir Goldstein 	ret = do_iter_readv_writev(file, iter, ppos, READ, flags);
915b8e1425bSAmir Goldstein out:
916b8e1425bSAmir Goldstein 	if (ret >= 0)
917b8e1425bSAmir Goldstein 		fsnotify_access(file);
918b8e1425bSAmir Goldstein 	return ret;
91918e9710eSChristoph Hellwig }
92018e9710eSChristoph Hellwig EXPORT_SYMBOL(vfs_iter_read);
92118e9710eSChristoph Hellwig 
9226ae65439SAmir Goldstein /*
9236ae65439SAmir Goldstein  * Caller is responsible for calling kiocb_end_write() on completion
9246ae65439SAmir Goldstein  * if async iocb was queued.
9256ae65439SAmir Goldstein  */
vfs_iocb_iter_write(struct file * file,struct kiocb * iocb,struct iov_iter * iter)9265dcdc43eSJiufei Xue ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
9275dcdc43eSJiufei Xue 			    struct iov_iter *iter)
9285dcdc43eSJiufei Xue {
9295dcdc43eSJiufei Xue 	size_t tot_len;
9305dcdc43eSJiufei Xue 	ssize_t ret = 0;
9315dcdc43eSJiufei Xue 
9325dcdc43eSJiufei Xue 	if (!file->f_op->write_iter)
9335dcdc43eSJiufei Xue 		return -EINVAL;
9345dcdc43eSJiufei Xue 	if (!(file->f_mode & FMODE_WRITE))
9355dcdc43eSJiufei Xue 		return -EBADF;
9365dcdc43eSJiufei Xue 	if (!(file->f_mode & FMODE_CAN_WRITE))
9375dcdc43eSJiufei Xue 		return -EINVAL;
9385dcdc43eSJiufei Xue 
9395dcdc43eSJiufei Xue 	tot_len = iov_iter_count(iter);
9405dcdc43eSJiufei Xue 	if (!tot_len)
9415dcdc43eSJiufei Xue 		return 0;
9425dcdc43eSJiufei Xue 	ret = rw_verify_area(WRITE, file, &iocb->ki_pos, tot_len);
9435dcdc43eSJiufei Xue 	if (ret < 0)
9445dcdc43eSJiufei Xue 		return ret;
9455dcdc43eSJiufei Xue 
9466ae65439SAmir Goldstein 	kiocb_start_write(iocb);
9477c98f7cbSMiklos Szeredi 	ret = file->f_op->write_iter(iocb, iter);
9486ae65439SAmir Goldstein 	if (ret != -EIOCBQUEUED)
9496ae65439SAmir Goldstein 		kiocb_end_write(iocb);
9505dcdc43eSJiufei Xue 	if (ret > 0)
9515dcdc43eSJiufei Xue 		fsnotify_modify(file);
9525dcdc43eSJiufei Xue 
9535dcdc43eSJiufei Xue 	return ret;
9545dcdc43eSJiufei Xue }
9555dcdc43eSJiufei Xue EXPORT_SYMBOL(vfs_iocb_iter_write);
9565dcdc43eSJiufei Xue 
vfs_iter_write(struct file * file,struct iov_iter * iter,loff_t * ppos,rwf_t flags)957abbb6589SChristoph Hellwig ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos,
958ddef7ed2SChristoph Hellwig 		       rwf_t flags)
959abbb6589SChristoph Hellwig {
9601c8aa833SAmir Goldstein 	size_t tot_len;
9611c8aa833SAmir Goldstein 	ssize_t ret;
962269aed70SAmir Goldstein 
9631c8aa833SAmir Goldstein 	if (!(file->f_mode & FMODE_WRITE))
9641c8aa833SAmir Goldstein 		return -EBADF;
9651c8aa833SAmir Goldstein 	if (!(file->f_mode & FMODE_CAN_WRITE))
9661c8aa833SAmir Goldstein 		return -EINVAL;
967abbb6589SChristoph Hellwig 	if (!file->f_op->write_iter)
968abbb6589SChristoph Hellwig 		return -EINVAL;
969269aed70SAmir Goldstein 
9701c8aa833SAmir Goldstein 	tot_len = iov_iter_count(iter);
9711c8aa833SAmir Goldstein 	if (!tot_len)
9721c8aa833SAmir Goldstein 		return 0;
9731c8aa833SAmir Goldstein 
9741c8aa833SAmir Goldstein 	ret = rw_verify_area(WRITE, file, ppos, tot_len);
9751c8aa833SAmir Goldstein 	if (ret < 0)
9761c8aa833SAmir Goldstein 		return ret;
9771c8aa833SAmir Goldstein 
978269aed70SAmir Goldstein 	file_start_write(file);
9791c8aa833SAmir Goldstein 	ret = do_iter_readv_writev(file, iter, ppos, WRITE, flags);
9801c8aa833SAmir Goldstein 	if (ret > 0)
9811c8aa833SAmir Goldstein 		fsnotify_modify(file);
982269aed70SAmir Goldstein 	file_end_write(file);
983269aed70SAmir Goldstein 
984269aed70SAmir Goldstein 	return ret;
985abbb6589SChristoph Hellwig }
986abbb6589SChristoph Hellwig EXPORT_SYMBOL(vfs_iter_write);
987abbb6589SChristoph Hellwig 
vfs_readv(struct file * file,const struct iovec __user * vec,unsigned long vlen,loff_t * pos,rwf_t flags)98836e2c742SChristoph Hellwig static ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
989ddef7ed2SChristoph Hellwig 			 unsigned long vlen, loff_t *pos, rwf_t flags)
9907687a7a4SMiklos Szeredi {
9917687a7a4SMiklos Szeredi 	struct iovec iovstack[UIO_FASTIOV];
9927687a7a4SMiklos Szeredi 	struct iovec *iov = iovstack;
9937687a7a4SMiklos Szeredi 	struct iov_iter iter;
994b8e1425bSAmir Goldstein 	size_t tot_len;
995b8e1425bSAmir Goldstein 	ssize_t ret = 0;
9967687a7a4SMiklos Szeredi 
997b8e1425bSAmir Goldstein 	if (!(file->f_mode & FMODE_READ))
998b8e1425bSAmir Goldstein 		return -EBADF;
999b8e1425bSAmir Goldstein 	if (!(file->f_mode & FMODE_CAN_READ))
1000b8e1425bSAmir Goldstein 		return -EINVAL;
1001b8e1425bSAmir Goldstein 
1002b8e1425bSAmir Goldstein 	ret = import_iovec(ITER_DEST, vec, vlen, ARRAY_SIZE(iovstack), &iov,
1003b8e1425bSAmir Goldstein 			   &iter);
1004b8e1425bSAmir Goldstein 	if (ret < 0)
1005b8e1425bSAmir Goldstein 		return ret;
1006b8e1425bSAmir Goldstein 
1007b8e1425bSAmir Goldstein 	tot_len = iov_iter_count(&iter);
1008b8e1425bSAmir Goldstein 	if (!tot_len)
1009b8e1425bSAmir Goldstein 		goto out;
1010b8e1425bSAmir Goldstein 
1011b8e1425bSAmir Goldstein 	ret = rw_verify_area(READ, file, pos, tot_len);
1012b8e1425bSAmir Goldstein 	if (ret < 0)
1013b8e1425bSAmir Goldstein 		goto out;
1014b8e1425bSAmir Goldstein 
1015b8e1425bSAmir Goldstein 	if (file->f_op->read_iter)
1016b8e1425bSAmir Goldstein 		ret = do_iter_readv_writev(file, &iter, pos, READ, flags);
1017b8e1425bSAmir Goldstein 	else
1018b8e1425bSAmir Goldstein 		ret = do_loop_readv_writev(file, &iter, pos, READ, flags);
1019b8e1425bSAmir Goldstein out:
1020b8e1425bSAmir Goldstein 	if (ret >= 0)
1021b8e1425bSAmir Goldstein 		fsnotify_access(file);
10227687a7a4SMiklos Szeredi 	kfree(iov);
10237687a7a4SMiklos Szeredi 	return ret;
10247687a7a4SMiklos Szeredi }
10251da177e4SLinus Torvalds 
vfs_writev(struct file * file,const struct iovec __user * vec,unsigned long vlen,loff_t * pos,rwf_t flags)10269725d4ceSChristoph Hellwig static ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
1027ddef7ed2SChristoph Hellwig 			  unsigned long vlen, loff_t *pos, rwf_t flags)
10281da177e4SLinus Torvalds {
1029251b42a1SChristoph Hellwig 	struct iovec iovstack[UIO_FASTIOV];
1030251b42a1SChristoph Hellwig 	struct iovec *iov = iovstack;
1031251b42a1SChristoph Hellwig 	struct iov_iter iter;
10321c8aa833SAmir Goldstein 	size_t tot_len;
10331c8aa833SAmir Goldstein 	ssize_t ret = 0;
10341da177e4SLinus Torvalds 
10351c8aa833SAmir Goldstein 	if (!(file->f_mode & FMODE_WRITE))
10361c8aa833SAmir Goldstein 		return -EBADF;
10371c8aa833SAmir Goldstein 	if (!(file->f_mode & FMODE_CAN_WRITE))
10381c8aa833SAmir Goldstein 		return -EINVAL;
10391c8aa833SAmir Goldstein 
10401c8aa833SAmir Goldstein 	ret = import_iovec(ITER_SOURCE, vec, vlen, ARRAY_SIZE(iovstack), &iov,
10411c8aa833SAmir Goldstein 			   &iter);
10421c8aa833SAmir Goldstein 	if (ret < 0)
10431c8aa833SAmir Goldstein 		return ret;
10441c8aa833SAmir Goldstein 
10451c8aa833SAmir Goldstein 	tot_len = iov_iter_count(&iter);
10461c8aa833SAmir Goldstein 	if (!tot_len)
10471c8aa833SAmir Goldstein 		goto out;
10481c8aa833SAmir Goldstein 
10491c8aa833SAmir Goldstein 	ret = rw_verify_area(WRITE, file, pos, tot_len);
10501c8aa833SAmir Goldstein 	if (ret < 0)
10511c8aa833SAmir Goldstein 		goto out;
10521c8aa833SAmir Goldstein 
105362473a2dSAl Viro 	file_start_write(file);
10541c8aa833SAmir Goldstein 	if (file->f_op->write_iter)
10551c8aa833SAmir Goldstein 		ret = do_iter_readv_writev(file, &iter, pos, WRITE, flags);
10561c8aa833SAmir Goldstein 	else
10571c8aa833SAmir Goldstein 		ret = do_loop_readv_writev(file, &iter, pos, WRITE, flags);
10581c8aa833SAmir Goldstein 	if (ret > 0)
10591c8aa833SAmir Goldstein 		fsnotify_modify(file);
106062473a2dSAl Viro 	file_end_write(file);
10611c8aa833SAmir Goldstein out:
1062251b42a1SChristoph Hellwig 	kfree(iov);
1063251b42a1SChristoph Hellwig 	return ret;
1064251b42a1SChristoph Hellwig }
10651da177e4SLinus Torvalds 
do_readv(unsigned long fd,const struct iovec __user * vec,unsigned long vlen,rwf_t flags)1066f17d8b35SMilosz Tanski static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
1067ddef7ed2SChristoph Hellwig 			unsigned long vlen, rwf_t flags)
10681da177e4SLinus Torvalds {
1069d7a9616cSAl Viro 	CLASS(fd_pos, f)(fd);
10701da177e4SLinus Torvalds 	ssize_t ret = -EBADF;
10711da177e4SLinus Torvalds 
1072d7a9616cSAl Viro 	if (!fd_empty(f)) {
10731da91ea8SAl Viro 		loff_t pos, *ppos = file_ppos(fd_file(f));
1074438ab720SKirill Smelkov 		if (ppos) {
1075438ab720SKirill Smelkov 			pos = *ppos;
1076438ab720SKirill Smelkov 			ppos = &pos;
1077438ab720SKirill Smelkov 		}
10781da91ea8SAl Viro 		ret = vfs_readv(fd_file(f), vec, vlen, ppos, flags);
1079438ab720SKirill Smelkov 		if (ret >= 0 && ppos)
10801da91ea8SAl Viro 			fd_file(f)->f_pos = pos;
10811da177e4SLinus Torvalds 	}
10821da177e4SLinus Torvalds 
10831da177e4SLinus Torvalds 	if (ret > 0)
10844b98d11bSAlexey Dobriyan 		add_rchar(current, ret);
10854b98d11bSAlexey Dobriyan 	inc_syscr(current);
10861da177e4SLinus Torvalds 	return ret;
10871da177e4SLinus Torvalds }
10881da177e4SLinus Torvalds 
do_writev(unsigned long fd,const struct iovec __user * vec,unsigned long vlen,rwf_t flags)1089f17d8b35SMilosz Tanski static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec,
1090ddef7ed2SChristoph Hellwig 			 unsigned long vlen, rwf_t flags)
10911da177e4SLinus Torvalds {
1092d7a9616cSAl Viro 	CLASS(fd_pos, f)(fd);
10931da177e4SLinus Torvalds 	ssize_t ret = -EBADF;
10941da177e4SLinus Torvalds 
1095d7a9616cSAl Viro 	if (!fd_empty(f)) {
10961da91ea8SAl Viro 		loff_t pos, *ppos = file_ppos(fd_file(f));
1097438ab720SKirill Smelkov 		if (ppos) {
1098438ab720SKirill Smelkov 			pos = *ppos;
1099438ab720SKirill Smelkov 			ppos = &pos;
1100438ab720SKirill Smelkov 		}
11011da91ea8SAl Viro 		ret = vfs_writev(fd_file(f), vec, vlen, ppos, flags);
1102438ab720SKirill Smelkov 		if (ret >= 0 && ppos)
11031da91ea8SAl Viro 			fd_file(f)->f_pos = pos;
11041da177e4SLinus Torvalds 	}
11051da177e4SLinus Torvalds 
11061da177e4SLinus Torvalds 	if (ret > 0)
11074b98d11bSAlexey Dobriyan 		add_wchar(current, ret);
11084b98d11bSAlexey Dobriyan 	inc_syscw(current);
11091da177e4SLinus Torvalds 	return ret;
11101da177e4SLinus Torvalds }
11111da177e4SLinus Torvalds 
pos_from_hilo(unsigned long high,unsigned long low)1112601cc11dSLinus Torvalds static inline loff_t pos_from_hilo(unsigned long high, unsigned long low)
1113f3554f4bSGerd Hoffmann {
1114601cc11dSLinus Torvalds #define HALF_LONG_BITS (BITS_PER_LONG / 2)
1115601cc11dSLinus Torvalds 	return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low;
1116601cc11dSLinus Torvalds }
1117601cc11dSLinus Torvalds 
do_preadv(unsigned long fd,const struct iovec __user * vec,unsigned long vlen,loff_t pos,rwf_t flags)1118f17d8b35SMilosz Tanski static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
1119ddef7ed2SChristoph Hellwig 			 unsigned long vlen, loff_t pos, rwf_t flags)
1120601cc11dSLinus Torvalds {
1121f3554f4bSGerd Hoffmann 	ssize_t ret = -EBADF;
1122f3554f4bSGerd Hoffmann 
1123f3554f4bSGerd Hoffmann 	if (pos < 0)
1124f3554f4bSGerd Hoffmann 		return -EINVAL;
1125f3554f4bSGerd Hoffmann 
112620d9eb3bSAl Viro 	CLASS(fd, f)(fd);
112720d9eb3bSAl Viro 	if (!fd_empty(f)) {
1128f3554f4bSGerd Hoffmann 		ret = -ESPIPE;
11291da91ea8SAl Viro 		if (fd_file(f)->f_mode & FMODE_PREAD)
11301da91ea8SAl Viro 			ret = vfs_readv(fd_file(f), vec, vlen, &pos, flags);
1131f3554f4bSGerd Hoffmann 	}
1132f3554f4bSGerd Hoffmann 
1133f3554f4bSGerd Hoffmann 	if (ret > 0)
1134f3554f4bSGerd Hoffmann 		add_rchar(current, ret);
1135f3554f4bSGerd Hoffmann 	inc_syscr(current);
1136f3554f4bSGerd Hoffmann 	return ret;
1137f3554f4bSGerd Hoffmann }
1138f3554f4bSGerd Hoffmann 
do_pwritev(unsigned long fd,const struct iovec __user * vec,unsigned long vlen,loff_t pos,rwf_t flags)1139f17d8b35SMilosz Tanski static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec,
1140ddef7ed2SChristoph Hellwig 			  unsigned long vlen, loff_t pos, rwf_t flags)
1141f3554f4bSGerd Hoffmann {
1142f3554f4bSGerd Hoffmann 	ssize_t ret = -EBADF;
1143f3554f4bSGerd Hoffmann 
1144f3554f4bSGerd Hoffmann 	if (pos < 0)
1145f3554f4bSGerd Hoffmann 		return -EINVAL;
1146f3554f4bSGerd Hoffmann 
114720d9eb3bSAl Viro 	CLASS(fd, f)(fd);
114820d9eb3bSAl Viro 	if (!fd_empty(f)) {
1149f3554f4bSGerd Hoffmann 		ret = -ESPIPE;
11501da91ea8SAl Viro 		if (fd_file(f)->f_mode & FMODE_PWRITE)
11511da91ea8SAl Viro 			ret = vfs_writev(fd_file(f), vec, vlen, &pos, flags);
1152f3554f4bSGerd Hoffmann 	}
1153f3554f4bSGerd Hoffmann 
1154f3554f4bSGerd Hoffmann 	if (ret > 0)
1155f3554f4bSGerd Hoffmann 		add_wchar(current, ret);
1156f3554f4bSGerd Hoffmann 	inc_syscw(current);
1157f3554f4bSGerd Hoffmann 	return ret;
1158f3554f4bSGerd Hoffmann }
1159f3554f4bSGerd Hoffmann 
SYSCALL_DEFINE3(readv,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen)1160f17d8b35SMilosz Tanski SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
1161f17d8b35SMilosz Tanski 		unsigned long, vlen)
1162f17d8b35SMilosz Tanski {
1163f17d8b35SMilosz Tanski 	return do_readv(fd, vec, vlen, 0);
1164f17d8b35SMilosz Tanski }
1165f17d8b35SMilosz Tanski 
SYSCALL_DEFINE3(writev,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen)1166f17d8b35SMilosz Tanski SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
1167f17d8b35SMilosz Tanski 		unsigned long, vlen)
1168f17d8b35SMilosz Tanski {
1169f17d8b35SMilosz Tanski 	return do_writev(fd, vec, vlen, 0);
1170f17d8b35SMilosz Tanski }
1171f17d8b35SMilosz Tanski 
SYSCALL_DEFINE5(preadv,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen,unsigned long,pos_l,unsigned long,pos_h)1172f17d8b35SMilosz Tanski SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
1173f17d8b35SMilosz Tanski 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
1174f17d8b35SMilosz Tanski {
1175f17d8b35SMilosz Tanski 	loff_t pos = pos_from_hilo(pos_h, pos_l);
1176f17d8b35SMilosz Tanski 
1177f17d8b35SMilosz Tanski 	return do_preadv(fd, vec, vlen, pos, 0);
1178f17d8b35SMilosz Tanski }
1179f17d8b35SMilosz Tanski 
SYSCALL_DEFINE6(preadv2,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen,unsigned long,pos_l,unsigned long,pos_h,rwf_t,flags)1180f17d8b35SMilosz Tanski SYSCALL_DEFINE6(preadv2, unsigned long, fd, const struct iovec __user *, vec,
1181f17d8b35SMilosz Tanski 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
1182ddef7ed2SChristoph Hellwig 		rwf_t, flags)
1183f17d8b35SMilosz Tanski {
1184f17d8b35SMilosz Tanski 	loff_t pos = pos_from_hilo(pos_h, pos_l);
1185f17d8b35SMilosz Tanski 
1186f17d8b35SMilosz Tanski 	if (pos == -1)
1187f17d8b35SMilosz Tanski 		return do_readv(fd, vec, vlen, flags);
1188f17d8b35SMilosz Tanski 
1189f17d8b35SMilosz Tanski 	return do_preadv(fd, vec, vlen, pos, flags);
1190f17d8b35SMilosz Tanski }
1191f17d8b35SMilosz Tanski 
SYSCALL_DEFINE5(pwritev,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen,unsigned long,pos_l,unsigned long,pos_h)1192f17d8b35SMilosz Tanski SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
1193f17d8b35SMilosz Tanski 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
1194f17d8b35SMilosz Tanski {
1195f17d8b35SMilosz Tanski 	loff_t pos = pos_from_hilo(pos_h, pos_l);
1196f17d8b35SMilosz Tanski 
1197f17d8b35SMilosz Tanski 	return do_pwritev(fd, vec, vlen, pos, 0);
1198f17d8b35SMilosz Tanski }
1199f17d8b35SMilosz Tanski 
SYSCALL_DEFINE6(pwritev2,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen,unsigned long,pos_l,unsigned long,pos_h,rwf_t,flags)1200f17d8b35SMilosz Tanski SYSCALL_DEFINE6(pwritev2, unsigned long, fd, const struct iovec __user *, vec,
1201f17d8b35SMilosz Tanski 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
1202ddef7ed2SChristoph Hellwig 		rwf_t, flags)
1203f17d8b35SMilosz Tanski {
1204f17d8b35SMilosz Tanski 	loff_t pos = pos_from_hilo(pos_h, pos_l);
1205f17d8b35SMilosz Tanski 
1206f17d8b35SMilosz Tanski 	if (pos == -1)
1207f17d8b35SMilosz Tanski 		return do_writev(fd, vec, vlen, flags);
1208f17d8b35SMilosz Tanski 
1209f17d8b35SMilosz Tanski 	return do_pwritev(fd, vec, vlen, pos, flags);
1210f17d8b35SMilosz Tanski }
1211f17d8b35SMilosz Tanski 
12123523a9d4SChristoph Hellwig /*
12133523a9d4SChristoph Hellwig  * Various compat syscalls.  Note that they all pretend to take a native
12143523a9d4SChristoph Hellwig  * iovec - import_iovec will properly treat those as compat_iovecs based on
12153523a9d4SChristoph Hellwig  * in_compat_syscall().
12163523a9d4SChristoph Hellwig  */
121772ec3516SAl Viro #ifdef CONFIG_COMPAT
1218378a10f3SHeiko Carstens #ifdef __ARCH_WANT_COMPAT_SYS_PREADV64
COMPAT_SYSCALL_DEFINE4(preadv64,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen,loff_t,pos)1219378a10f3SHeiko Carstens COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
12203523a9d4SChristoph Hellwig 		const struct iovec __user *, vec,
1221378a10f3SHeiko Carstens 		unsigned long, vlen, loff_t, pos)
1222378a10f3SHeiko Carstens {
12233523a9d4SChristoph Hellwig 	return do_preadv(fd, vec, vlen, pos, 0);
1224378a10f3SHeiko Carstens }
1225378a10f3SHeiko Carstens #endif
1226378a10f3SHeiko Carstens 
COMPAT_SYSCALL_DEFINE5(preadv,compat_ulong_t,fd,const struct iovec __user *,vec,compat_ulong_t,vlen,u32,pos_low,u32,pos_high)1227dfd948e3SHeiko Carstens COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
12283523a9d4SChristoph Hellwig 		const struct iovec __user *, vec,
1229dfd948e3SHeiko Carstens 		compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
123072ec3516SAl Viro {
123172ec3516SAl Viro 	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1232378a10f3SHeiko Carstens 
12333523a9d4SChristoph Hellwig 	return do_preadv(fd, vec, vlen, pos, 0);
1234f17d8b35SMilosz Tanski }
1235f17d8b35SMilosz Tanski 
12363ebfd81fSH.J. Lu #ifdef __ARCH_WANT_COMPAT_SYS_PREADV64V2
COMPAT_SYSCALL_DEFINE5(preadv64v2,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen,loff_t,pos,rwf_t,flags)12373ebfd81fSH.J. Lu COMPAT_SYSCALL_DEFINE5(preadv64v2, unsigned long, fd,
12383523a9d4SChristoph Hellwig 		const struct iovec __user *, vec,
1239ddef7ed2SChristoph Hellwig 		unsigned long, vlen, loff_t, pos, rwf_t, flags)
12403ebfd81fSH.J. Lu {
1241cc4b1242SAurelien Jarno 	if (pos == -1)
12423523a9d4SChristoph Hellwig 		return do_readv(fd, vec, vlen, flags);
12433523a9d4SChristoph Hellwig 	return do_preadv(fd, vec, vlen, pos, flags);
12443ebfd81fSH.J. Lu }
12453ebfd81fSH.J. Lu #endif
12463ebfd81fSH.J. Lu 
COMPAT_SYSCALL_DEFINE6(preadv2,compat_ulong_t,fd,const struct iovec __user *,vec,compat_ulong_t,vlen,u32,pos_low,u32,pos_high,rwf_t,flags)1247f17d8b35SMilosz Tanski COMPAT_SYSCALL_DEFINE6(preadv2, compat_ulong_t, fd,
12483523a9d4SChristoph Hellwig 		const struct iovec __user *, vec,
1249f17d8b35SMilosz Tanski 		compat_ulong_t, vlen, u32, pos_low, u32, pos_high,
1250ddef7ed2SChristoph Hellwig 		rwf_t, flags)
1251f17d8b35SMilosz Tanski {
1252f17d8b35SMilosz Tanski 	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1253f17d8b35SMilosz Tanski 
1254f17d8b35SMilosz Tanski 	if (pos == -1)
12553523a9d4SChristoph Hellwig 		return do_readv(fd, vec, vlen, flags);
12563523a9d4SChristoph Hellwig 	return do_preadv(fd, vec, vlen, pos, flags);
125772ec3516SAl Viro }
125872ec3516SAl Viro 
1259378a10f3SHeiko Carstens #ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64
COMPAT_SYSCALL_DEFINE4(pwritev64,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen,loff_t,pos)1260378a10f3SHeiko Carstens COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
12613523a9d4SChristoph Hellwig 		const struct iovec __user *, vec,
1262378a10f3SHeiko Carstens 		unsigned long, vlen, loff_t, pos)
1263378a10f3SHeiko Carstens {
12643523a9d4SChristoph Hellwig 	return do_pwritev(fd, vec, vlen, pos, 0);
1265378a10f3SHeiko Carstens }
1266378a10f3SHeiko Carstens #endif
1267378a10f3SHeiko Carstens 
COMPAT_SYSCALL_DEFINE5(pwritev,compat_ulong_t,fd,const struct iovec __user *,vec,compat_ulong_t,vlen,u32,pos_low,u32,pos_high)1268dfd948e3SHeiko Carstens COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
12693523a9d4SChristoph Hellwig 		const struct iovec __user *,vec,
1270dfd948e3SHeiko Carstens 		compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
127172ec3516SAl Viro {
127272ec3516SAl Viro 	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1273378a10f3SHeiko Carstens 
12743523a9d4SChristoph Hellwig 	return do_pwritev(fd, vec, vlen, pos, 0);
127572ec3516SAl Viro }
1276f17d8b35SMilosz Tanski 
12773ebfd81fSH.J. Lu #ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64V2
COMPAT_SYSCALL_DEFINE5(pwritev64v2,unsigned long,fd,const struct iovec __user *,vec,unsigned long,vlen,loff_t,pos,rwf_t,flags)12783ebfd81fSH.J. Lu COMPAT_SYSCALL_DEFINE5(pwritev64v2, unsigned long, fd,
12793523a9d4SChristoph Hellwig 		const struct iovec __user *, vec,
1280ddef7ed2SChristoph Hellwig 		unsigned long, vlen, loff_t, pos, rwf_t, flags)
12813ebfd81fSH.J. Lu {
1282cc4b1242SAurelien Jarno 	if (pos == -1)
12833523a9d4SChristoph Hellwig 		return do_writev(fd, vec, vlen, flags);
12843523a9d4SChristoph Hellwig 	return do_pwritev(fd, vec, vlen, pos, flags);
12853ebfd81fSH.J. Lu }
12863ebfd81fSH.J. Lu #endif
12873ebfd81fSH.J. Lu 
COMPAT_SYSCALL_DEFINE6(pwritev2,compat_ulong_t,fd,const struct iovec __user *,vec,compat_ulong_t,vlen,u32,pos_low,u32,pos_high,rwf_t,flags)1288f17d8b35SMilosz Tanski COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd,
12893523a9d4SChristoph Hellwig 		const struct iovec __user *,vec,
1290ddef7ed2SChristoph Hellwig 		compat_ulong_t, vlen, u32, pos_low, u32, pos_high, rwf_t, flags)
1291f17d8b35SMilosz Tanski {
1292f17d8b35SMilosz Tanski 	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1293f17d8b35SMilosz Tanski 
1294f17d8b35SMilosz Tanski 	if (pos == -1)
12953523a9d4SChristoph Hellwig 		return do_writev(fd, vec, vlen, flags);
12963523a9d4SChristoph Hellwig 	return do_pwritev(fd, vec, vlen, pos, flags);
1297f17d8b35SMilosz Tanski }
12983523a9d4SChristoph Hellwig #endif /* CONFIG_COMPAT */
129972ec3516SAl Viro 
do_sendfile(int out_fd,int in_fd,loff_t * ppos,size_t count,loff_t max)130019f4fc3aSAl Viro static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
130119f4fc3aSAl Viro 			   size_t count, loff_t max)
13021da177e4SLinus Torvalds {
13031da177e4SLinus Torvalds 	struct inode *in_inode, *out_inode;
1304b964bf53SAl Viro 	struct pipe_inode_info *opipe;
13051da177e4SLinus Torvalds 	loff_t pos;
13067995bd28SAl Viro 	loff_t out_pos;
13071da177e4SLinus Torvalds 	ssize_t retval;
13082903ff01SAl Viro 	int fl;
13091da177e4SLinus Torvalds 
13101da177e4SLinus Torvalds 	/*
13111da177e4SLinus Torvalds 	 * Get input file, and verify that it is ok..
13121da177e4SLinus Torvalds 	 */
13138152f820SAl Viro 	CLASS(fd, in)(in_fd);
13148152f820SAl Viro 	if (fd_empty(in))
13158152f820SAl Viro 		return -EBADF;
13161da91ea8SAl Viro 	if (!(fd_file(in)->f_mode & FMODE_READ))
13178152f820SAl Viro 		return -EBADF;
13187995bd28SAl Viro 	if (!ppos) {
13191da91ea8SAl Viro 		pos = fd_file(in)->f_pos;
13207995bd28SAl Viro 	} else {
13217995bd28SAl Viro 		pos = *ppos;
13221da91ea8SAl Viro 		if (!(fd_file(in)->f_mode & FMODE_PREAD))
13238152f820SAl Viro 			return -ESPIPE;
13247995bd28SAl Viro 	}
13251da91ea8SAl Viro 	retval = rw_verify_area(READ, fd_file(in), &pos, count);
1326e28cc715SLinus Torvalds 	if (retval < 0)
13278152f820SAl Viro 		return retval;
1328bc61384dSAl Viro 	if (count > MAX_RW_COUNT)
1329bc61384dSAl Viro 		count =  MAX_RW_COUNT;
13301da177e4SLinus Torvalds 
13311da177e4SLinus Torvalds 	/*
13321da177e4SLinus Torvalds 	 * Get output file, and verify that it is ok..
13331da177e4SLinus Torvalds 	 */
13348152f820SAl Viro 	CLASS(fd, out)(out_fd);
13358152f820SAl Viro 	if (fd_empty(out))
13368152f820SAl Viro 		return -EBADF;
13371da91ea8SAl Viro 	if (!(fd_file(out)->f_mode & FMODE_WRITE))
13388152f820SAl Viro 		return -EBADF;
13391da91ea8SAl Viro 	in_inode = file_inode(fd_file(in));
13401da91ea8SAl Viro 	out_inode = file_inode(fd_file(out));
13411da91ea8SAl Viro 	out_pos = fd_file(out)->f_pos;
13421da177e4SLinus Torvalds 
13431da177e4SLinus Torvalds 	if (!max)
13441da177e4SLinus Torvalds 		max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
13451da177e4SLinus Torvalds 
13461da177e4SLinus Torvalds 	if (unlikely(pos + count > max)) {
13471da177e4SLinus Torvalds 		if (pos >= max)
13488152f820SAl Viro 			return -EOVERFLOW;
13491da177e4SLinus Torvalds 		count = max - pos;
13501da177e4SLinus Torvalds 	}
13511da177e4SLinus Torvalds 
1352534f2aaaSJens Axboe 	fl = 0;
1353534f2aaaSJens Axboe #if 0
1354534f2aaaSJens Axboe 	/*
1355534f2aaaSJens Axboe 	 * We need to debate whether we can enable this or not. The
1356534f2aaaSJens Axboe 	 * man page documents EAGAIN return for the output at least,
1357534f2aaaSJens Axboe 	 * and the application is arguably buggy if it doesn't expect
1358534f2aaaSJens Axboe 	 * EAGAIN on a non-blocking file descriptor.
1359534f2aaaSJens Axboe 	 */
13601da91ea8SAl Viro 	if (fd_file(in)->f_flags & O_NONBLOCK)
1361534f2aaaSJens Axboe 		fl = SPLICE_F_NONBLOCK;
1362534f2aaaSJens Axboe #endif
13631da91ea8SAl Viro 	opipe = get_pipe_info(fd_file(out), true);
1364b964bf53SAl Viro 	if (!opipe) {
13651da91ea8SAl Viro 		retval = rw_verify_area(WRITE, fd_file(out), &out_pos, count);
1366b964bf53SAl Viro 		if (retval < 0)
13678152f820SAl Viro 			return retval;
13681da91ea8SAl Viro 		retval = do_splice_direct(fd_file(in), &pos, fd_file(out), &out_pos,
1369b964bf53SAl Viro 					  count, fl);
1370b964bf53SAl Viro 	} else {
13711da91ea8SAl Viro 		if (fd_file(out)->f_flags & O_NONBLOCK)
1372bdeb77bcSAndrei Vagin 			fl |= SPLICE_F_NONBLOCK;
1373bdeb77bcSAndrei Vagin 
13741da91ea8SAl Viro 		retval = splice_file_to_pipe(fd_file(in), opipe, &pos, count, fl);
1375b964bf53SAl Viro 	}
13761da177e4SLinus Torvalds 
13771da177e4SLinus Torvalds 	if (retval > 0) {
13784b98d11bSAlexey Dobriyan 		add_rchar(current, retval);
13794b98d11bSAlexey Dobriyan 		add_wchar(current, retval);
13801da91ea8SAl Viro 		fsnotify_access(fd_file(in));
13811da91ea8SAl Viro 		fsnotify_modify(fd_file(out));
13821da91ea8SAl Viro 		fd_file(out)->f_pos = out_pos;
13837995bd28SAl Viro 		if (ppos)
13847995bd28SAl Viro 			*ppos = pos;
13857995bd28SAl Viro 		else
13861da91ea8SAl Viro 			fd_file(in)->f_pos = pos;
13871da177e4SLinus Torvalds 	}
13881da177e4SLinus Torvalds 
13894b98d11bSAlexey Dobriyan 	inc_syscr(current);
13904b98d11bSAlexey Dobriyan 	inc_syscw(current);
13917995bd28SAl Viro 	if (pos > max)
13921da177e4SLinus Torvalds 		retval = -EOVERFLOW;
13931da177e4SLinus Torvalds 	return retval;
13941da177e4SLinus Torvalds }
13951da177e4SLinus Torvalds 
SYSCALL_DEFINE4(sendfile,int,out_fd,int,in_fd,off_t __user *,offset,size_t,count)1396002c8976SHeiko Carstens SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd, off_t __user *, offset, size_t, count)
13971da177e4SLinus Torvalds {
13981da177e4SLinus Torvalds 	loff_t pos;
13991da177e4SLinus Torvalds 	off_t off;
14001da177e4SLinus Torvalds 	ssize_t ret;
14011da177e4SLinus Torvalds 
14021da177e4SLinus Torvalds 	if (offset) {
14031da177e4SLinus Torvalds 		if (unlikely(get_user(off, offset)))
14041da177e4SLinus Torvalds 			return -EFAULT;
14051da177e4SLinus Torvalds 		pos = off;
14061da177e4SLinus Torvalds 		ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
14071da177e4SLinus Torvalds 		if (unlikely(put_user(pos, offset)))
14081da177e4SLinus Torvalds 			return -EFAULT;
14091da177e4SLinus Torvalds 		return ret;
14101da177e4SLinus Torvalds 	}
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
14131da177e4SLinus Torvalds }
14141da177e4SLinus Torvalds 
SYSCALL_DEFINE4(sendfile64,int,out_fd,int,in_fd,loff_t __user *,offset,size_t,count)1415002c8976SHeiko Carstens SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, size_t, count)
14161da177e4SLinus Torvalds {
14171da177e4SLinus Torvalds 	loff_t pos;
14181da177e4SLinus Torvalds 	ssize_t ret;
14191da177e4SLinus Torvalds 
14201da177e4SLinus Torvalds 	if (offset) {
14211da177e4SLinus Torvalds 		if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
14221da177e4SLinus Torvalds 			return -EFAULT;
14231da177e4SLinus Torvalds 		ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
14241da177e4SLinus Torvalds 		if (unlikely(put_user(pos, offset)))
14251da177e4SLinus Torvalds 			return -EFAULT;
14261da177e4SLinus Torvalds 		return ret;
14271da177e4SLinus Torvalds 	}
14281da177e4SLinus Torvalds 
14291da177e4SLinus Torvalds 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
14301da177e4SLinus Torvalds }
143119f4fc3aSAl Viro 
143219f4fc3aSAl Viro #ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE4(sendfile,int,out_fd,int,in_fd,compat_off_t __user *,offset,compat_size_t,count)143319f4fc3aSAl Viro COMPAT_SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd,
143419f4fc3aSAl Viro 		compat_off_t __user *, offset, compat_size_t, count)
143519f4fc3aSAl Viro {
143619f4fc3aSAl Viro 	loff_t pos;
143719f4fc3aSAl Viro 	off_t off;
143819f4fc3aSAl Viro 	ssize_t ret;
143919f4fc3aSAl Viro 
144019f4fc3aSAl Viro 	if (offset) {
144119f4fc3aSAl Viro 		if (unlikely(get_user(off, offset)))
144219f4fc3aSAl Viro 			return -EFAULT;
144319f4fc3aSAl Viro 		pos = off;
144419f4fc3aSAl Viro 		ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
144519f4fc3aSAl Viro 		if (unlikely(put_user(pos, offset)))
144619f4fc3aSAl Viro 			return -EFAULT;
144719f4fc3aSAl Viro 		return ret;
144819f4fc3aSAl Viro 	}
144919f4fc3aSAl Viro 
145019f4fc3aSAl Viro 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
145119f4fc3aSAl Viro }
145219f4fc3aSAl Viro 
COMPAT_SYSCALL_DEFINE4(sendfile64,int,out_fd,int,in_fd,compat_loff_t __user *,offset,compat_size_t,count)145319f4fc3aSAl Viro COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd,
145419f4fc3aSAl Viro 		compat_loff_t __user *, offset, compat_size_t, count)
145519f4fc3aSAl Viro {
145619f4fc3aSAl Viro 	loff_t pos;
145719f4fc3aSAl Viro 	ssize_t ret;
145819f4fc3aSAl Viro 
145919f4fc3aSAl Viro 	if (offset) {
146019f4fc3aSAl Viro 		if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
146119f4fc3aSAl Viro 			return -EFAULT;
146219f4fc3aSAl Viro 		ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
146319f4fc3aSAl Viro 		if (unlikely(put_user(pos, offset)))
146419f4fc3aSAl Viro 			return -EFAULT;
146519f4fc3aSAl Viro 		return ret;
146619f4fc3aSAl Viro 	}
146719f4fc3aSAl Viro 
146819f4fc3aSAl Viro 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
146919f4fc3aSAl Viro }
147019f4fc3aSAl Viro #endif
147129732938SZach Brown 
147229732938SZach Brown /*
1473407e9c63SDarrick J. Wong  * Performs necessary checks before doing a file copy
1474407e9c63SDarrick J. Wong  *
1475407e9c63SDarrick J. Wong  * Can adjust amount of bytes to copy via @req_count argument.
1476407e9c63SDarrick J. Wong  * Returns appropriate error code that caller should return or
1477407e9c63SDarrick J. Wong  * zero in case the copy should be allowed.
1478407e9c63SDarrick J. Wong  */
generic_copy_file_checks(struct file * file_in,loff_t pos_in,struct file * file_out,loff_t pos_out,size_t * req_count,unsigned int flags)1479407e9c63SDarrick J. Wong static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
1480407e9c63SDarrick J. Wong 				    struct file *file_out, loff_t pos_out,
1481407e9c63SDarrick J. Wong 				    size_t *req_count, unsigned int flags)
1482407e9c63SDarrick J. Wong {
1483407e9c63SDarrick J. Wong 	struct inode *inode_in = file_inode(file_in);
1484407e9c63SDarrick J. Wong 	struct inode *inode_out = file_inode(file_out);
1485407e9c63SDarrick J. Wong 	uint64_t count = *req_count;
1486407e9c63SDarrick J. Wong 	loff_t size_in;
1487407e9c63SDarrick J. Wong 	int ret;
1488407e9c63SDarrick J. Wong 
1489407e9c63SDarrick J. Wong 	ret = generic_file_rw_checks(file_in, file_out);
1490407e9c63SDarrick J. Wong 	if (ret)
1491407e9c63SDarrick J. Wong 		return ret;
1492407e9c63SDarrick J. Wong 
1493868f9f2fSAmir Goldstein 	/*
1494868f9f2fSAmir Goldstein 	 * We allow some filesystems to handle cross sb copy, but passing
1495868f9f2fSAmir Goldstein 	 * a file of the wrong filesystem type to filesystem driver can result
1496868f9f2fSAmir Goldstein 	 * in an attempt to dereference the wrong type of ->private_data, so
1497868f9f2fSAmir Goldstein 	 * avoid doing that until we really have a good reason.
1498868f9f2fSAmir Goldstein 	 *
1499868f9f2fSAmir Goldstein 	 * nfs and cifs define several different file_system_type structures
1500868f9f2fSAmir Goldstein 	 * and several different sets of file_operations, but they all end up
1501868f9f2fSAmir Goldstein 	 * using the same ->copy_file_range() function pointer.
1502868f9f2fSAmir Goldstein 	 */
150310bc8e4aSAmir Goldstein 	if (flags & COPY_FILE_SPLICE) {
150410bc8e4aSAmir Goldstein 		/* cross sb splice is allowed */
150510bc8e4aSAmir Goldstein 	} else if (file_out->f_op->copy_file_range) {
1506868f9f2fSAmir Goldstein 		if (file_in->f_op->copy_file_range !=
1507868f9f2fSAmir Goldstein 		    file_out->f_op->copy_file_range)
1508868f9f2fSAmir Goldstein 			return -EXDEV;
1509868f9f2fSAmir Goldstein 	} else if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) {
1510868f9f2fSAmir Goldstein 		return -EXDEV;
1511868f9f2fSAmir Goldstein 	}
1512868f9f2fSAmir Goldstein 
1513407e9c63SDarrick J. Wong 	/* Don't touch certain kinds of inodes */
1514407e9c63SDarrick J. Wong 	if (IS_IMMUTABLE(inode_out))
1515407e9c63SDarrick J. Wong 		return -EPERM;
1516407e9c63SDarrick J. Wong 
1517407e9c63SDarrick J. Wong 	if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out))
1518407e9c63SDarrick J. Wong 		return -ETXTBSY;
1519407e9c63SDarrick J. Wong 
1520407e9c63SDarrick J. Wong 	/* Ensure offsets don't wrap. */
1521407e9c63SDarrick J. Wong 	if (pos_in + count < pos_in || pos_out + count < pos_out)
1522407e9c63SDarrick J. Wong 		return -EOVERFLOW;
1523407e9c63SDarrick J. Wong 
1524407e9c63SDarrick J. Wong 	/* Shorten the copy to EOF */
1525407e9c63SDarrick J. Wong 	size_in = i_size_read(inode_in);
1526407e9c63SDarrick J. Wong 	if (pos_in >= size_in)
1527407e9c63SDarrick J. Wong 		count = 0;
1528407e9c63SDarrick J. Wong 	else
1529407e9c63SDarrick J. Wong 		count = min(count, size_in - (uint64_t)pos_in);
1530407e9c63SDarrick J. Wong 
1531407e9c63SDarrick J. Wong 	ret = generic_write_check_limits(file_out, pos_out, &count);
1532407e9c63SDarrick J. Wong 	if (ret)
1533407e9c63SDarrick J. Wong 		return ret;
1534407e9c63SDarrick J. Wong 
1535407e9c63SDarrick J. Wong 	/* Don't allow overlapped copying within the same file. */
1536407e9c63SDarrick J. Wong 	if (inode_in == inode_out &&
1537407e9c63SDarrick J. Wong 	    pos_out + count > pos_in &&
1538407e9c63SDarrick J. Wong 	    pos_out < pos_in + count)
1539407e9c63SDarrick J. Wong 		return -EINVAL;
1540407e9c63SDarrick J. Wong 
1541407e9c63SDarrick J. Wong 	*req_count = count;
1542407e9c63SDarrick J. Wong 	return 0;
1543407e9c63SDarrick J. Wong }
1544407e9c63SDarrick J. Wong 
1545407e9c63SDarrick J. Wong /*
154629732938SZach Brown  * copy_file_range() differs from regular file read and write in that it
154729732938SZach Brown  * specifically allows return partial success.  When it does so is up to
154829732938SZach Brown  * the copy_file_range method.
154929732938SZach Brown  */
vfs_copy_file_range(struct file * file_in,loff_t pos_in,struct file * file_out,loff_t pos_out,size_t len,unsigned int flags)155029732938SZach Brown ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
155129732938SZach Brown 			    struct file *file_out, loff_t pos_out,
155229732938SZach Brown 			    size_t len, unsigned int flags)
155329732938SZach Brown {
155429732938SZach Brown 	ssize_t ret;
155510bc8e4aSAmir Goldstein 	bool splice = flags & COPY_FILE_SPLICE;
155673065126SAmir Goldstein 	bool samesb = file_inode(file_in)->i_sb == file_inode(file_out)->i_sb;
155729732938SZach Brown 
155810bc8e4aSAmir Goldstein 	if (flags & ~COPY_FILE_SPLICE)
155929732938SZach Brown 		return -EINVAL;
156029732938SZach Brown 
156196e6e8f4SAmir Goldstein 	ret = generic_copy_file_checks(file_in, pos_in, file_out, pos_out, &len,
156296e6e8f4SAmir Goldstein 				       flags);
1563a3171351SAmir Goldstein 	if (unlikely(ret))
1564a3171351SAmir Goldstein 		return ret;
156511cbfb10SAmir Goldstein 
156629732938SZach Brown 	ret = rw_verify_area(READ, file_in, &pos_in, len);
1567bc61384dSAl Viro 	if (unlikely(ret))
1568bc61384dSAl Viro 		return ret;
1569bc61384dSAl Viro 
157029732938SZach Brown 	ret = rw_verify_area(WRITE, file_out, &pos_out, len);
1571bc61384dSAl Viro 	if (unlikely(ret))
157229732938SZach Brown 		return ret;
157329732938SZach Brown 
157429732938SZach Brown 	if (len == 0)
157529732938SZach Brown 		return 0;
157629732938SZach Brown 
1577bfe219d3SAmir Goldstein 	file_start_write(file_out);
157829732938SZach Brown 
1579a76b5b04SChristoph Hellwig 	/*
1580868f9f2fSAmir Goldstein 	 * Cloning is supported by more file systems, so we implement copy on
1581868f9f2fSAmir Goldstein 	 * same sb using clone, but for filesystems where both clone and copy
1582868f9f2fSAmir Goldstein 	 * are supported (e.g. nfs,cifs), we only call the copy method.
1583a76b5b04SChristoph Hellwig 	 */
158410bc8e4aSAmir Goldstein 	if (!splice && file_out->f_op->copy_file_range) {
1585868f9f2fSAmir Goldstein 		ret = file_out->f_op->copy_file_range(file_in, pos_in,
1586868f9f2fSAmir Goldstein 						      file_out, pos_out,
1587868f9f2fSAmir Goldstein 						      len, flags);
158873065126SAmir Goldstein 	} else if (!splice && file_in->f_op->remap_file_range && samesb) {
1589868f9f2fSAmir Goldstein 		ret = file_in->f_op->remap_file_range(file_in, pos_in,
159042ec3d4cSDarrick J. Wong 				file_out, pos_out,
1591eca3654eSDarrick J. Wong 				min_t(loff_t, MAX_RW_COUNT, len),
1592eca3654eSDarrick J. Wong 				REMAP_FILE_CAN_SHORTEN);
159373065126SAmir Goldstein 		/* fallback to splice */
159473065126SAmir Goldstein 		if (ret <= 0)
159573065126SAmir Goldstein 			splice = true;
159673065126SAmir Goldstein 	} else if (samesb) {
159773065126SAmir Goldstein 		/* Fallback to splice for same sb copy for backward compat */
159873065126SAmir Goldstein 		splice = true;
1599a76b5b04SChristoph Hellwig 	}
1600a76b5b04SChristoph Hellwig 
160173065126SAmir Goldstein 	file_end_write(file_out);
160273065126SAmir Goldstein 
160373065126SAmir Goldstein 	if (!splice)
160473065126SAmir Goldstein 		goto done;
160573065126SAmir Goldstein 
1606868f9f2fSAmir Goldstein 	/*
1607868f9f2fSAmir Goldstein 	 * We can get here for same sb copy of filesystems that do not implement
1608868f9f2fSAmir Goldstein 	 * ->copy_file_range() in case filesystem does not support clone or in
1609868f9f2fSAmir Goldstein 	 * case filesystem supports clone but rejected the clone request (e.g.
1610868f9f2fSAmir Goldstein 	 * because it was not block aligned).
1611868f9f2fSAmir Goldstein 	 *
1612868f9f2fSAmir Goldstein 	 * In both cases, fall back to kernel copy so we are able to maintain a
1613868f9f2fSAmir Goldstein 	 * consistent story about which filesystems support copy_file_range()
1614868f9f2fSAmir Goldstein 	 * and which filesystems do not, that will allow userspace tools to
1615868f9f2fSAmir Goldstein 	 * make consistent desicions w.r.t using copy_file_range().
161610bc8e4aSAmir Goldstein 	 *
161773065126SAmir Goldstein 	 * We also get here if caller (e.g. nfsd) requested COPY_FILE_SPLICE
161873065126SAmir Goldstein 	 * for server-side-copy between any two sb.
161973065126SAmir Goldstein 	 *
162073065126SAmir Goldstein 	 * In any case, we call do_splice_direct() and not splice_file_range(),
162173065126SAmir Goldstein 	 * without file_start_write() held, to avoid possible deadlocks related
162273065126SAmir Goldstein 	 * to splicing from input file, while file_start_write() is held on
162373065126SAmir Goldstein 	 * the output file on a different sb.
1624868f9f2fSAmir Goldstein 	 */
162573065126SAmir Goldstein 	ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out,
162673065126SAmir Goldstein 			       min_t(size_t, len, MAX_RW_COUNT), 0);
1627a76b5b04SChristoph Hellwig done:
162829732938SZach Brown 	if (ret > 0) {
162929732938SZach Brown 		fsnotify_access(file_in);
163029732938SZach Brown 		add_rchar(current, ret);
163129732938SZach Brown 		fsnotify_modify(file_out);
163229732938SZach Brown 		add_wchar(current, ret);
163329732938SZach Brown 	}
1634a76b5b04SChristoph Hellwig 
163529732938SZach Brown 	inc_syscr(current);
163629732938SZach Brown 	inc_syscw(current);
163729732938SZach Brown 
163829732938SZach Brown 	return ret;
163929732938SZach Brown }
164029732938SZach Brown EXPORT_SYMBOL(vfs_copy_file_range);
164129732938SZach Brown 
SYSCALL_DEFINE6(copy_file_range,int,fd_in,loff_t __user *,off_in,int,fd_out,loff_t __user *,off_out,size_t,len,unsigned int,flags)164229732938SZach Brown SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in,
164329732938SZach Brown 		int, fd_out, loff_t __user *, off_out,
164429732938SZach Brown 		size_t, len, unsigned int, flags)
164529732938SZach Brown {
164629732938SZach Brown 	loff_t pos_in;
164729732938SZach Brown 	loff_t pos_out;
164829732938SZach Brown 	ssize_t ret = -EBADF;
164929732938SZach Brown 
16506348be02SAl Viro 	CLASS(fd, f_in)(fd_in);
16516348be02SAl Viro 	if (fd_empty(f_in))
16526348be02SAl Viro 		return -EBADF;
165329732938SZach Brown 
16546348be02SAl Viro 	CLASS(fd, f_out)(fd_out);
16556348be02SAl Viro 	if (fd_empty(f_out))
16566348be02SAl Viro 		return -EBADF;
165729732938SZach Brown 
165829732938SZach Brown 	if (off_in) {
165929732938SZach Brown 		if (copy_from_user(&pos_in, off_in, sizeof(loff_t)))
16606348be02SAl Viro 			return -EFAULT;
166129732938SZach Brown 	} else {
16621da91ea8SAl Viro 		pos_in = fd_file(f_in)->f_pos;
166329732938SZach Brown 	}
166429732938SZach Brown 
166529732938SZach Brown 	if (off_out) {
166629732938SZach Brown 		if (copy_from_user(&pos_out, off_out, sizeof(loff_t)))
16676348be02SAl Viro 			return -EFAULT;
166829732938SZach Brown 	} else {
16691da91ea8SAl Viro 		pos_out = fd_file(f_out)->f_pos;
167029732938SZach Brown 	}
167129732938SZach Brown 
167210bc8e4aSAmir Goldstein 	if (flags != 0)
16736348be02SAl Viro 		return -EINVAL;
167410bc8e4aSAmir Goldstein 
16751da91ea8SAl Viro 	ret = vfs_copy_file_range(fd_file(f_in), pos_in, fd_file(f_out), pos_out, len,
167629732938SZach Brown 				  flags);
167729732938SZach Brown 	if (ret > 0) {
167829732938SZach Brown 		pos_in += ret;
167929732938SZach Brown 		pos_out += ret;
168029732938SZach Brown 
168129732938SZach Brown 		if (off_in) {
168229732938SZach Brown 			if (copy_to_user(off_in, &pos_in, sizeof(loff_t)))
168329732938SZach Brown 				ret = -EFAULT;
168429732938SZach Brown 		} else {
16851da91ea8SAl Viro 			fd_file(f_in)->f_pos = pos_in;
168629732938SZach Brown 		}
168729732938SZach Brown 
168829732938SZach Brown 		if (off_out) {
168929732938SZach Brown 			if (copy_to_user(off_out, &pos_out, sizeof(loff_t)))
169029732938SZach Brown 				ret = -EFAULT;
169129732938SZach Brown 		} else {
16921da91ea8SAl Viro 			fd_file(f_out)->f_pos = pos_out;
169329732938SZach Brown 		}
169429732938SZach Brown 	}
169529732938SZach Brown 	return ret;
169629732938SZach Brown }
169704b38d60SChristoph Hellwig 
1698407e9c63SDarrick J. Wong /*
1699407e9c63SDarrick J. Wong  * Don't operate on ranges the page cache doesn't support, and don't exceed the
1700407e9c63SDarrick J. Wong  * LFS limits.  If pos is under the limit it becomes a short access.  If it
1701407e9c63SDarrick J. Wong  * exceeds the limit we return -EFBIG.
1702407e9c63SDarrick J. Wong  */
generic_write_check_limits(struct file * file,loff_t pos,loff_t * count)1703407e9c63SDarrick J. Wong int generic_write_check_limits(struct file *file, loff_t pos, loff_t *count)
170404b38d60SChristoph Hellwig {
1705407e9c63SDarrick J. Wong 	struct inode *inode = file->f_mapping->host;
1706407e9c63SDarrick J. Wong 	loff_t max_size = inode->i_sb->s_maxbytes;
1707407e9c63SDarrick J. Wong 	loff_t limit = rlimit(RLIMIT_FSIZE);
170804b38d60SChristoph Hellwig 
1709407e9c63SDarrick J. Wong 	if (limit != RLIM_INFINITY) {
1710407e9c63SDarrick J. Wong 		if (pos >= limit) {
1711407e9c63SDarrick J. Wong 			send_sig(SIGXFSZ, current, 0);
1712407e9c63SDarrick J. Wong 			return -EFBIG;
1713407e9c63SDarrick J. Wong 		}
1714407e9c63SDarrick J. Wong 		*count = min(*count, limit - pos);
1715407e9c63SDarrick J. Wong 	}
1716407e9c63SDarrick J. Wong 
1717407e9c63SDarrick J. Wong 	if (!(file->f_flags & O_LARGEFILE))
1718407e9c63SDarrick J. Wong 		max_size = MAX_NON_LFS;
1719407e9c63SDarrick J. Wong 
1720407e9c63SDarrick J. Wong 	if (unlikely(pos >= max_size))
1721407e9c63SDarrick J. Wong 		return -EFBIG;
1722407e9c63SDarrick J. Wong 
1723407e9c63SDarrick J. Wong 	*count = min(*count, max_size - pos);
1724407e9c63SDarrick J. Wong 
1725407e9c63SDarrick J. Wong 	return 0;
1726407e9c63SDarrick J. Wong }
17275b9932f6SDarrick J. Wong EXPORT_SYMBOL_GPL(generic_write_check_limits);
1728407e9c63SDarrick J. Wong 
1729f6f7a25aSOmar Sandoval /* Like generic_write_checks(), but takes size of write instead of iter. */
generic_write_checks_count(struct kiocb * iocb,loff_t * count)1730f6f7a25aSOmar Sandoval int generic_write_checks_count(struct kiocb *iocb, loff_t *count)
1731407e9c63SDarrick J. Wong {
1732407e9c63SDarrick J. Wong 	struct file *file = iocb->ki_filp;
1733407e9c63SDarrick J. Wong 	struct inode *inode = file->f_mapping->host;
1734407e9c63SDarrick J. Wong 
1735407e9c63SDarrick J. Wong 	if (IS_SWAPFILE(inode))
1736407e9c63SDarrick J. Wong 		return -ETXTBSY;
1737407e9c63SDarrick J. Wong 
1738f6f7a25aSOmar Sandoval 	if (!*count)
1739407e9c63SDarrick J. Wong 		return 0;
1740407e9c63SDarrick J. Wong 
1741407e9c63SDarrick J. Wong 	if (iocb->ki_flags & IOCB_APPEND)
1742407e9c63SDarrick J. Wong 		iocb->ki_pos = i_size_read(inode);
1743407e9c63SDarrick J. Wong 
174480175539SStefan Roesch 	if ((iocb->ki_flags & IOCB_NOWAIT) &&
174580175539SStefan Roesch 	    !((iocb->ki_flags & IOCB_DIRECT) ||
1746210a03c9SChristian Brauner 	      (file->f_op->fop_flags & FOP_BUFFER_WASYNC)))
174704b38d60SChristoph Hellwig 		return -EINVAL;
174804b38d60SChristoph Hellwig 
1749f6f7a25aSOmar Sandoval 	return generic_write_check_limits(iocb->ki_filp, iocb->ki_pos, count);
1750f6f7a25aSOmar Sandoval }
1751f6f7a25aSOmar Sandoval EXPORT_SYMBOL(generic_write_checks_count);
1752f6f7a25aSOmar Sandoval 
1753f6f7a25aSOmar Sandoval /*
1754f6f7a25aSOmar Sandoval  * Performs necessary checks before doing a write
1755f6f7a25aSOmar Sandoval  *
1756f6f7a25aSOmar Sandoval  * Can adjust writing position or amount of bytes to write.
1757f6f7a25aSOmar Sandoval  * Returns appropriate error code that caller should return or
1758f6f7a25aSOmar Sandoval  * zero in case that write should be allowed.
1759f6f7a25aSOmar Sandoval  */
generic_write_checks(struct kiocb * iocb,struct iov_iter * from)1760f6f7a25aSOmar Sandoval ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
1761f6f7a25aSOmar Sandoval {
1762f6f7a25aSOmar Sandoval 	loff_t count = iov_iter_count(from);
1763f6f7a25aSOmar Sandoval 	int ret;
1764f6f7a25aSOmar Sandoval 
1765f6f7a25aSOmar Sandoval 	ret = generic_write_checks_count(iocb, &count);
1766407e9c63SDarrick J. Wong 	if (ret)
1767407e9c63SDarrick J. Wong 		return ret;
176804b38d60SChristoph Hellwig 
1769407e9c63SDarrick J. Wong 	iov_iter_truncate(from, count);
1770407e9c63SDarrick J. Wong 	return iov_iter_count(from);
177104b38d60SChristoph Hellwig }
1772407e9c63SDarrick J. Wong EXPORT_SYMBOL(generic_write_checks);
1773876bec6fSDarrick J. Wong 
1774876bec6fSDarrick J. Wong /*
1775407e9c63SDarrick J. Wong  * Performs common checks before doing a file copy/clone
1776407e9c63SDarrick J. Wong  * from @file_in to @file_out.
1777edc58dd0SDarrick J. Wong  */
generic_file_rw_checks(struct file * file_in,struct file * file_out)1778407e9c63SDarrick J. Wong int generic_file_rw_checks(struct file *file_in, struct file *file_out)
17791da177e4SLinus Torvalds {
17801383a7edSDarrick J. Wong 	struct inode *inode_in = file_inode(file_in);
17811383a7edSDarrick J. Wong 	struct inode *inode_out = file_inode(file_out);
17821da177e4SLinus Torvalds 
1783407e9c63SDarrick J. Wong 	/* Don't copy dirs, pipes, sockets... */
17841da177e4SLinus Torvalds 	if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
17851da177e4SLinus Torvalds 		return -EISDIR;
17861da177e4SLinus Torvalds 	if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
17871da177e4SLinus Torvalds 		return -EINVAL;
17881da177e4SLinus Torvalds 
1789407e9c63SDarrick J. Wong 	if (!(file_in->f_mode & FMODE_READ) ||
1790407e9c63SDarrick J. Wong 	    !(file_out->f_mode & FMODE_WRITE) ||
1791407e9c63SDarrick J. Wong 	    (file_out->f_flags & O_APPEND))
1792407e9c63SDarrick J. Wong 		return -EBADF;
17931383a7edSDarrick J. Wong 
17942c5773f1SDarrick J. Wong 	return 0;
17951da177e4SLinus Torvalds }
1796c34fc6f2SPrasad Singamsetty 
generic_atomic_write_valid(struct kiocb * iocb,struct iov_iter * iter)1797c3be7ebbSJohn Garry int generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter)
1798c34fc6f2SPrasad Singamsetty {
1799c34fc6f2SPrasad Singamsetty 	size_t len = iov_iter_count(iter);
1800c34fc6f2SPrasad Singamsetty 
1801c34fc6f2SPrasad Singamsetty 	if (!iter_is_ubuf(iter))
1802c3be7ebbSJohn Garry 		return -EINVAL;
1803c34fc6f2SPrasad Singamsetty 
1804c34fc6f2SPrasad Singamsetty 	if (!is_power_of_2(len))
1805c3be7ebbSJohn Garry 		return -EINVAL;
1806c34fc6f2SPrasad Singamsetty 
18079a8dbdadSJohn Garry 	if (!IS_ALIGNED(iocb->ki_pos, len))
1808c3be7ebbSJohn Garry 		return -EINVAL;
1809c34fc6f2SPrasad Singamsetty 
1810c3be7ebbSJohn Garry 	if (!(iocb->ki_flags & IOCB_DIRECT))
1811c3be7ebbSJohn Garry 		return -EOPNOTSUPP;
1812c3be7ebbSJohn Garry 
1813c3be7ebbSJohn Garry 	return 0;
1814c34fc6f2SPrasad Singamsetty }
1815a570bad1SJohn Garry EXPORT_SYMBOL_GPL(generic_atomic_write_valid);
1816