1994 lines · 45.6 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * "splice": joining two ropes together by interweaving their strands. * * This is the "extended pipe" functionality, where a pipe is used as * an arbitrary in-memory buffer. Think of a pipe as a small kernel * buffer that you can use to transfer data from one end to the other. * * The traditional unix read/write is extended with a "splice()" operation * that transfers data buffers to or from a pipe buffer. * * Named by Larry McVoy, original implementation from Linus, extended by * Jens to support splicing to files, network, direct splicing, etc and * fixing lots of bugs. * * Copyright (C) 2005-2006 Jens Axboe <axboe@kernel.dk> * Copyright (C) 2005-2006 Linus Torvalds <torvalds@osdl.org> * Copyright (C) 2006 Ingo Molnar <mingo@elte.hu> * */#include <linux/bvec.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/pagemap.h>#include <linux/splice.h>#include <linux/memcontrol.h>#include <linux/mm_inline.h>#include <linux/swap.h>#include <linux/writeback.h>#include <linux/export.h>#include <linux/syscalls.h>#include <linux/uio.h>#include <linux/fsnotify.h>#include <linux/security.h>#include <linux/gfp.h>#include <linux/net.h>#include <linux/socket.h>#include <linux/sched/signal.h> #include "internal.h" /* * Splice doesn't support FMODE_NOWAIT. Since pipes may set this flag to * indicate they support non-blocking reads or writes, we must clear it * here if set to avoid blocking other users of this pipe if splice is * being done on it. */static noinline void pipe_clear_nowait(struct file *file){	fmode_t fmode = READ_ONCE(file->f_mode); 	do {		if (!(fmode & FMODE_NOWAIT))			break;	} while (!try_cmpxchg(&file->f_mode, &fmode, fmode & ~FMODE_NOWAIT));} /* * Attempt to steal a page from a pipe buffer. This should perhaps go into * a vm helper function, it's already simplified quite a bit by the * addition of remove_mapping(). If success is returned, the caller may * attempt to reuse this page for another destination. */static bool page_cache_pipe_buf_try_steal(struct pipe_inode_info *pipe,		struct pipe_buffer *buf){	struct folio *folio = page_folio(buf->page);	struct address_space *mapping; 	folio_lock(folio); 	mapping = folio_mapping(folio);	if (mapping) {		WARN_ON(!folio_test_uptodate(folio)); 		/*		 * At least for ext2 with nobh option, we need to wait on		 * writeback completing on this folio, since we'll remove it		 * from the pagecache.  Otherwise truncate wont wait on the		 * folio, allowing the disk blocks to be reused by someone else		 * before we actually wrote our data to them. fs corruption		 * ensues.		 */		folio_wait_writeback(folio); 		if (!filemap_release_folio(folio, GFP_KERNEL))			goto out_unlock; 		/*		 * If we succeeded in removing the mapping, set LRU flag		 * and return good.		 */		if (remove_mapping(mapping, folio)) {			buf->flags |= PIPE_BUF_FLAG_LRU;			return true;		}	} 	/*	 * Raced with truncate or failed to remove folio from current	 * address space, unlock and return failure.	 */out_unlock:	folio_unlock(folio);	return false;} static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,					struct pipe_buffer *buf){	put_page(buf->page);	buf->flags &= ~PIPE_BUF_FLAG_LRU;} /* * Check whether the contents of buf is OK to access. Since the content * is a page cache page, IO may be in flight. */static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe,				       struct pipe_buffer *buf){	struct folio *folio = page_folio(buf->page);	int err; 	if (!folio_test_uptodate(folio)) {		folio_lock(folio); 		/*		 * Folio got truncated/unhashed. This will cause a 0-byte		 * splice, if this is the first page.		 */		if (!folio->mapping) {			err = -ENODATA;			goto error;		} 		/*		 * Uh oh, read-error from disk.		 */		if (!folio_test_uptodate(folio)) {			err = -EIO;			goto error;		} 		/* Folio is ok after all, we are done */		folio_unlock(folio);	} 	return 0;error:	folio_unlock(folio);	return err;} const struct pipe_buf_operations page_cache_pipe_buf_ops = {	.confirm	= page_cache_pipe_buf_confirm,	.release	= page_cache_pipe_buf_release,	.try_steal	= page_cache_pipe_buf_try_steal,	.get		= generic_pipe_buf_get,}; static bool user_page_pipe_buf_try_steal(struct pipe_inode_info *pipe,		struct pipe_buffer *buf){	if (!(buf->flags & PIPE_BUF_FLAG_GIFT))		return false; 	buf->flags |= PIPE_BUF_FLAG_LRU;	return generic_pipe_buf_try_steal(pipe, buf);} static const struct pipe_buf_operations user_page_pipe_buf_ops = {	.release	= page_cache_pipe_buf_release,	.try_steal	= user_page_pipe_buf_try_steal,	.get		= generic_pipe_buf_get,}; static void wakeup_pipe_readers(struct pipe_inode_info *pipe){	smp_mb();	if (waitqueue_active(&pipe->rd_wait))		wake_up_interruptible(&pipe->rd_wait);	kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);} /** * splice_to_pipe - fill passed data into a pipe * @pipe:	pipe to fill * @spd:	data to fill * * Description: *    @spd contains a map of pages and len/offset tuples, along with *    the struct pipe_buf_operations associated with these pages. This *    function will link that data to the pipe. * */ssize_t splice_to_pipe(struct pipe_inode_info *pipe,		       struct splice_pipe_desc *spd){	unsigned int spd_pages = spd->nr_pages;	unsigned int tail = pipe->tail;	unsigned int head = pipe->head;	ssize_t ret = 0;	int page_nr = 0; 	if (!spd_pages)		return 0; 	if (unlikely(!pipe->readers)) {		send_sig(SIGPIPE, current, 0);		ret = -EPIPE;		goto out;	} 	while (!pipe_full(head, tail, pipe->max_usage)) {		struct pipe_buffer *buf = pipe_buf(pipe, head); 		buf->page = spd->pages[page_nr];		buf->offset = spd->partial[page_nr].offset;		buf->len = spd->partial[page_nr].len;		buf->private = spd->partial[page_nr].private;		buf->ops = spd->ops;		buf->flags = 0; 		head++;		pipe->head = head;		page_nr++;		ret += buf->len; 		if (!--spd->nr_pages)			break;	} 	if (!ret)		ret = -EAGAIN; out:	while (page_nr < spd_pages)		spd->spd_release(spd, page_nr++); 	return ret;}EXPORT_SYMBOL_GPL(splice_to_pipe); ssize_t add_to_pipe(struct pipe_inode_info *pipe, struct pipe_buffer *buf){	unsigned int head = pipe->head;	unsigned int tail = pipe->tail;	int ret; 	if (unlikely(!pipe->readers)) {		send_sig(SIGPIPE, current, 0);		ret = -EPIPE;	} else if (pipe_full(head, tail, pipe->max_usage)) {		ret = -EAGAIN;	} else {		*pipe_buf(pipe, head) = *buf;		pipe->head = head + 1;		return buf->len;	}	pipe_buf_release(pipe, buf);	return ret;}EXPORT_SYMBOL(add_to_pipe); /* * Check if we need to grow the arrays holding pages and partial page * descriptions. */int splice_grow_spd(const struct pipe_inode_info *pipe, struct splice_pipe_desc *spd){	unsigned int max_usage = READ_ONCE(pipe->max_usage); 	spd->nr_pages_max = max_usage;	if (max_usage <= PIPE_DEF_BUFFERS)		return 0; 	spd->pages = kmalloc_objs(struct page *, max_usage);	spd->partial = kmalloc_objs(struct partial_page, max_usage); 	if (spd->pages && spd->partial)		return 0; 	kfree(spd->pages);	kfree(spd->partial);	return -ENOMEM;} void splice_shrink_spd(struct splice_pipe_desc *spd){	if (spd->nr_pages_max <= PIPE_DEF_BUFFERS)		return; 	kfree(spd->pages);	kfree(spd->partial);} /** * copy_splice_read -  Copy data from a file and splice the copy into a pipe * @in: The file to read from * @ppos: Pointer to the file position to read from * @pipe: The pipe to splice into * @len: The amount to splice * @flags: The SPLICE_F_* flags * * This function allocates a bunch of pages sufficient to hold the requested * amount of data (but limited by the remaining pipe capacity), passes it to * the file's ->read_iter() to read into and then splices the used pages into * the pipe. * * Return: On success, the number of bytes read will be returned and *@ppos * will be updated if appropriate; 0 will be returned if there is no more data * to be read; -EAGAIN will be returned if the pipe had no space, and some * other negative error code will be returned on error.  A short read may occur * if the pipe has insufficient space, we reach the end of the data or we hit a * hole. */ssize_t copy_splice_read(struct file *in, loff_t *ppos,			 struct pipe_inode_info *pipe,			 size_t len, unsigned int flags){	struct iov_iter to;	struct bio_vec *bv;	struct kiocb kiocb;	struct page **pages;	ssize_t ret;	size_t used, npages, chunk, remain, keep = 0;	int i; 	/* Work out how much data we can actually add into the pipe */	used = pipe_buf_usage(pipe);	npages = max_t(ssize_t, pipe->max_usage - used, 0);	len = min_t(size_t, len, npages * PAGE_SIZE);	npages = DIV_ROUND_UP(len, PAGE_SIZE); 	bv = kzalloc(array_size(npages, sizeof(bv[0])) +		     array_size(npages, sizeof(struct page *)), GFP_KERNEL);	if (!bv)		return -ENOMEM; 	pages = (struct page **)(bv + npages);	npages = alloc_pages_bulk(GFP_USER, npages, pages);	if (!npages) {		kfree(bv);		return -ENOMEM;	} 	remain = len = min_t(size_t, len, npages * PAGE_SIZE); 	for (i = 0; i < npages; i++) {		chunk = min_t(size_t, PAGE_SIZE, remain);		bv[i].bv_page = pages[i];		bv[i].bv_offset = 0;		bv[i].bv_len = chunk;		remain -= chunk;	} 	/* Do the I/O */	iov_iter_bvec(&to, ITER_DEST, bv, npages, len);	init_sync_kiocb(&kiocb, in);	kiocb.ki_pos = *ppos;	ret = in->f_op->read_iter(&kiocb, &to); 	if (ret > 0) {		keep = DIV_ROUND_UP(ret, PAGE_SIZE);		*ppos = kiocb.ki_pos;	} 	/*	 * Callers of ->splice_read() expect -EAGAIN on "can't put anything in	 * there", rather than -EFAULT.	 */	if (ret == -EFAULT)		ret = -EAGAIN; 	/* Free any pages that didn't get touched at all. */	if (keep < npages)		release_pages(pages + keep, npages - keep); 	/* Push the remaining pages into the pipe. */	remain = ret;	for (i = 0; i < keep; i++) {		struct pipe_buffer *buf = pipe_head_buf(pipe); 		chunk = min_t(size_t, remain, PAGE_SIZE);		*buf = (struct pipe_buffer) {			.ops	= &default_pipe_buf_ops,			.page	= bv[i].bv_page,			.offset	= 0,			.len	= chunk,		};		pipe->head++;		remain -= chunk;	} 	kfree(bv);	return ret;}EXPORT_SYMBOL(copy_splice_read); const struct pipe_buf_operations default_pipe_buf_ops = {	.release	= generic_pipe_buf_release,	.try_steal	= generic_pipe_buf_try_steal,	.get		= generic_pipe_buf_get,}; /* Pipe buffer operations for a socket and similar. */const struct pipe_buf_operations nosteal_pipe_buf_ops = {	.release	= generic_pipe_buf_release,	.get		= generic_pipe_buf_get,};EXPORT_SYMBOL(nosteal_pipe_buf_ops); static void wakeup_pipe_writers(struct pipe_inode_info *pipe){	smp_mb();	if (waitqueue_active(&pipe->wr_wait))		wake_up_interruptible(&pipe->wr_wait);	kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);} /** * splice_from_pipe_feed - feed available data from a pipe to a file * @pipe:	pipe to splice from * @sd:		information to @actor * @actor:	handler that splices the data * * Description: *    This function loops over the pipe and calls @actor to do the *    actual moving of a single struct pipe_buffer to the desired *    destination.  It returns when there's no more buffers left in *    the pipe or if the requested number of bytes (@sd->total_len) *    have been copied.  It returns a positive number (one) if the *    pipe needs to be filled with more data, zero if the required *    number of bytes have been copied and -errno on error. * *    This, together with splice_from_pipe_{begin,end,next}, may be *    used to implement the functionality of __splice_from_pipe() when *    locking is required around copying the pipe buffers to the *    destination. */static int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_desc *sd,			  splice_actor *actor){	unsigned int head = pipe->head;	unsigned int tail = pipe->tail;	int ret; 	while (!pipe_empty(head, tail)) {		struct pipe_buffer *buf = pipe_buf(pipe, tail); 		sd->len = buf->len;		if (sd->len > sd->total_len)			sd->len = sd->total_len; 		ret = pipe_buf_confirm(pipe, buf);		if (unlikely(ret)) {			if (ret == -ENODATA)				ret = 0;			return ret;		} 		ret = actor(pipe, buf, sd);		if (ret <= 0)			return ret; 		buf->offset += ret;		buf->len -= ret; 		sd->num_spliced += ret;		sd->len -= ret;		sd->pos += ret;		sd->total_len -= ret; 		if (!buf->len) {			pipe_buf_release(pipe, buf);			tail++;			pipe->tail = tail;			if (pipe->files)				sd->need_wakeup = true;		} 		if (!sd->total_len)			return 0;	} 	return 1;} /* We know we have a pipe buffer, but maybe it's empty? */static inline bool eat_empty_buffer(struct pipe_inode_info *pipe){	unsigned int tail = pipe->tail;	struct pipe_buffer *buf = pipe_buf(pipe, tail); 	if (unlikely(!buf->len)) {		pipe_buf_release(pipe, buf);		pipe->tail = tail+1;		return true;	}

Lines 1–500 of 1994.