mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 14:14:24 +08:00
pipe: merge anon_pipe_buf*_ops
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>
This commit is contained in:
parent
00c285d0d0
commit
f6dd975583
45
fs/pipe.c
45
fs/pipe.c
@ -231,7 +231,6 @@ 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,
|
||||
@ -239,40 +238,6 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
|
||||
.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)
|
||||
{
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
12
fs/splice.c
12
fs/splice.c
@ -1624,12 +1624,11 @@ retry:
|
||||
*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;
|
||||
@ -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;
|
||||
|
@ -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
|
||||
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user