Adds one central function which shall be used to initialize a newly allocated struct pipe_buffer. This shall make the pipe code more robust for the next time the pipe_buffer struct gets modified, to avoid leaving new members uninitialized. Instead, adding new members should also add a new pipe_buf_init() parameter, which causes compile-time errors in call sites that were not adapted. This commit doesn't refactor fs/fuse/dev.c because this code looks obscure to me; it initializes pipe_buffers incrementally through a variety of functions, too complicated for me to understand. To: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> To: linux-fsdevel@xxxxxxxxxxxxxxx To: linux-kernel@xxxxxxxxxxxxxxx Signed-off-by: Max Kellermann <max.kellermann@xxxxxxxxx> --- fs/pipe.c | 11 +++-------- fs/splice.c | 9 ++++----- include/linux/pipe_fs_i.h | 20 ++++++++++++++++++++ kernel/watch_queue.c | 8 +++----- lib/iov_iter.c | 13 +++---------- 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index b2075ecd4751..6da11ea9da49 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -518,14 +518,9 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) /* Insert it into the buffer array */ buf = &pipe->bufs[head & mask]; - buf->page = page; - buf->ops = &anon_pipe_buf_ops; - buf->offset = 0; - buf->len = 0; - if (is_packetized(filp)) - buf->flags = PIPE_BUF_FLAG_PACKET; - else - buf->flags = PIPE_BUF_FLAG_CAN_MERGE; + pipe_buf_init(buf, page, 0, 0, + &anon_pipe_buf_ops, + is_packetized(filp) ? PIPE_BUF_FLAG_PACKET : PIPE_BUF_FLAG_CAN_MERGE); pipe->tmp_page = NULL; copied = copy_page_from_iter(page, 0, PAGE_SIZE, from); diff --git a/fs/splice.c b/fs/splice.c index 5dbce4dcc1a7..d2e4205acc46 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -200,12 +200,11 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe, while (!pipe_full(head, tail, pipe->max_usage)) { struct pipe_buffer *buf = &pipe->bufs[head & mask]; - buf->page = spd->pages[page_nr]; - buf->offset = spd->partial[page_nr].offset; - buf->len = spd->partial[page_nr].len; + pipe_buf_init(buf, spd->pages[page_nr], + spd->partial[page_nr].offset, + spd->partial[page_nr].len, + spd->ops, 0); buf->private = spd->partial[page_nr].private; - buf->ops = spd->ops; - buf->flags = 0; head++; pipe->head = head; diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 0e36a58adf0e..61639682cc4e 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -179,6 +179,26 @@ static inline unsigned int pipe_space_for_user(unsigned int head, unsigned int t return p_space; } +/** + * Initialize a struct pipe_buffer. + */ +static inline void pipe_buf_init(struct pipe_buffer *buf, + struct page *page, + unsigned int offset, unsigned int len, + const struct pipe_buf_operations *ops, + unsigned int flags) +{ + buf->page = page; + buf->offset = offset; + buf->len = len; + buf->ops = ops; + buf->flags = flags; + + /* not initializing the "private" member because it is only + used by pipe_buf_operations which inject it via struct + partial_page / struct splice_pipe_desc */ +} + /** * pipe_buf_get - get a reference to a pipe_buffer * @pipe: the pipe that the buffer belongs to diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c index 9c9eb20dd2c5..34720138cc22 100644 --- a/kernel/watch_queue.c +++ b/kernel/watch_queue.c @@ -106,12 +106,10 @@ static bool post_one_notification(struct watch_queue *wqueue, kunmap_atomic(p); buf = &pipe->bufs[head & mask]; - buf->page = page; + pipe_buf_init(buf, page, offset, len, + &watch_queue_pipe_buf_ops, + PIPE_BUF_FLAG_WHOLE); buf->private = (unsigned long)wqueue; - buf->ops = &watch_queue_pipe_buf_ops; - buf->offset = offset; - buf->len = len; - buf->flags = PIPE_BUF_FLAG_WHOLE; pipe->head = head + 1; if (!test_and_clear_bit(note, wqueue->notes_bitmap)) { diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 6dd5330f7a99..289e96947fb5 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -413,12 +413,8 @@ static size_t copy_page_to_iter_pipe(struct page *page, size_t offset, size_t by if (pipe_full(i_head, p_tail, pipe->max_usage)) return 0; - buf->ops = &page_cache_pipe_buf_ops; - buf->flags = 0; get_page(page); - buf->page = page; - buf->offset = offset; - buf->len = bytes; + pipe_buf_init(buf, page, offset, bytes, &page_cache_pipe_buf_ops, 0); pipe->head = i_head + 1; i->iov_offset = offset + bytes; @@ -577,11 +573,8 @@ static size_t push_pipe(struct iov_iter *i, size_t size, if (!page) break; - buf->ops = &default_pipe_buf_ops; - buf->flags = 0; - buf->page = page; - buf->offset = 0; - buf->len = min_t(ssize_t, left, PAGE_SIZE); + pipe_buf_init(buf, page, 0, min_t(ssize_t, left, PAGE_SIZE), + &default_pipe_buf_ops, 0); left -= buf->len; iter_head++; pipe->head = iter_head; -- 2.34.0