xref: /openbmc/linux/fs/splice.c (revision 5abc97aa)
15274f052SJens Axboe /*
25274f052SJens Axboe  * "splice": joining two ropes together by interweaving their strands.
35274f052SJens Axboe  *
45274f052SJens Axboe  * This is the "extended pipe" functionality, where a pipe is used as
55274f052SJens Axboe  * an arbitrary in-memory buffer. Think of a pipe as a small kernel
65274f052SJens Axboe  * buffer that you can use to transfer data from one end to the other.
75274f052SJens Axboe  *
85274f052SJens Axboe  * The traditional unix read/write is extended with a "splice()" operation
95274f052SJens Axboe  * that transfers data buffers to or from a pipe buffer.
105274f052SJens Axboe  *
115274f052SJens Axboe  * Named by Larry McVoy, original implementation from Linus, extended by
125274f052SJens Axboe  * Jens to support splicing to files and fixing the initial implementation
135274f052SJens Axboe  * bugs.
145274f052SJens Axboe  *
155274f052SJens Axboe  * Copyright (C) 2005 Jens Axboe <axboe@suse.de>
165274f052SJens Axboe  * Copyright (C) 2005 Linus Torvalds <torvalds@osdl.org>
175274f052SJens Axboe  *
185274f052SJens Axboe  */
195274f052SJens Axboe #include <linux/fs.h>
205274f052SJens Axboe #include <linux/file.h>
215274f052SJens Axboe #include <linux/pagemap.h>
225274f052SJens Axboe #include <linux/pipe_fs_i.h>
235274f052SJens Axboe #include <linux/mm_inline.h>
245abc97aaSJens Axboe #include <linux/swap.h>
255274f052SJens Axboe 
265274f052SJens Axboe /*
275274f052SJens Axboe  * Passed to the actors
285274f052SJens Axboe  */
295274f052SJens Axboe struct splice_desc {
305274f052SJens Axboe 	unsigned int len, total_len;	/* current and remaining length */
315274f052SJens Axboe 	unsigned int flags;		/* splice flags */
325274f052SJens Axboe 	struct file *file;		/* file to read/write */
335274f052SJens Axboe 	loff_t pos;			/* file position */
345274f052SJens Axboe };
355274f052SJens Axboe 
365abc97aaSJens Axboe static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
375abc97aaSJens Axboe 				     struct pipe_buffer *buf)
385abc97aaSJens Axboe {
395abc97aaSJens Axboe 	struct page *page = buf->page;
405abc97aaSJens Axboe 
415abc97aaSJens Axboe 	WARN_ON(!PageLocked(page));
425abc97aaSJens Axboe 	WARN_ON(!PageUptodate(page));
435abc97aaSJens Axboe 
445abc97aaSJens Axboe 	if (!remove_mapping(page_mapping(page), page))
455abc97aaSJens Axboe 		return 1;
465abc97aaSJens Axboe 
475abc97aaSJens Axboe 	if (PageLRU(page)) {
485abc97aaSJens Axboe 		struct zone *zone = page_zone(page);
495abc97aaSJens Axboe 
505abc97aaSJens Axboe 		spin_lock_irq(&zone->lru_lock);
515abc97aaSJens Axboe 		BUG_ON(!PageLRU(page));
525abc97aaSJens Axboe 		__ClearPageLRU(page);
535abc97aaSJens Axboe 		del_page_from_lru(zone, page);
545abc97aaSJens Axboe 		spin_unlock_irq(&zone->lru_lock);
555abc97aaSJens Axboe 	}
565abc97aaSJens Axboe 
575abc97aaSJens Axboe 	buf->stolen = 1;
585abc97aaSJens Axboe 	return 0;
595abc97aaSJens Axboe }
605abc97aaSJens Axboe 
615274f052SJens Axboe static void page_cache_pipe_buf_release(struct pipe_inode_info *info,
625274f052SJens Axboe 					struct pipe_buffer *buf)
635274f052SJens Axboe {
645274f052SJens Axboe 	page_cache_release(buf->page);
655274f052SJens Axboe 	buf->page = NULL;
665abc97aaSJens Axboe 	buf->stolen = 0;
675274f052SJens Axboe }
685274f052SJens Axboe 
695274f052SJens Axboe static void *page_cache_pipe_buf_map(struct file *file,
705274f052SJens Axboe 				     struct pipe_inode_info *info,
715274f052SJens Axboe 				     struct pipe_buffer *buf)
725274f052SJens Axboe {
735274f052SJens Axboe 	struct page *page = buf->page;
745274f052SJens Axboe 
755274f052SJens Axboe 	lock_page(page);
765274f052SJens Axboe 
775274f052SJens Axboe 	if (!PageUptodate(page)) {
785274f052SJens Axboe 		unlock_page(page);
795274f052SJens Axboe 		return ERR_PTR(-EIO);
805274f052SJens Axboe 	}
815274f052SJens Axboe 
825274f052SJens Axboe 	if (!page->mapping) {
835274f052SJens Axboe 		unlock_page(page);
845274f052SJens Axboe 		return ERR_PTR(-ENODATA);
855274f052SJens Axboe 	}
865274f052SJens Axboe 
875274f052SJens Axboe 	return kmap(buf->page);
885274f052SJens Axboe }
895274f052SJens Axboe 
905274f052SJens Axboe static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info,
915274f052SJens Axboe 				      struct pipe_buffer *buf)
925274f052SJens Axboe {
935abc97aaSJens Axboe 	if (!buf->stolen)
945274f052SJens Axboe 		unlock_page(buf->page);
955274f052SJens Axboe 	kunmap(buf->page);
965274f052SJens Axboe }
975274f052SJens Axboe 
985274f052SJens Axboe static struct pipe_buf_operations page_cache_pipe_buf_ops = {
995274f052SJens Axboe 	.can_merge = 0,
1005274f052SJens Axboe 	.map = page_cache_pipe_buf_map,
1015274f052SJens Axboe 	.unmap = page_cache_pipe_buf_unmap,
1025274f052SJens Axboe 	.release = page_cache_pipe_buf_release,
1035abc97aaSJens Axboe 	.steal = page_cache_pipe_buf_steal,
1045274f052SJens Axboe };
1055274f052SJens Axboe 
1065274f052SJens Axboe static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
1075274f052SJens Axboe 			    int nr_pages, unsigned long offset,
1085274f052SJens Axboe 			    unsigned long len)
1095274f052SJens Axboe {
1105274f052SJens Axboe 	struct pipe_inode_info *info;
1115274f052SJens Axboe 	int ret, do_wakeup, i;
1125274f052SJens Axboe 
1135274f052SJens Axboe 	ret = 0;
1145274f052SJens Axboe 	do_wakeup = 0;
1155274f052SJens Axboe 	i = 0;
1165274f052SJens Axboe 
1175274f052SJens Axboe 	mutex_lock(PIPE_MUTEX(*inode));
1185274f052SJens Axboe 
1195274f052SJens Axboe 	info = inode->i_pipe;
1205274f052SJens Axboe 	for (;;) {
1215274f052SJens Axboe 		int bufs;
1225274f052SJens Axboe 
1235274f052SJens Axboe 		if (!PIPE_READERS(*inode)) {
1245274f052SJens Axboe 			send_sig(SIGPIPE, current, 0);
1255274f052SJens Axboe 			if (!ret)
1265274f052SJens Axboe 				ret = -EPIPE;
1275274f052SJens Axboe 			break;
1285274f052SJens Axboe 		}
1295274f052SJens Axboe 
1305274f052SJens Axboe 		bufs = info->nrbufs;
1315274f052SJens Axboe 		if (bufs < PIPE_BUFFERS) {
1325274f052SJens Axboe 			int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1);
1335274f052SJens Axboe 			struct pipe_buffer *buf = info->bufs + newbuf;
1345274f052SJens Axboe 			struct page *page = pages[i++];
1355274f052SJens Axboe 			unsigned long this_len;
1365274f052SJens Axboe 
1375274f052SJens Axboe 			this_len = PAGE_CACHE_SIZE - offset;
1385274f052SJens Axboe 			if (this_len > len)
1395274f052SJens Axboe 				this_len = len;
1405274f052SJens Axboe 
1415274f052SJens Axboe 			buf->page = page;
1425274f052SJens Axboe 			buf->offset = offset;
1435274f052SJens Axboe 			buf->len = this_len;
1445274f052SJens Axboe 			buf->ops = &page_cache_pipe_buf_ops;
1455274f052SJens Axboe 			info->nrbufs = ++bufs;
1465274f052SJens Axboe 			do_wakeup = 1;
1475274f052SJens Axboe 
1485274f052SJens Axboe 			ret += this_len;
1495274f052SJens Axboe 			len -= this_len;
1505274f052SJens Axboe 			offset = 0;
1515274f052SJens Axboe 			if (!--nr_pages)
1525274f052SJens Axboe 				break;
1535274f052SJens Axboe 			if (!len)
1545274f052SJens Axboe 				break;
1555274f052SJens Axboe 			if (bufs < PIPE_BUFFERS)
1565274f052SJens Axboe 				continue;
1575274f052SJens Axboe 
1585274f052SJens Axboe 			break;
1595274f052SJens Axboe 		}
1605274f052SJens Axboe 
1615274f052SJens Axboe 		if (signal_pending(current)) {
1625274f052SJens Axboe 			if (!ret)
1635274f052SJens Axboe 				ret = -ERESTARTSYS;
1645274f052SJens Axboe 			break;
1655274f052SJens Axboe 		}
1665274f052SJens Axboe 
1675274f052SJens Axboe 		if (do_wakeup) {
1685274f052SJens Axboe 			wake_up_interruptible_sync(PIPE_WAIT(*inode));
1695274f052SJens Axboe 			kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO,
1705274f052SJens Axboe 				    POLL_IN);
1715274f052SJens Axboe 			do_wakeup = 0;
1725274f052SJens Axboe 		}
1735274f052SJens Axboe 
1745274f052SJens Axboe 		PIPE_WAITING_WRITERS(*inode)++;
1755274f052SJens Axboe 		pipe_wait(inode);
1765274f052SJens Axboe 		PIPE_WAITING_WRITERS(*inode)--;
1775274f052SJens Axboe 	}
1785274f052SJens Axboe 
1795274f052SJens Axboe 	mutex_unlock(PIPE_MUTEX(*inode));
1805274f052SJens Axboe 
1815274f052SJens Axboe 	if (do_wakeup) {
1825274f052SJens Axboe 		wake_up_interruptible(PIPE_WAIT(*inode));
1835274f052SJens Axboe 		kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
1845274f052SJens Axboe 	}
1855274f052SJens Axboe 
1865274f052SJens Axboe 	while (i < nr_pages)
1875274f052SJens Axboe 		page_cache_release(pages[i++]);
1885274f052SJens Axboe 
1895274f052SJens Axboe 	return ret;
1905274f052SJens Axboe }
1915274f052SJens Axboe 
1925274f052SJens Axboe static int __generic_file_splice_read(struct file *in, struct inode *pipe,
1935274f052SJens Axboe 				      size_t len)
1945274f052SJens Axboe {
1955274f052SJens Axboe 	struct address_space *mapping = in->f_mapping;
1965274f052SJens Axboe 	unsigned int offset, nr_pages;
1975274f052SJens Axboe 	struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS];
1985274f052SJens Axboe 	struct page *page;
1995274f052SJens Axboe 	pgoff_t index, pidx;
2005274f052SJens Axboe 	int i, j;
2015274f052SJens Axboe 
2025274f052SJens Axboe 	index = in->f_pos >> PAGE_CACHE_SHIFT;
2035274f052SJens Axboe 	offset = in->f_pos & ~PAGE_CACHE_MASK;
2045274f052SJens Axboe 	nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
2055274f052SJens Axboe 
2065274f052SJens Axboe 	if (nr_pages > PIPE_BUFFERS)
2075274f052SJens Axboe 		nr_pages = PIPE_BUFFERS;
2085274f052SJens Axboe 
2095274f052SJens Axboe 	/*
2105274f052SJens Axboe 	 * initiate read-ahead on this page range
2115274f052SJens Axboe 	 */
2125274f052SJens Axboe 	do_page_cache_readahead(mapping, in, index, nr_pages);
2135274f052SJens Axboe 
2145274f052SJens Axboe 	/*
2155274f052SJens Axboe 	 * Get as many pages from the page cache as possible..
2165274f052SJens Axboe 	 * Start IO on the page cache entries we create (we
2175274f052SJens Axboe 	 * can assume that any pre-existing ones we find have
2185274f052SJens Axboe 	 * already had IO started on them).
2195274f052SJens Axboe 	 */
2205274f052SJens Axboe 	i = find_get_pages(mapping, index, nr_pages, pages);
2215274f052SJens Axboe 
2225274f052SJens Axboe 	/*
2235274f052SJens Axboe 	 * common case - we found all pages and they are contiguous,
2245274f052SJens Axboe 	 * kick them off
2255274f052SJens Axboe 	 */
2265274f052SJens Axboe 	if (i && (pages[i - 1]->index == index + i - 1))
2275274f052SJens Axboe 		goto splice_them;
2285274f052SJens Axboe 
2295274f052SJens Axboe 	/*
2305274f052SJens Axboe 	 * fill shadow[] with pages at the right locations, so we only
2315274f052SJens Axboe 	 * have to fill holes
2325274f052SJens Axboe 	 */
2335274f052SJens Axboe 	memset(shadow, 0, i * sizeof(struct page *));
2345274f052SJens Axboe 	for (j = 0, pidx = index; j < i; pidx++, j++)
2355274f052SJens Axboe 		shadow[pages[j]->index - pidx] = pages[j];
2365274f052SJens Axboe 
2375274f052SJens Axboe 	/*
2385274f052SJens Axboe 	 * now fill in the holes
2395274f052SJens Axboe 	 */
2405274f052SJens Axboe 	for (i = 0, pidx = index; i < nr_pages; pidx++, i++) {
2415274f052SJens Axboe 		int error;
2425274f052SJens Axboe 
2435274f052SJens Axboe 		if (shadow[i])
2445274f052SJens Axboe 			continue;
2455274f052SJens Axboe 
2465274f052SJens Axboe 		/*
2475274f052SJens Axboe 		 * no page there, look one up / create it
2485274f052SJens Axboe 		 */
2495274f052SJens Axboe 		page = find_or_create_page(mapping, pidx,
2505274f052SJens Axboe 						   mapping_gfp_mask(mapping));
2515274f052SJens Axboe 		if (!page)
2525274f052SJens Axboe 			break;
2535274f052SJens Axboe 
2545274f052SJens Axboe 		if (PageUptodate(page))
2555274f052SJens Axboe 			unlock_page(page);
2565274f052SJens Axboe 		else {
2575274f052SJens Axboe 			error = mapping->a_ops->readpage(in, page);
2585274f052SJens Axboe 
2595274f052SJens Axboe 			if (unlikely(error)) {
2605274f052SJens Axboe 				page_cache_release(page);
2615274f052SJens Axboe 				break;
2625274f052SJens Axboe 			}
2635274f052SJens Axboe 		}
2645274f052SJens Axboe 		shadow[i] = page;
2655274f052SJens Axboe 	}
2665274f052SJens Axboe 
2675274f052SJens Axboe 	if (!i) {
2685274f052SJens Axboe 		for (i = 0; i < nr_pages; i++) {
2695274f052SJens Axboe 			 if (shadow[i])
2705274f052SJens Axboe 				page_cache_release(shadow[i]);
2715274f052SJens Axboe 		}
2725274f052SJens Axboe 		return 0;
2735274f052SJens Axboe 	}
2745274f052SJens Axboe 
2755274f052SJens Axboe 	memcpy(pages, shadow, i * sizeof(struct page *));
2765274f052SJens Axboe 
2775274f052SJens Axboe 	/*
2785274f052SJens Axboe 	 * Now we splice them into the pipe..
2795274f052SJens Axboe 	 */
2805274f052SJens Axboe splice_them:
2815274f052SJens Axboe 	return move_to_pipe(pipe, pages, i, offset, len);
2825274f052SJens Axboe }
2835274f052SJens Axboe 
2845274f052SJens Axboe ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
2855274f052SJens Axboe 				 size_t len, unsigned int flags)
2865274f052SJens Axboe {
2875274f052SJens Axboe 	ssize_t spliced;
2885274f052SJens Axboe 	int ret;
2895274f052SJens Axboe 
2905274f052SJens Axboe 	ret = 0;
2915274f052SJens Axboe 	spliced = 0;
2925274f052SJens Axboe 	while (len) {
2935274f052SJens Axboe 		ret = __generic_file_splice_read(in, pipe, len);
2945274f052SJens Axboe 
2955274f052SJens Axboe 		if (ret <= 0)
2965274f052SJens Axboe 			break;
2975274f052SJens Axboe 
2985274f052SJens Axboe 		in->f_pos += ret;
2995274f052SJens Axboe 		len -= ret;
3005274f052SJens Axboe 		spliced += ret;
3015274f052SJens Axboe 	}
3025274f052SJens Axboe 
3035274f052SJens Axboe 	if (spliced)
3045274f052SJens Axboe 		return spliced;
3055274f052SJens Axboe 
3065274f052SJens Axboe 	return ret;
3075274f052SJens Axboe }
3085274f052SJens Axboe 
3095274f052SJens Axboe /*
3105274f052SJens Axboe  * Send 'len' bytes to socket from 'file' at position 'pos' using sendpage().
3115274f052SJens Axboe  */
3125274f052SJens Axboe static int pipe_to_sendpage(struct pipe_inode_info *info,
3135274f052SJens Axboe 			    struct pipe_buffer *buf, struct splice_desc *sd)
3145274f052SJens Axboe {
3155274f052SJens Axboe 	struct file *file = sd->file;
3165274f052SJens Axboe 	loff_t pos = sd->pos;
3175274f052SJens Axboe 	unsigned int offset;
3185274f052SJens Axboe 	ssize_t ret;
3195274f052SJens Axboe 	void *ptr;
3205274f052SJens Axboe 
3215274f052SJens Axboe 	/*
3225274f052SJens Axboe 	 * sub-optimal, but we are limited by the pipe ->map. we don't
3235274f052SJens Axboe 	 * need a kmap'ed buffer here, we just want to make sure we
3245274f052SJens Axboe 	 * have the page pinned if the pipe page originates from the
3255274f052SJens Axboe 	 * page cache
3265274f052SJens Axboe 	 */
3275274f052SJens Axboe 	ptr = buf->ops->map(file, info, buf);
3285274f052SJens Axboe 	if (IS_ERR(ptr))
3295274f052SJens Axboe 		return PTR_ERR(ptr);
3305274f052SJens Axboe 
3315274f052SJens Axboe 	offset = pos & ~PAGE_CACHE_MASK;
3325274f052SJens Axboe 
3335274f052SJens Axboe 	ret = file->f_op->sendpage(file, buf->page, offset, sd->len, &pos,
3345274f052SJens Axboe 					sd->len < sd->total_len);
3355274f052SJens Axboe 
3365274f052SJens Axboe 	buf->ops->unmap(info, buf);
3375274f052SJens Axboe 	if (ret == sd->len)
3385274f052SJens Axboe 		return 0;
3395274f052SJens Axboe 
3405274f052SJens Axboe 	return -EIO;
3415274f052SJens Axboe }
3425274f052SJens Axboe 
3435274f052SJens Axboe /*
3445274f052SJens Axboe  * This is a little more tricky than the file -> pipe splicing. There are
3455274f052SJens Axboe  * basically three cases:
3465274f052SJens Axboe  *
3475274f052SJens Axboe  *	- Destination page already exists in the address space and there
3485274f052SJens Axboe  *	  are users of it. For that case we have no other option that
3495274f052SJens Axboe  *	  copying the data. Tough luck.
3505274f052SJens Axboe  *	- Destination page already exists in the address space, but there
3515274f052SJens Axboe  *	  are no users of it. Make sure it's uptodate, then drop it. Fall
3525274f052SJens Axboe  *	  through to last case.
3535274f052SJens Axboe  *	- Destination page does not exist, we can add the pipe page to
3545274f052SJens Axboe  *	  the page cache and avoid the copy.
3555274f052SJens Axboe  *
3565274f052SJens Axboe  * For now we just do the slower thing and always copy pages over, it's
3575274f052SJens Axboe  * easier than migrating pages from the pipe to the target file. For the
3585274f052SJens Axboe  * case of doing file | file splicing, the migrate approach had some LRU
3595274f052SJens Axboe  * nastiness...
3605274f052SJens Axboe  */
3615274f052SJens Axboe static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
3625274f052SJens Axboe 			struct splice_desc *sd)
3635274f052SJens Axboe {
3645274f052SJens Axboe 	struct file *file = sd->file;
3655274f052SJens Axboe 	struct address_space *mapping = file->f_mapping;
3665274f052SJens Axboe 	unsigned int offset;
3675274f052SJens Axboe 	struct page *page;
3685274f052SJens Axboe 	pgoff_t index;
3695abc97aaSJens Axboe 	char *src;
3705274f052SJens Axboe 	int ret;
3715274f052SJens Axboe 
3725274f052SJens Axboe 	/*
3735274f052SJens Axboe 	 * after this, page will be locked and unmapped
3745274f052SJens Axboe 	 */
3755274f052SJens Axboe 	src = buf->ops->map(file, info, buf);
3765274f052SJens Axboe 	if (IS_ERR(src))
3775274f052SJens Axboe 		return PTR_ERR(src);
3785274f052SJens Axboe 
3795274f052SJens Axboe 	index = sd->pos >> PAGE_CACHE_SHIFT;
3805274f052SJens Axboe 	offset = sd->pos & ~PAGE_CACHE_MASK;
3815274f052SJens Axboe 
3825abc97aaSJens Axboe 	/*
3835abc97aaSJens Axboe 	 * reuse buf page, if SPLICE_F_MOVE is set
3845abc97aaSJens Axboe 	 */
3855abc97aaSJens Axboe 	if (sd->flags & SPLICE_F_MOVE) {
3865abc97aaSJens Axboe 		if (buf->ops->steal(info, buf))
3875abc97aaSJens Axboe 			goto find_page;
3885abc97aaSJens Axboe 
3895abc97aaSJens Axboe 		page = buf->page;
3905abc97aaSJens Axboe 		if (add_to_page_cache_lru(page, mapping, index,
3915abc97aaSJens Axboe 						mapping_gfp_mask(mapping)))
3925abc97aaSJens Axboe 			goto find_page;
3935abc97aaSJens Axboe 	} else {
3945274f052SJens Axboe find_page:
3955274f052SJens Axboe 		ret = -ENOMEM;
3965abc97aaSJens Axboe 		page = find_or_create_page(mapping, index,
3975abc97aaSJens Axboe 						mapping_gfp_mask(mapping));
3985274f052SJens Axboe 		if (!page)
3995274f052SJens Axboe 			goto out;
4005274f052SJens Axboe 
4015274f052SJens Axboe 		/*
4025274f052SJens Axboe 		 * If the page is uptodate, it is also locked. If it isn't
4035274f052SJens Axboe 		 * uptodate, we can mark it uptodate if we are filling the
4045274f052SJens Axboe 		 * full page. Otherwise we need to read it in first...
4055274f052SJens Axboe 		 */
4065274f052SJens Axboe 		if (!PageUptodate(page)) {
4075274f052SJens Axboe 			if (sd->len < PAGE_CACHE_SIZE) {
4085274f052SJens Axboe 				ret = mapping->a_ops->readpage(file, page);
4095274f052SJens Axboe 				if (unlikely(ret))
4105274f052SJens Axboe 					goto out;
4115274f052SJens Axboe 
4125274f052SJens Axboe 				lock_page(page);
4135274f052SJens Axboe 
4145274f052SJens Axboe 				if (!PageUptodate(page)) {
4155274f052SJens Axboe 					/*
4165274f052SJens Axboe 					 * page got invalidated, repeat
4175274f052SJens Axboe 					 */
4185274f052SJens Axboe 					if (!page->mapping) {
4195274f052SJens Axboe 						unlock_page(page);
4205274f052SJens Axboe 						page_cache_release(page);
4215274f052SJens Axboe 						goto find_page;
4225274f052SJens Axboe 					}
4235274f052SJens Axboe 					ret = -EIO;
4245274f052SJens Axboe 					goto out;
4255274f052SJens Axboe 				}
4265274f052SJens Axboe 			} else {
4275274f052SJens Axboe 				WARN_ON(!PageLocked(page));
4285274f052SJens Axboe 				SetPageUptodate(page);
4295274f052SJens Axboe 			}
4305274f052SJens Axboe 		}
4315abc97aaSJens Axboe 	}
4325274f052SJens Axboe 
4335274f052SJens Axboe 	ret = mapping->a_ops->prepare_write(file, page, 0, sd->len);
4345274f052SJens Axboe 	if (ret)
4355274f052SJens Axboe 		goto out;
4365274f052SJens Axboe 
4375abc97aaSJens Axboe 	if (!buf->stolen) {
4385abc97aaSJens Axboe 		char *dst = kmap_atomic(page, KM_USER0);
4395abc97aaSJens Axboe 
4405274f052SJens Axboe 		memcpy(dst + offset, src + buf->offset, sd->len);
4415274f052SJens Axboe 		flush_dcache_page(page);
4425274f052SJens Axboe 		kunmap_atomic(dst, KM_USER0);
4435abc97aaSJens Axboe 	}
4445274f052SJens Axboe 
4455274f052SJens Axboe 	ret = mapping->a_ops->commit_write(file, page, 0, sd->len);
4465274f052SJens Axboe 	if (ret < 0)
4475274f052SJens Axboe 		goto out;
4485274f052SJens Axboe 
4495274f052SJens Axboe 	set_page_dirty(page);
4505274f052SJens Axboe 	ret = write_one_page(page, 0);
4515274f052SJens Axboe out:
4525274f052SJens Axboe 	if (ret < 0)
4535274f052SJens Axboe 		unlock_page(page);
4545abc97aaSJens Axboe 	if (!buf->stolen)
4555274f052SJens Axboe 		page_cache_release(page);
4565274f052SJens Axboe 	buf->ops->unmap(info, buf);
4575274f052SJens Axboe 	return ret;
4585274f052SJens Axboe }
4595274f052SJens Axboe 
4605274f052SJens Axboe typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
4615274f052SJens Axboe 			   struct splice_desc *);
4625274f052SJens Axboe 
4635274f052SJens Axboe static ssize_t move_from_pipe(struct inode *inode, struct file *out,
4645274f052SJens Axboe 			      size_t len, unsigned int flags,
4655274f052SJens Axboe 			      splice_actor *actor)
4665274f052SJens Axboe {
4675274f052SJens Axboe 	struct pipe_inode_info *info;
4685274f052SJens Axboe 	int ret, do_wakeup, err;
4695274f052SJens Axboe 	struct splice_desc sd;
4705274f052SJens Axboe 
4715274f052SJens Axboe 	ret = 0;
4725274f052SJens Axboe 	do_wakeup = 0;
4735274f052SJens Axboe 
4745274f052SJens Axboe 	sd.total_len = len;
4755274f052SJens Axboe 	sd.flags = flags;
4765274f052SJens Axboe 	sd.file = out;
4775274f052SJens Axboe 	sd.pos = out->f_pos;
4785274f052SJens Axboe 
4795274f052SJens Axboe 	mutex_lock(PIPE_MUTEX(*inode));
4805274f052SJens Axboe 
4815274f052SJens Axboe 	info = inode->i_pipe;
4825274f052SJens Axboe 	for (;;) {
4835274f052SJens Axboe 		int bufs = info->nrbufs;
4845274f052SJens Axboe 
4855274f052SJens Axboe 		if (bufs) {
4865274f052SJens Axboe 			int curbuf = info->curbuf;
4875274f052SJens Axboe 			struct pipe_buffer *buf = info->bufs + curbuf;
4885274f052SJens Axboe 			struct pipe_buf_operations *ops = buf->ops;
4895274f052SJens Axboe 
4905274f052SJens Axboe 			sd.len = buf->len;
4915274f052SJens Axboe 			if (sd.len > sd.total_len)
4925274f052SJens Axboe 				sd.len = sd.total_len;
4935274f052SJens Axboe 
4945274f052SJens Axboe 			err = actor(info, buf, &sd);
4955274f052SJens Axboe 			if (err) {
4965274f052SJens Axboe 				if (!ret && err != -ENODATA)
4975274f052SJens Axboe 					ret = err;
4985274f052SJens Axboe 
4995274f052SJens Axboe 				break;
5005274f052SJens Axboe 			}
5015274f052SJens Axboe 
5025274f052SJens Axboe 			ret += sd.len;
5035274f052SJens Axboe 			buf->offset += sd.len;
5045274f052SJens Axboe 			buf->len -= sd.len;
5055274f052SJens Axboe 			if (!buf->len) {
5065274f052SJens Axboe 				buf->ops = NULL;
5075274f052SJens Axboe 				ops->release(info, buf);
5085274f052SJens Axboe 				curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1);
5095274f052SJens Axboe 				info->curbuf = curbuf;
5105274f052SJens Axboe 				info->nrbufs = --bufs;
5115274f052SJens Axboe 				do_wakeup = 1;
5125274f052SJens Axboe 			}
5135274f052SJens Axboe 
5145274f052SJens Axboe 			sd.pos += sd.len;
5155274f052SJens Axboe 			sd.total_len -= sd.len;
5165274f052SJens Axboe 			if (!sd.total_len)
5175274f052SJens Axboe 				break;
5185274f052SJens Axboe 		}
5195274f052SJens Axboe 
5205274f052SJens Axboe 		if (bufs)
5215274f052SJens Axboe 			continue;
5225274f052SJens Axboe 		if (!PIPE_WRITERS(*inode))
5235274f052SJens Axboe 			break;
5245274f052SJens Axboe 		if (!PIPE_WAITING_WRITERS(*inode)) {
5255274f052SJens Axboe 			if (ret)
5265274f052SJens Axboe 				break;
5275274f052SJens Axboe 		}
5285274f052SJens Axboe 
5295274f052SJens Axboe 		if (signal_pending(current)) {
5305274f052SJens Axboe 			if (!ret)
5315274f052SJens Axboe 				ret = -ERESTARTSYS;
5325274f052SJens Axboe 			break;
5335274f052SJens Axboe 		}
5345274f052SJens Axboe 
5355274f052SJens Axboe 		if (do_wakeup) {
5365274f052SJens Axboe 			wake_up_interruptible_sync(PIPE_WAIT(*inode));
5375274f052SJens Axboe 			kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT);
5385274f052SJens Axboe 			do_wakeup = 0;
5395274f052SJens Axboe 		}
5405274f052SJens Axboe 
5415274f052SJens Axboe 		pipe_wait(inode);
5425274f052SJens Axboe 	}
5435274f052SJens Axboe 
5445274f052SJens Axboe 	mutex_unlock(PIPE_MUTEX(*inode));
5455274f052SJens Axboe 
5465274f052SJens Axboe 	if (do_wakeup) {
5475274f052SJens Axboe 		wake_up_interruptible(PIPE_WAIT(*inode));
5485274f052SJens Axboe 		kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
5495274f052SJens Axboe 	}
5505274f052SJens Axboe 
5515274f052SJens Axboe 	mutex_lock(&out->f_mapping->host->i_mutex);
5525274f052SJens Axboe 	out->f_pos = sd.pos;
5535274f052SJens Axboe 	mutex_unlock(&out->f_mapping->host->i_mutex);
5545274f052SJens Axboe 	return ret;
5555274f052SJens Axboe 
5565274f052SJens Axboe }
5575274f052SJens Axboe 
5585274f052SJens Axboe ssize_t generic_file_splice_write(struct inode *inode, struct file *out,
5595274f052SJens Axboe 				  size_t len, unsigned int flags)
5605274f052SJens Axboe {
5615274f052SJens Axboe 	return move_from_pipe(inode, out, len, flags, pipe_to_file);
5625274f052SJens Axboe }
5635274f052SJens Axboe 
5645274f052SJens Axboe ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
5655274f052SJens Axboe 				size_t len, unsigned int flags)
5665274f052SJens Axboe {
5675274f052SJens Axboe 	return move_from_pipe(inode, out, len, flags, pipe_to_sendpage);
5685274f052SJens Axboe }
5695274f052SJens Axboe 
5705274f052SJens Axboe static long do_splice_from(struct inode *pipe, struct file *out, size_t len,
5715274f052SJens Axboe 			   unsigned int flags)
5725274f052SJens Axboe {
5735274f052SJens Axboe 	loff_t pos;
5745274f052SJens Axboe 	int ret;
5755274f052SJens Axboe 
5765274f052SJens Axboe 	if (!out->f_op || !out->f_op->splice_write)
5775274f052SJens Axboe 		return -EINVAL;
5785274f052SJens Axboe 
5795274f052SJens Axboe 	if (!(out->f_mode & FMODE_WRITE))
5805274f052SJens Axboe 		return -EBADF;
5815274f052SJens Axboe 
5825274f052SJens Axboe 	pos = out->f_pos;
5835274f052SJens Axboe 	ret = rw_verify_area(WRITE, out, &pos, len);
5845274f052SJens Axboe 	if (unlikely(ret < 0))
5855274f052SJens Axboe 		return ret;
5865274f052SJens Axboe 
5875274f052SJens Axboe 	return out->f_op->splice_write(pipe, out, len, flags);
5885274f052SJens Axboe }
5895274f052SJens Axboe 
5905274f052SJens Axboe static long do_splice_to(struct file *in, struct inode *pipe, size_t len,
5915274f052SJens Axboe 			 unsigned int flags)
5925274f052SJens Axboe {
5935274f052SJens Axboe 	loff_t pos, isize, left;
5945274f052SJens Axboe 	int ret;
5955274f052SJens Axboe 
5965274f052SJens Axboe 	if (!in->f_op || !in->f_op->splice_read)
5975274f052SJens Axboe 		return -EINVAL;
5985274f052SJens Axboe 
5995274f052SJens Axboe 	if (!(in->f_mode & FMODE_READ))
6005274f052SJens Axboe 		return -EBADF;
6015274f052SJens Axboe 
6025274f052SJens Axboe 	pos = in->f_pos;
6035274f052SJens Axboe 	ret = rw_verify_area(READ, in, &pos, len);
6045274f052SJens Axboe 	if (unlikely(ret < 0))
6055274f052SJens Axboe 		return ret;
6065274f052SJens Axboe 
6075274f052SJens Axboe 	isize = i_size_read(in->f_mapping->host);
6085274f052SJens Axboe 	if (unlikely(in->f_pos >= isize))
6095274f052SJens Axboe 		return 0;
6105274f052SJens Axboe 
6115274f052SJens Axboe 	left = isize - in->f_pos;
6125274f052SJens Axboe 	if (left < len)
6135274f052SJens Axboe 		len = left;
6145274f052SJens Axboe 
6155274f052SJens Axboe 	return in->f_op->splice_read(in, pipe, len, flags);
6165274f052SJens Axboe }
6175274f052SJens Axboe 
6185274f052SJens Axboe static long do_splice(struct file *in, struct file *out, size_t len,
6195274f052SJens Axboe 		      unsigned int flags)
6205274f052SJens Axboe {
6215274f052SJens Axboe 	struct inode *pipe;
6225274f052SJens Axboe 
6235274f052SJens Axboe 	pipe = in->f_dentry->d_inode;
6245274f052SJens Axboe 	if (pipe->i_pipe)
6255274f052SJens Axboe 		return do_splice_from(pipe, out, len, flags);
6265274f052SJens Axboe 
6275274f052SJens Axboe 	pipe = out->f_dentry->d_inode;
6285274f052SJens Axboe 	if (pipe->i_pipe)
6295274f052SJens Axboe 		return do_splice_to(in, pipe, len, flags);
6305274f052SJens Axboe 
6315274f052SJens Axboe 	return -EINVAL;
6325274f052SJens Axboe }
6335274f052SJens Axboe 
6345274f052SJens Axboe asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags)
6355274f052SJens Axboe {
6365274f052SJens Axboe 	long error;
6375274f052SJens Axboe 	struct file *in, *out;
6385274f052SJens Axboe 	int fput_in, fput_out;
6395274f052SJens Axboe 
6405274f052SJens Axboe 	if (unlikely(!len))
6415274f052SJens Axboe 		return 0;
6425274f052SJens Axboe 
6435274f052SJens Axboe 	error = -EBADF;
6445274f052SJens Axboe 	in = fget_light(fdin, &fput_in);
6455274f052SJens Axboe 	if (in) {
6465274f052SJens Axboe 		if (in->f_mode & FMODE_READ) {
6475274f052SJens Axboe 			out = fget_light(fdout, &fput_out);
6485274f052SJens Axboe 			if (out) {
6495274f052SJens Axboe 				if (out->f_mode & FMODE_WRITE)
6505274f052SJens Axboe 					error = do_splice(in, out, len, flags);
6515274f052SJens Axboe 				fput_light(out, fput_out);
6525274f052SJens Axboe 			}
6535274f052SJens Axboe 		}
6545274f052SJens Axboe 
6555274f052SJens Axboe 		fput_light(in, fput_in);
6565274f052SJens Axboe 	}
6575274f052SJens Axboe 
6585274f052SJens Axboe 	return error;
6595274f052SJens Axboe }
660