@@ -1434,106 +1434,32 @@ static long do_splice(struct file *in, loff_t __user *off_in,
14341434 return - EINVAL ;
14351435}
14361436
1437- /*
1438- * Map an iov into an array of pages and offset/length tupples. With the
1439- * partial_page structure, we can map several non-contiguous ranges into
1440- * our ones pages[] map instead of splitting that operation into pieces.
1441- * Could easily be exported as a generic helper for other users, in which
1442- * case one would probably want to add a 'max_nr_pages' parameter as well.
1443- */
1444- static int get_iovec_page_array (const struct iovec __user * iov ,
1445- unsigned int nr_vecs , struct page * * pages ,
1446- struct partial_page * partial , bool aligned ,
1437+ static int get_iovec_page_array (struct iov_iter * from ,
1438+ struct page * * pages ,
1439+ struct partial_page * partial ,
14471440 unsigned int pipe_buffers )
14481441{
1449- int buffers = 0 , error = 0 ;
1450-
1451- while (nr_vecs ) {
1452- unsigned long off , npages ;
1453- struct iovec entry ;
1454- void __user * base ;
1455- size_t len ;
1456- int i ;
1457-
1458- error = - EFAULT ;
1459- if (copy_from_user (& entry , iov , sizeof (entry )))
1460- break ;
1461-
1462- base = entry .iov_base ;
1463- len = entry .iov_len ;
1464-
1465- /*
1466- * Sanity check this iovec. 0 read succeeds.
1467- */
1468- error = 0 ;
1469- if (unlikely (!len ))
1470- break ;
1471- error = - EFAULT ;
1472- if (!access_ok (VERIFY_READ , base , len ))
1473- break ;
1474-
1475- /*
1476- * Get this base offset and number of pages, then map
1477- * in the user pages.
1478- */
1479- off = (unsigned long ) base & ~PAGE_MASK ;
1480-
1481- /*
1482- * If asked for alignment, the offset must be zero and the
1483- * length a multiple of the PAGE_SIZE.
1484- */
1485- error = - EINVAL ;
1486- if (aligned && (off || len & ~PAGE_MASK ))
1487- break ;
1488-
1489- npages = (off + len + PAGE_SIZE - 1 ) >> PAGE_SHIFT ;
1490- if (npages > pipe_buffers - buffers )
1491- npages = pipe_buffers - buffers ;
1492-
1493- error = get_user_pages_fast ((unsigned long )base , npages ,
1494- 0 , & pages [buffers ]);
1495-
1496- if (unlikely (error <= 0 ))
1497- break ;
1498-
1499- /*
1500- * Fill this contiguous range into the partial page map.
1501- */
1502- for (i = 0 ; i < error ; i ++ ) {
1503- const int plen = min_t (size_t , len , PAGE_SIZE - off );
1504-
1505- partial [buffers ].offset = off ;
1506- partial [buffers ].len = plen ;
1507-
1508- off = 0 ;
1509- len -= plen ;
1442+ int buffers = 0 ;
1443+ while (iov_iter_count (from )) {
1444+ ssize_t copied ;
1445+ size_t start ;
1446+
1447+ copied = iov_iter_get_pages (from , pages + buffers , ~0UL ,
1448+ pipe_buffers - buffers , & start );
1449+ if (copied <= 0 )
1450+ return buffers ? buffers : copied ;
1451+
1452+ iov_iter_advance (from , copied );
1453+ while (copied ) {
1454+ int size = min_t (int , copied , PAGE_SIZE - start );
1455+ partial [buffers ].offset = start ;
1456+ partial [buffers ].len = size ;
1457+ copied -= size ;
1458+ start = 0 ;
15101459 buffers ++ ;
15111460 }
1512-
1513- /*
1514- * We didn't complete this iov, stop here since it probably
1515- * means we have to move some of this into a pipe to
1516- * be able to continue.
1517- */
1518- if (len )
1519- break ;
1520-
1521- /*
1522- * Don't continue if we mapped fewer pages than we asked for,
1523- * or if we mapped the max number of pages that we have
1524- * room for.
1525- */
1526- if (error < npages || buffers == pipe_buffers )
1527- break ;
1528-
1529- nr_vecs -- ;
1530- iov ++ ;
15311461 }
1532-
1533- if (buffers )
1534- return buffers ;
1535-
1536- return error ;
1462+ return buffers ;
15371463}
15381464
15391465static int pipe_to_user (struct pipe_inode_info * pipe , struct pipe_buffer * buf ,
@@ -1587,10 +1513,13 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
15871513 * as splice-from-memory, where the regular splice is splice-from-file (or
15881514 * to file). In both cases the output is a pipe, naturally.
15891515 */
1590- static long vmsplice_to_pipe (struct file * file , const struct iovec __user * iov ,
1516+ static long vmsplice_to_pipe (struct file * file , const struct iovec __user * uiov ,
15911517 unsigned long nr_segs , unsigned int flags )
15921518{
15931519 struct pipe_inode_info * pipe ;
1520+ struct iovec iovstack [UIO_FASTIOV ];
1521+ struct iovec * iov = iovstack ;
1522+ struct iov_iter from ;
15941523 struct page * pages [PIPE_DEF_BUFFERS ];
15951524 struct partial_page partial [PIPE_DEF_BUFFERS ];
15961525 struct splice_pipe_desc spd = {
@@ -1607,18 +1536,26 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
16071536 if (!pipe )
16081537 return - EBADF ;
16091538
1610- if (splice_grow_spd (pipe , & spd ))
1539+ ret = import_iovec (WRITE , uiov , nr_segs ,
1540+ ARRAY_SIZE (iovstack ), & iov , & from );
1541+ if (ret < 0 )
1542+ return ret ;
1543+
1544+ if (splice_grow_spd (pipe , & spd )) {
1545+ kfree (iov );
16111546 return - ENOMEM ;
1547+ }
16121548
1613- spd .nr_pages = get_iovec_page_array (iov , nr_segs , spd .pages ,
1614- spd .partial , false,
1549+ spd .nr_pages = get_iovec_page_array (& from , spd .pages ,
1550+ spd .partial ,
16151551 spd .nr_pages_max );
16161552 if (spd .nr_pages <= 0 )
16171553 ret = spd .nr_pages ;
16181554 else
16191555 ret = splice_to_pipe (pipe , & spd );
16201556
16211557 splice_shrink_spd (& spd );
1558+ kfree (iov );
16221559 return ret ;
16231560}
16241561
0 commit comments