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> 25a0f06780SJeff Garzik #include <linux/module.h> 265274f052SJens Axboe 275274f052SJens Axboe /* 285274f052SJens Axboe * Passed to the actors 295274f052SJens Axboe */ 305274f052SJens Axboe struct splice_desc { 315274f052SJens Axboe unsigned int len, total_len; /* current and remaining length */ 325274f052SJens Axboe unsigned int flags; /* splice flags */ 335274f052SJens Axboe struct file *file; /* file to read/write */ 345274f052SJens Axboe loff_t pos; /* file position */ 355274f052SJens Axboe }; 365274f052SJens Axboe 375abc97aaSJens Axboe static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, 385abc97aaSJens Axboe struct pipe_buffer *buf) 395abc97aaSJens Axboe { 405abc97aaSJens Axboe struct page *page = buf->page; 415abc97aaSJens Axboe 425abc97aaSJens Axboe WARN_ON(!PageLocked(page)); 435abc97aaSJens Axboe WARN_ON(!PageUptodate(page)); 445abc97aaSJens Axboe 455abc97aaSJens Axboe if (!remove_mapping(page_mapping(page), page)) 465abc97aaSJens Axboe return 1; 475abc97aaSJens Axboe 485abc97aaSJens Axboe if (PageLRU(page)) { 495abc97aaSJens Axboe struct zone *zone = page_zone(page); 505abc97aaSJens Axboe 515abc97aaSJens Axboe spin_lock_irq(&zone->lru_lock); 525abc97aaSJens Axboe BUG_ON(!PageLRU(page)); 535abc97aaSJens Axboe __ClearPageLRU(page); 545abc97aaSJens Axboe del_page_from_lru(zone, page); 555abc97aaSJens Axboe spin_unlock_irq(&zone->lru_lock); 565abc97aaSJens Axboe } 575abc97aaSJens Axboe 585abc97aaSJens Axboe buf->stolen = 1; 595abc97aaSJens Axboe return 0; 605abc97aaSJens Axboe } 615abc97aaSJens Axboe 625274f052SJens Axboe static void page_cache_pipe_buf_release(struct pipe_inode_info *info, 635274f052SJens Axboe struct pipe_buffer *buf) 645274f052SJens Axboe { 655274f052SJens Axboe page_cache_release(buf->page); 665274f052SJens Axboe buf->page = NULL; 675abc97aaSJens Axboe buf->stolen = 0; 685274f052SJens Axboe } 695274f052SJens Axboe 705274f052SJens Axboe static void *page_cache_pipe_buf_map(struct file *file, 715274f052SJens Axboe struct pipe_inode_info *info, 725274f052SJens Axboe struct pipe_buffer *buf) 735274f052SJens Axboe { 745274f052SJens Axboe struct page *page = buf->page; 755274f052SJens Axboe 765274f052SJens Axboe lock_page(page); 775274f052SJens Axboe 785274f052SJens Axboe if (!PageUptodate(page)) { 795274f052SJens Axboe unlock_page(page); 805274f052SJens Axboe return ERR_PTR(-EIO); 815274f052SJens Axboe } 825274f052SJens Axboe 835274f052SJens Axboe if (!page->mapping) { 845274f052SJens Axboe unlock_page(page); 855274f052SJens Axboe return ERR_PTR(-ENODATA); 865274f052SJens Axboe } 875274f052SJens Axboe 885274f052SJens Axboe return kmap(buf->page); 895274f052SJens Axboe } 905274f052SJens Axboe 915274f052SJens Axboe static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info, 925274f052SJens Axboe struct pipe_buffer *buf) 935274f052SJens Axboe { 945abc97aaSJens Axboe if (!buf->stolen) 955274f052SJens Axboe unlock_page(buf->page); 965274f052SJens Axboe kunmap(buf->page); 975274f052SJens Axboe } 985274f052SJens Axboe 995274f052SJens Axboe static struct pipe_buf_operations page_cache_pipe_buf_ops = { 1005274f052SJens Axboe .can_merge = 0, 1015274f052SJens Axboe .map = page_cache_pipe_buf_map, 1025274f052SJens Axboe .unmap = page_cache_pipe_buf_unmap, 1035274f052SJens Axboe .release = page_cache_pipe_buf_release, 1045abc97aaSJens Axboe .steal = page_cache_pipe_buf_steal, 1055274f052SJens Axboe }; 1065274f052SJens Axboe 1075274f052SJens Axboe static ssize_t move_to_pipe(struct inode *inode, struct page **pages, 1085274f052SJens Axboe int nr_pages, unsigned long offset, 10929e35094SLinus Torvalds unsigned long len, unsigned int flags) 1105274f052SJens Axboe { 1115274f052SJens Axboe struct pipe_inode_info *info; 1125274f052SJens Axboe int ret, do_wakeup, i; 1135274f052SJens Axboe 1145274f052SJens Axboe ret = 0; 1155274f052SJens Axboe do_wakeup = 0; 1165274f052SJens Axboe i = 0; 1175274f052SJens Axboe 1185274f052SJens Axboe mutex_lock(PIPE_MUTEX(*inode)); 1195274f052SJens Axboe 1205274f052SJens Axboe info = inode->i_pipe; 1215274f052SJens Axboe for (;;) { 1225274f052SJens Axboe int bufs; 1235274f052SJens Axboe 1245274f052SJens Axboe if (!PIPE_READERS(*inode)) { 1255274f052SJens Axboe send_sig(SIGPIPE, current, 0); 1265274f052SJens Axboe if (!ret) 1275274f052SJens Axboe ret = -EPIPE; 1285274f052SJens Axboe break; 1295274f052SJens Axboe } 1305274f052SJens Axboe 1315274f052SJens Axboe bufs = info->nrbufs; 1325274f052SJens Axboe if (bufs < PIPE_BUFFERS) { 1335274f052SJens Axboe int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1); 1345274f052SJens Axboe struct pipe_buffer *buf = info->bufs + newbuf; 1355274f052SJens Axboe struct page *page = pages[i++]; 1365274f052SJens Axboe unsigned long this_len; 1375274f052SJens Axboe 1385274f052SJens Axboe this_len = PAGE_CACHE_SIZE - offset; 1395274f052SJens Axboe if (this_len > len) 1405274f052SJens Axboe this_len = len; 1415274f052SJens Axboe 1425274f052SJens Axboe buf->page = page; 1435274f052SJens Axboe buf->offset = offset; 1445274f052SJens Axboe buf->len = this_len; 1455274f052SJens Axboe buf->ops = &page_cache_pipe_buf_ops; 1465274f052SJens Axboe info->nrbufs = ++bufs; 1475274f052SJens Axboe do_wakeup = 1; 1485274f052SJens Axboe 1495274f052SJens Axboe ret += this_len; 1505274f052SJens Axboe len -= this_len; 1515274f052SJens Axboe offset = 0; 1525274f052SJens Axboe if (!--nr_pages) 1535274f052SJens Axboe break; 1545274f052SJens Axboe if (!len) 1555274f052SJens Axboe break; 1565274f052SJens Axboe if (bufs < PIPE_BUFFERS) 1575274f052SJens Axboe continue; 1585274f052SJens Axboe 1595274f052SJens Axboe break; 1605274f052SJens Axboe } 1615274f052SJens Axboe 16229e35094SLinus Torvalds if (flags & SPLICE_F_NONBLOCK) { 16329e35094SLinus Torvalds if (!ret) 16429e35094SLinus Torvalds ret = -EAGAIN; 16529e35094SLinus Torvalds break; 16629e35094SLinus Torvalds } 16729e35094SLinus Torvalds 1685274f052SJens Axboe if (signal_pending(current)) { 1695274f052SJens Axboe if (!ret) 1705274f052SJens Axboe ret = -ERESTARTSYS; 1715274f052SJens Axboe break; 1725274f052SJens Axboe } 1735274f052SJens Axboe 1745274f052SJens Axboe if (do_wakeup) { 1755274f052SJens Axboe wake_up_interruptible_sync(PIPE_WAIT(*inode)); 1765274f052SJens Axboe kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, 1775274f052SJens Axboe POLL_IN); 1785274f052SJens Axboe do_wakeup = 0; 1795274f052SJens Axboe } 1805274f052SJens Axboe 1815274f052SJens Axboe PIPE_WAITING_WRITERS(*inode)++; 1825274f052SJens Axboe pipe_wait(inode); 1835274f052SJens Axboe PIPE_WAITING_WRITERS(*inode)--; 1845274f052SJens Axboe } 1855274f052SJens Axboe 1865274f052SJens Axboe mutex_unlock(PIPE_MUTEX(*inode)); 1875274f052SJens Axboe 1885274f052SJens Axboe if (do_wakeup) { 1895274f052SJens Axboe wake_up_interruptible(PIPE_WAIT(*inode)); 1905274f052SJens Axboe kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); 1915274f052SJens Axboe } 1925274f052SJens Axboe 1935274f052SJens Axboe while (i < nr_pages) 1945274f052SJens Axboe page_cache_release(pages[i++]); 1955274f052SJens Axboe 1965274f052SJens Axboe return ret; 1975274f052SJens Axboe } 1985274f052SJens Axboe 1995274f052SJens Axboe static int __generic_file_splice_read(struct file *in, struct inode *pipe, 20029e35094SLinus Torvalds size_t len, unsigned int flags) 2015274f052SJens Axboe { 2025274f052SJens Axboe struct address_space *mapping = in->f_mapping; 2035274f052SJens Axboe unsigned int offset, nr_pages; 2045274f052SJens Axboe struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS]; 2055274f052SJens Axboe struct page *page; 2065274f052SJens Axboe pgoff_t index, pidx; 2075274f052SJens Axboe int i, j; 2085274f052SJens Axboe 2095274f052SJens Axboe index = in->f_pos >> PAGE_CACHE_SHIFT; 2105274f052SJens Axboe offset = in->f_pos & ~PAGE_CACHE_MASK; 2115274f052SJens Axboe nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 2125274f052SJens Axboe 2135274f052SJens Axboe if (nr_pages > PIPE_BUFFERS) 2145274f052SJens Axboe nr_pages = PIPE_BUFFERS; 2155274f052SJens Axboe 2165274f052SJens Axboe /* 2175274f052SJens Axboe * initiate read-ahead on this page range 2185274f052SJens Axboe */ 2195274f052SJens Axboe do_page_cache_readahead(mapping, in, index, nr_pages); 2205274f052SJens Axboe 2215274f052SJens Axboe /* 2225274f052SJens Axboe * Get as many pages from the page cache as possible.. 2235274f052SJens Axboe * Start IO on the page cache entries we create (we 2245274f052SJens Axboe * can assume that any pre-existing ones we find have 2255274f052SJens Axboe * already had IO started on them). 2265274f052SJens Axboe */ 2275274f052SJens Axboe i = find_get_pages(mapping, index, nr_pages, pages); 2285274f052SJens Axboe 2295274f052SJens Axboe /* 2305274f052SJens Axboe * common case - we found all pages and they are contiguous, 2315274f052SJens Axboe * kick them off 2325274f052SJens Axboe */ 2335274f052SJens Axboe if (i && (pages[i - 1]->index == index + i - 1)) 2345274f052SJens Axboe goto splice_them; 2355274f052SJens Axboe 2365274f052SJens Axboe /* 2375274f052SJens Axboe * fill shadow[] with pages at the right locations, so we only 2385274f052SJens Axboe * have to fill holes 2395274f052SJens Axboe */ 2405274f052SJens Axboe memset(shadow, 0, i * sizeof(struct page *)); 2415274f052SJens Axboe for (j = 0, pidx = index; j < i; pidx++, j++) 2425274f052SJens Axboe shadow[pages[j]->index - pidx] = pages[j]; 2435274f052SJens Axboe 2445274f052SJens Axboe /* 2455274f052SJens Axboe * now fill in the holes 2465274f052SJens Axboe */ 2475274f052SJens Axboe for (i = 0, pidx = index; i < nr_pages; pidx++, i++) { 2485274f052SJens Axboe int error; 2495274f052SJens Axboe 2505274f052SJens Axboe if (shadow[i]) 2515274f052SJens Axboe continue; 2525274f052SJens Axboe 2535274f052SJens Axboe /* 2545274f052SJens Axboe * no page there, look one up / create it 2555274f052SJens Axboe */ 2565274f052SJens Axboe page = find_or_create_page(mapping, pidx, 2575274f052SJens Axboe mapping_gfp_mask(mapping)); 2585274f052SJens Axboe if (!page) 2595274f052SJens Axboe break; 2605274f052SJens Axboe 2615274f052SJens Axboe if (PageUptodate(page)) 2625274f052SJens Axboe unlock_page(page); 2635274f052SJens Axboe else { 2645274f052SJens Axboe error = mapping->a_ops->readpage(in, page); 2655274f052SJens Axboe 2665274f052SJens Axboe if (unlikely(error)) { 2675274f052SJens Axboe page_cache_release(page); 2685274f052SJens Axboe break; 2695274f052SJens Axboe } 2705274f052SJens Axboe } 2715274f052SJens Axboe shadow[i] = page; 2725274f052SJens Axboe } 2735274f052SJens Axboe 2745274f052SJens Axboe if (!i) { 2755274f052SJens Axboe for (i = 0; i < nr_pages; i++) { 2765274f052SJens Axboe if (shadow[i]) 2775274f052SJens Axboe page_cache_release(shadow[i]); 2785274f052SJens Axboe } 2795274f052SJens Axboe return 0; 2805274f052SJens Axboe } 2815274f052SJens Axboe 2825274f052SJens Axboe memcpy(pages, shadow, i * sizeof(struct page *)); 2835274f052SJens Axboe 2845274f052SJens Axboe /* 2855274f052SJens Axboe * Now we splice them into the pipe.. 2865274f052SJens Axboe */ 2875274f052SJens Axboe splice_them: 28829e35094SLinus Torvalds return move_to_pipe(pipe, pages, i, offset, len, flags); 2895274f052SJens Axboe } 2905274f052SJens Axboe 2915274f052SJens Axboe ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, 2925274f052SJens Axboe size_t len, unsigned int flags) 2935274f052SJens Axboe { 2945274f052SJens Axboe ssize_t spliced; 2955274f052SJens Axboe int ret; 2965274f052SJens Axboe 2975274f052SJens Axboe ret = 0; 2985274f052SJens Axboe spliced = 0; 2995274f052SJens Axboe while (len) { 30029e35094SLinus Torvalds ret = __generic_file_splice_read(in, pipe, len, flags); 3015274f052SJens Axboe 3025274f052SJens Axboe if (ret <= 0) 3035274f052SJens Axboe break; 3045274f052SJens Axboe 3055274f052SJens Axboe in->f_pos += ret; 3065274f052SJens Axboe len -= ret; 3075274f052SJens Axboe spliced += ret; 30829e35094SLinus Torvalds 30929e35094SLinus Torvalds if (!(flags & SPLICE_F_NONBLOCK)) 31029e35094SLinus Torvalds continue; 31129e35094SLinus Torvalds ret = -EAGAIN; 31229e35094SLinus Torvalds break; 3135274f052SJens Axboe } 3145274f052SJens Axboe 3155274f052SJens Axboe if (spliced) 3165274f052SJens Axboe return spliced; 3175274f052SJens Axboe 3185274f052SJens Axboe return ret; 3195274f052SJens Axboe } 3205274f052SJens Axboe 3215274f052SJens Axboe /* 3225274f052SJens Axboe * Send 'len' bytes to socket from 'file' at position 'pos' using sendpage(). 3235274f052SJens Axboe */ 3245274f052SJens Axboe static int pipe_to_sendpage(struct pipe_inode_info *info, 3255274f052SJens Axboe struct pipe_buffer *buf, struct splice_desc *sd) 3265274f052SJens Axboe { 3275274f052SJens Axboe struct file *file = sd->file; 3285274f052SJens Axboe loff_t pos = sd->pos; 3295274f052SJens Axboe unsigned int offset; 3305274f052SJens Axboe ssize_t ret; 3315274f052SJens Axboe void *ptr; 3325274f052SJens Axboe 3335274f052SJens Axboe /* 3345274f052SJens Axboe * sub-optimal, but we are limited by the pipe ->map. we don't 3355274f052SJens Axboe * need a kmap'ed buffer here, we just want to make sure we 3365274f052SJens Axboe * have the page pinned if the pipe page originates from the 3375274f052SJens Axboe * page cache 3385274f052SJens Axboe */ 3395274f052SJens Axboe ptr = buf->ops->map(file, info, buf); 3405274f052SJens Axboe if (IS_ERR(ptr)) 3415274f052SJens Axboe return PTR_ERR(ptr); 3425274f052SJens Axboe 3435274f052SJens Axboe offset = pos & ~PAGE_CACHE_MASK; 3445274f052SJens Axboe 3455274f052SJens Axboe ret = file->f_op->sendpage(file, buf->page, offset, sd->len, &pos, 3465274f052SJens Axboe sd->len < sd->total_len); 3475274f052SJens Axboe 3485274f052SJens Axboe buf->ops->unmap(info, buf); 3495274f052SJens Axboe if (ret == sd->len) 3505274f052SJens Axboe return 0; 3515274f052SJens Axboe 3525274f052SJens Axboe return -EIO; 3535274f052SJens Axboe } 3545274f052SJens Axboe 3555274f052SJens Axboe /* 3565274f052SJens Axboe * This is a little more tricky than the file -> pipe splicing. There are 3575274f052SJens Axboe * basically three cases: 3585274f052SJens Axboe * 3595274f052SJens Axboe * - Destination page already exists in the address space and there 3605274f052SJens Axboe * are users of it. For that case we have no other option that 3615274f052SJens Axboe * copying the data. Tough luck. 3625274f052SJens Axboe * - Destination page already exists in the address space, but there 3635274f052SJens Axboe * are no users of it. Make sure it's uptodate, then drop it. Fall 3645274f052SJens Axboe * through to last case. 3655274f052SJens Axboe * - Destination page does not exist, we can add the pipe page to 3665274f052SJens Axboe * the page cache and avoid the copy. 3675274f052SJens Axboe * 3685274f052SJens Axboe * For now we just do the slower thing and always copy pages over, it's 3695274f052SJens Axboe * easier than migrating pages from the pipe to the target file. For the 3705274f052SJens Axboe * case of doing file | file splicing, the migrate approach had some LRU 3715274f052SJens Axboe * nastiness... 3725274f052SJens Axboe */ 3735274f052SJens Axboe static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, 3745274f052SJens Axboe struct splice_desc *sd) 3755274f052SJens Axboe { 3765274f052SJens Axboe struct file *file = sd->file; 3775274f052SJens Axboe struct address_space *mapping = file->f_mapping; 3785274f052SJens Axboe unsigned int offset; 3795274f052SJens Axboe struct page *page; 3805274f052SJens Axboe pgoff_t index; 3815abc97aaSJens Axboe char *src; 3825274f052SJens Axboe int ret; 3835274f052SJens Axboe 3845274f052SJens Axboe /* 3855274f052SJens Axboe * after this, page will be locked and unmapped 3865274f052SJens Axboe */ 3875274f052SJens Axboe src = buf->ops->map(file, info, buf); 3885274f052SJens Axboe if (IS_ERR(src)) 3895274f052SJens Axboe return PTR_ERR(src); 3905274f052SJens Axboe 3915274f052SJens Axboe index = sd->pos >> PAGE_CACHE_SHIFT; 3925274f052SJens Axboe offset = sd->pos & ~PAGE_CACHE_MASK; 3935274f052SJens Axboe 3945abc97aaSJens Axboe /* 3955abc97aaSJens Axboe * reuse buf page, if SPLICE_F_MOVE is set 3965abc97aaSJens Axboe */ 3975abc97aaSJens Axboe if (sd->flags & SPLICE_F_MOVE) { 3985abc97aaSJens Axboe if (buf->ops->steal(info, buf)) 3995abc97aaSJens Axboe goto find_page; 4005abc97aaSJens Axboe 4015abc97aaSJens Axboe page = buf->page; 4025abc97aaSJens Axboe if (add_to_page_cache_lru(page, mapping, index, 4035abc97aaSJens Axboe mapping_gfp_mask(mapping))) 4045abc97aaSJens Axboe goto find_page; 4055abc97aaSJens Axboe } else { 4065274f052SJens Axboe find_page: 4075274f052SJens Axboe ret = -ENOMEM; 4085abc97aaSJens Axboe page = find_or_create_page(mapping, index, 4095abc97aaSJens Axboe mapping_gfp_mask(mapping)); 4105274f052SJens Axboe if (!page) 4115274f052SJens Axboe goto out; 4125274f052SJens Axboe 4135274f052SJens Axboe /* 4145274f052SJens Axboe * If the page is uptodate, it is also locked. If it isn't 4155274f052SJens Axboe * uptodate, we can mark it uptodate if we are filling the 4165274f052SJens Axboe * full page. Otherwise we need to read it in first... 4175274f052SJens Axboe */ 4185274f052SJens Axboe if (!PageUptodate(page)) { 4195274f052SJens Axboe if (sd->len < PAGE_CACHE_SIZE) { 4205274f052SJens Axboe ret = mapping->a_ops->readpage(file, page); 4215274f052SJens Axboe if (unlikely(ret)) 4225274f052SJens Axboe goto out; 4235274f052SJens Axboe 4245274f052SJens Axboe lock_page(page); 4255274f052SJens Axboe 4265274f052SJens Axboe if (!PageUptodate(page)) { 4275274f052SJens Axboe /* 4285274f052SJens Axboe * page got invalidated, repeat 4295274f052SJens Axboe */ 4305274f052SJens Axboe if (!page->mapping) { 4315274f052SJens Axboe unlock_page(page); 4325274f052SJens Axboe page_cache_release(page); 4335274f052SJens Axboe goto find_page; 4345274f052SJens Axboe } 4355274f052SJens Axboe ret = -EIO; 4365274f052SJens Axboe goto out; 4375274f052SJens Axboe } 4385274f052SJens Axboe } else { 4395274f052SJens Axboe WARN_ON(!PageLocked(page)); 4405274f052SJens Axboe SetPageUptodate(page); 4415274f052SJens Axboe } 4425274f052SJens Axboe } 4435abc97aaSJens Axboe } 4445274f052SJens Axboe 4455274f052SJens Axboe ret = mapping->a_ops->prepare_write(file, page, 0, sd->len); 4465274f052SJens Axboe if (ret) 4475274f052SJens Axboe goto out; 4485274f052SJens Axboe 4495abc97aaSJens Axboe if (!buf->stolen) { 4505abc97aaSJens Axboe char *dst = kmap_atomic(page, KM_USER0); 4515abc97aaSJens Axboe 4525274f052SJens Axboe memcpy(dst + offset, src + buf->offset, sd->len); 4535274f052SJens Axboe flush_dcache_page(page); 4545274f052SJens Axboe kunmap_atomic(dst, KM_USER0); 4555abc97aaSJens Axboe } 4565274f052SJens Axboe 4575274f052SJens Axboe ret = mapping->a_ops->commit_write(file, page, 0, sd->len); 4585274f052SJens Axboe if (ret < 0) 4595274f052SJens Axboe goto out; 4605274f052SJens Axboe 4615274f052SJens Axboe set_page_dirty(page); 4625274f052SJens Axboe ret = write_one_page(page, 0); 4635274f052SJens Axboe out: 4645274f052SJens Axboe if (ret < 0) 4655274f052SJens Axboe unlock_page(page); 4665abc97aaSJens Axboe if (!buf->stolen) 4675274f052SJens Axboe page_cache_release(page); 4685274f052SJens Axboe buf->ops->unmap(info, buf); 4695274f052SJens Axboe return ret; 4705274f052SJens Axboe } 4715274f052SJens Axboe 4725274f052SJens Axboe typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, 4735274f052SJens Axboe struct splice_desc *); 4745274f052SJens Axboe 4755274f052SJens Axboe static ssize_t move_from_pipe(struct inode *inode, struct file *out, 4765274f052SJens Axboe size_t len, unsigned int flags, 4775274f052SJens Axboe splice_actor *actor) 4785274f052SJens Axboe { 4795274f052SJens Axboe struct pipe_inode_info *info; 4805274f052SJens Axboe int ret, do_wakeup, err; 4815274f052SJens Axboe struct splice_desc sd; 4825274f052SJens Axboe 4835274f052SJens Axboe ret = 0; 4845274f052SJens Axboe do_wakeup = 0; 4855274f052SJens Axboe 4865274f052SJens Axboe sd.total_len = len; 4875274f052SJens Axboe sd.flags = flags; 4885274f052SJens Axboe sd.file = out; 4895274f052SJens Axboe sd.pos = out->f_pos; 4905274f052SJens Axboe 4915274f052SJens Axboe mutex_lock(PIPE_MUTEX(*inode)); 4925274f052SJens Axboe 4935274f052SJens Axboe info = inode->i_pipe; 4945274f052SJens Axboe for (;;) { 4955274f052SJens Axboe int bufs = info->nrbufs; 4965274f052SJens Axboe 4975274f052SJens Axboe if (bufs) { 4985274f052SJens Axboe int curbuf = info->curbuf; 4995274f052SJens Axboe struct pipe_buffer *buf = info->bufs + curbuf; 5005274f052SJens Axboe struct pipe_buf_operations *ops = buf->ops; 5015274f052SJens Axboe 5025274f052SJens Axboe sd.len = buf->len; 5035274f052SJens Axboe if (sd.len > sd.total_len) 5045274f052SJens Axboe sd.len = sd.total_len; 5055274f052SJens Axboe 5065274f052SJens Axboe err = actor(info, buf, &sd); 5075274f052SJens Axboe if (err) { 5085274f052SJens Axboe if (!ret && err != -ENODATA) 5095274f052SJens Axboe ret = err; 5105274f052SJens Axboe 5115274f052SJens Axboe break; 5125274f052SJens Axboe } 5135274f052SJens Axboe 5145274f052SJens Axboe ret += sd.len; 5155274f052SJens Axboe buf->offset += sd.len; 5165274f052SJens Axboe buf->len -= sd.len; 5175274f052SJens Axboe if (!buf->len) { 5185274f052SJens Axboe buf->ops = NULL; 5195274f052SJens Axboe ops->release(info, buf); 5205274f052SJens Axboe curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1); 5215274f052SJens Axboe info->curbuf = curbuf; 5225274f052SJens Axboe info->nrbufs = --bufs; 5235274f052SJens Axboe do_wakeup = 1; 5245274f052SJens Axboe } 5255274f052SJens Axboe 5265274f052SJens Axboe sd.pos += sd.len; 5275274f052SJens Axboe sd.total_len -= sd.len; 5285274f052SJens Axboe if (!sd.total_len) 5295274f052SJens Axboe break; 5305274f052SJens Axboe } 5315274f052SJens Axboe 5325274f052SJens Axboe if (bufs) 5335274f052SJens Axboe continue; 5345274f052SJens Axboe if (!PIPE_WRITERS(*inode)) 5355274f052SJens Axboe break; 5365274f052SJens Axboe if (!PIPE_WAITING_WRITERS(*inode)) { 5375274f052SJens Axboe if (ret) 5385274f052SJens Axboe break; 5395274f052SJens Axboe } 5405274f052SJens Axboe 54129e35094SLinus Torvalds if (flags & SPLICE_F_NONBLOCK) { 54229e35094SLinus Torvalds if (!ret) 54329e35094SLinus Torvalds ret = -EAGAIN; 54429e35094SLinus Torvalds break; 54529e35094SLinus Torvalds } 54629e35094SLinus Torvalds 5475274f052SJens Axboe if (signal_pending(current)) { 5485274f052SJens Axboe if (!ret) 5495274f052SJens Axboe ret = -ERESTARTSYS; 5505274f052SJens Axboe break; 5515274f052SJens Axboe } 5525274f052SJens Axboe 5535274f052SJens Axboe if (do_wakeup) { 5545274f052SJens Axboe wake_up_interruptible_sync(PIPE_WAIT(*inode)); 5555274f052SJens Axboe kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT); 5565274f052SJens Axboe do_wakeup = 0; 5575274f052SJens Axboe } 5585274f052SJens Axboe 5595274f052SJens Axboe pipe_wait(inode); 5605274f052SJens Axboe } 5615274f052SJens Axboe 5625274f052SJens Axboe mutex_unlock(PIPE_MUTEX(*inode)); 5635274f052SJens Axboe 5645274f052SJens Axboe if (do_wakeup) { 5655274f052SJens Axboe wake_up_interruptible(PIPE_WAIT(*inode)); 5665274f052SJens Axboe kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); 5675274f052SJens Axboe } 5685274f052SJens Axboe 5695274f052SJens Axboe mutex_lock(&out->f_mapping->host->i_mutex); 5705274f052SJens Axboe out->f_pos = sd.pos; 5715274f052SJens Axboe mutex_unlock(&out->f_mapping->host->i_mutex); 5725274f052SJens Axboe return ret; 5735274f052SJens Axboe 5745274f052SJens Axboe } 5755274f052SJens Axboe 5765274f052SJens Axboe ssize_t generic_file_splice_write(struct inode *inode, struct file *out, 5775274f052SJens Axboe size_t len, unsigned int flags) 5785274f052SJens Axboe { 5795274f052SJens Axboe return move_from_pipe(inode, out, len, flags, pipe_to_file); 5805274f052SJens Axboe } 5815274f052SJens Axboe 5825274f052SJens Axboe ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, 5835274f052SJens Axboe size_t len, unsigned int flags) 5845274f052SJens Axboe { 5855274f052SJens Axboe return move_from_pipe(inode, out, len, flags, pipe_to_sendpage); 5865274f052SJens Axboe } 5875274f052SJens Axboe 588a0f06780SJeff Garzik EXPORT_SYMBOL(generic_file_splice_write); 589a0f06780SJeff Garzik EXPORT_SYMBOL(generic_file_splice_read); 590a0f06780SJeff Garzik 5915274f052SJens Axboe static long do_splice_from(struct inode *pipe, struct file *out, size_t len, 5925274f052SJens Axboe unsigned int flags) 5935274f052SJens Axboe { 5945274f052SJens Axboe loff_t pos; 5955274f052SJens Axboe int ret; 5965274f052SJens Axboe 5975274f052SJens Axboe if (!out->f_op || !out->f_op->splice_write) 5985274f052SJens Axboe return -EINVAL; 5995274f052SJens Axboe 6005274f052SJens Axboe if (!(out->f_mode & FMODE_WRITE)) 6015274f052SJens Axboe return -EBADF; 6025274f052SJens Axboe 6035274f052SJens Axboe pos = out->f_pos; 6045274f052SJens Axboe ret = rw_verify_area(WRITE, out, &pos, len); 6055274f052SJens Axboe if (unlikely(ret < 0)) 6065274f052SJens Axboe return ret; 6075274f052SJens Axboe 6085274f052SJens Axboe return out->f_op->splice_write(pipe, out, len, flags); 6095274f052SJens Axboe } 6105274f052SJens Axboe 6115274f052SJens Axboe static long do_splice_to(struct file *in, struct inode *pipe, size_t len, 6125274f052SJens Axboe unsigned int flags) 6135274f052SJens Axboe { 6145274f052SJens Axboe loff_t pos, isize, left; 6155274f052SJens Axboe int ret; 6165274f052SJens Axboe 6175274f052SJens Axboe if (!in->f_op || !in->f_op->splice_read) 6185274f052SJens Axboe return -EINVAL; 6195274f052SJens Axboe 6205274f052SJens Axboe if (!(in->f_mode & FMODE_READ)) 6215274f052SJens Axboe return -EBADF; 6225274f052SJens Axboe 6235274f052SJens Axboe pos = in->f_pos; 6245274f052SJens Axboe ret = rw_verify_area(READ, in, &pos, len); 6255274f052SJens Axboe if (unlikely(ret < 0)) 6265274f052SJens Axboe return ret; 6275274f052SJens Axboe 6285274f052SJens Axboe isize = i_size_read(in->f_mapping->host); 6295274f052SJens Axboe if (unlikely(in->f_pos >= isize)) 6305274f052SJens Axboe return 0; 6315274f052SJens Axboe 6325274f052SJens Axboe left = isize - in->f_pos; 6335274f052SJens Axboe if (left < len) 6345274f052SJens Axboe len = left; 6355274f052SJens Axboe 6365274f052SJens Axboe return in->f_op->splice_read(in, pipe, len, flags); 6375274f052SJens Axboe } 6385274f052SJens Axboe 6395274f052SJens Axboe static long do_splice(struct file *in, struct file *out, size_t len, 6405274f052SJens Axboe unsigned int flags) 6415274f052SJens Axboe { 6425274f052SJens Axboe struct inode *pipe; 6435274f052SJens Axboe 6445274f052SJens Axboe pipe = in->f_dentry->d_inode; 6455274f052SJens Axboe if (pipe->i_pipe) 6465274f052SJens Axboe return do_splice_from(pipe, out, len, flags); 6475274f052SJens Axboe 6485274f052SJens Axboe pipe = out->f_dentry->d_inode; 6495274f052SJens Axboe if (pipe->i_pipe) 6505274f052SJens Axboe return do_splice_to(in, pipe, len, flags); 6515274f052SJens Axboe 6525274f052SJens Axboe return -EINVAL; 6535274f052SJens Axboe } 6545274f052SJens Axboe 6555274f052SJens Axboe asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags) 6565274f052SJens Axboe { 6575274f052SJens Axboe long error; 6585274f052SJens Axboe struct file *in, *out; 6595274f052SJens Axboe int fput_in, fput_out; 6605274f052SJens Axboe 6615274f052SJens Axboe if (unlikely(!len)) 6625274f052SJens Axboe return 0; 6635274f052SJens Axboe 6645274f052SJens Axboe error = -EBADF; 6655274f052SJens Axboe in = fget_light(fdin, &fput_in); 6665274f052SJens Axboe if (in) { 6675274f052SJens Axboe if (in->f_mode & FMODE_READ) { 6685274f052SJens Axboe out = fget_light(fdout, &fput_out); 6695274f052SJens Axboe if (out) { 6705274f052SJens Axboe if (out->f_mode & FMODE_WRITE) 6715274f052SJens Axboe error = do_splice(in, out, len, flags); 6725274f052SJens Axboe fput_light(out, fput_out); 6735274f052SJens Axboe } 6745274f052SJens Axboe } 6755274f052SJens Axboe 6765274f052SJens Axboe fput_light(in, fput_in); 6775274f052SJens Axboe } 6785274f052SJens Axboe 6795274f052SJens Axboe return error; 6805274f052SJens Axboe } 681