Skip to content

Commit

Permalink
pipe: merge anon_pipe_buf*_ops
Browse files Browse the repository at this point in the history
All the op vectors are exactly the same, they are just used to encode
packet or nomerge behavior.  There already is a flag for the packet
behavior, so just add a new one to allow for merging.  Inverting it vs
the previous nomerge special casing actually allows for much nicer code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Christoph Hellwig authored and Al Viro committed May 20, 2020
1 parent 00c285d commit f6dd975
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 48 deletions.
45 changes: 5 additions & 40 deletions fs/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,48 +231,13 @@ void generic_pipe_buf_release(struct pipe_inode_info *pipe,
}
EXPORT_SYMBOL(generic_pipe_buf_release);

/* New data written to a pipe may be appended to a buffer with this type. */
static const struct pipe_buf_operations anon_pipe_buf_ops = {
.confirm = generic_pipe_buf_confirm,
.release = anon_pipe_buf_release,
.steal = anon_pipe_buf_steal,
.get = generic_pipe_buf_get,
};

static const struct pipe_buf_operations anon_pipe_buf_nomerge_ops = {
.confirm = generic_pipe_buf_confirm,
.release = anon_pipe_buf_release,
.steal = anon_pipe_buf_steal,
.get = generic_pipe_buf_get,
};

static const struct pipe_buf_operations packet_pipe_buf_ops = {
.confirm = generic_pipe_buf_confirm,
.release = anon_pipe_buf_release,
.steal = anon_pipe_buf_steal,
.get = generic_pipe_buf_get,
};

/**
* pipe_buf_mark_unmergeable - mark a &struct pipe_buffer as unmergeable
* @buf: the buffer to mark
*
* Description:
* This function ensures that no future writes will be merged into the
* given &struct pipe_buffer. This is necessary when multiple pipe buffers
* share the same backing page.
*/
void pipe_buf_mark_unmergeable(struct pipe_buffer *buf)
{
if (buf->ops == &anon_pipe_buf_ops)
buf->ops = &anon_pipe_buf_nomerge_ops;
}

static bool pipe_buf_can_merge(struct pipe_buffer *buf)
{
return buf->ops == &anon_pipe_buf_ops;
}

/* Done while waiting without holding the pipe lock - thus the READ_ONCE() */
static inline bool pipe_readable(const struct pipe_inode_info *pipe)
{
Expand Down Expand Up @@ -478,7 +443,8 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
struct pipe_buffer *buf = &pipe->bufs[(head - 1) & mask];
int offset = buf->offset + buf->len;

if (pipe_buf_can_merge(buf) && offset + chars <= PAGE_SIZE) {
if ((buf->flags & PIPE_BUF_FLAG_CAN_MERGE) &&
offset + chars <= PAGE_SIZE) {
ret = pipe_buf_confirm(pipe, buf);
if (ret)
goto out;
Expand Down Expand Up @@ -541,11 +507,10 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
buf->ops = &anon_pipe_buf_ops;
buf->offset = 0;
buf->len = 0;
buf->flags = 0;
if (is_packetized(filp)) {
buf->ops = &packet_pipe_buf_ops;
if (is_packetized(filp))
buf->flags = PIPE_BUF_FLAG_PACKET;
}
else
buf->flags = PIPE_BUF_FLAG_CAN_MERGE;
pipe->tmp_page = NULL;

copied = copy_page_from_iter(page, 0, PAGE_SIZE, from);
Expand Down
12 changes: 5 additions & 7 deletions fs/splice.c
Original file line number Diff line number Diff line change
Expand Up @@ -1624,12 +1624,11 @@ static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe,
*obuf = *ibuf;

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

pipe_buf_mark_unmergeable(obuf);
obuf->flags &= ~PIPE_BUF_FLAG_CAN_MERGE;

obuf->len = len;
ibuf->offset += len;
Expand Down Expand Up @@ -1717,12 +1716,11 @@ static int link_pipe(struct pipe_inode_info *ipipe,
*obuf = *ibuf;

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

pipe_buf_mark_unmergeable(obuf);
obuf->flags &= ~PIPE_BUF_FLAG_CAN_MERGE;

if (obuf->len > len)
obuf->len = len;
Expand Down
2 changes: 1 addition & 1 deletion include/linux/pipe_fs_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
#define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */
#define PIPE_BUF_FLAG_CAN_MERGE 0x10 /* can merge buffers */

/**
* struct pipe_buffer - a linux kernel pipe buffer
Expand Down Expand Up @@ -233,7 +234,6 @@ int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
int generic_pipe_buf_nosteal(struct pipe_inode_info *, struct pipe_buffer *);
void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *);
void pipe_buf_mark_unmergeable(struct pipe_buffer *buf);

extern const struct pipe_buf_operations nosteal_pipe_buf_ops;

Expand Down

0 comments on commit f6dd975

Please sign in to comment.