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