Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 26440
b: refs/heads/master
c: 7afa6fd
h: refs/heads/master
v: v3
  • Loading branch information
Jens Axboe committed May 1, 2006
1 parent a0d457a commit 8f52e81
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f6762b7ad8edd6abc802542ce845d3bc8adcb92f
refs/heads/master: 7afa6fd037e51e95d322990cb127bb2b1217251a
28 changes: 25 additions & 3 deletions trunk/fs/splice.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = {
static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
return 1;
if (!(buf->flags & PIPE_BUF_FLAG_GIFT))
return 1;

return 0;
}

static struct pipe_buf_operations user_page_pipe_buf_ops = {
Expand Down Expand Up @@ -186,6 +189,9 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
buf->offset = spd->partial[page_nr].offset;
buf->len = spd->partial[page_nr].len;
buf->ops = spd->ops;
if (spd->flags & SPLICE_F_GIFT)
buf->flags |= PIPE_BUF_FLAG_GIFT;

pipe->nrbufs++;
page_nr++;
ret += buf->len;
Expand Down Expand Up @@ -1073,7 +1079,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
*/
static int get_iovec_page_array(const struct iovec __user *iov,
unsigned int nr_vecs, struct page **pages,
struct partial_page *partial)
struct partial_page *partial, int aligned)
{
int buffers = 0, error = 0;

Expand Down Expand Up @@ -1113,6 +1119,15 @@ static int get_iovec_page_array(const struct iovec __user *iov,
* in the user pages.
*/
off = (unsigned long) base & ~PAGE_MASK;

/*
* If asked for alignment, the offset must be zero and the
* length a multiple of the PAGE_SIZE.
*/
error = -EINVAL;
if (aligned && (off || len & ~PAGE_MASK))
break;

npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (npages > PIPE_BUFFERS - buffers)
npages = PIPE_BUFFERS - buffers;
Expand Down Expand Up @@ -1206,7 +1221,8 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
else if (unlikely(!nr_segs))
return 0;

spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial);
spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
flags & SPLICE_F_GIFT);
if (spd.nr_pages <= 0)
return spd.nr_pages;

Expand Down Expand Up @@ -1314,6 +1330,12 @@ static int link_pipe(struct pipe_inode_info *ipipe,
obuf = opipe->bufs + nbuf;
*obuf = *ibuf;

/*
* Don't inherit the gift flag, we need to
* prevent multiple steals of this page.
*/
obuf->flags &= ~PIPE_BUF_FLAG_GIFT;

if (obuf->len > len)
obuf->len = len;

Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/pipe_fs_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */
#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */

struct pipe_buffer {
struct page *page;
Expand Down Expand Up @@ -79,6 +80,7 @@ int generic_pipe_buf_pin(struct pipe_inode_info *, struct pipe_buffer *);
/* we may still block on the fd we splice */
/* from/to, of course */
#define SPLICE_F_MORE (0x04) /* expect more data */
#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */

/*
* Passed to the actors
Expand Down

0 comments on commit 8f52e81

Please sign in to comment.