From: Ming Lei <ming.lei@redhat.com>
To: David Howells <dhowells@redhat.com>
Cc: Jens Axboe <axboe@kernel.dk>, Al Viro <viro@zeniv.linux.org.uk>,
Christoph Hellwig <hch@infradead.org>,
Matthew Wilcox <willy@infradead.org>, Jan Kara <jack@suse.cz>,
Jeff Layton <jlayton@kernel.org>,
David Hildenbrand <david@redhat.com>,
Jason Gunthorpe <jgg@nvidia.com>,
Logan Gunthorpe <logang@deltatee.com>,
Hillf Danton <hdanton@sina.com>,
linux-fsdevel@vger.kernel.org, linux-block@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
Christoph Hellwig <hch@lst.de>,
John Hubbard <jhubbard@nvidia.com>,
ming.lei@redhat.com
Subject: Re: [PATCH v14 02/17] splice: Add a func to do a splice from a buffered file without ITER_PIPE
Date: Sat, 18 Feb 2023 10:41:49 +0800 [thread overview]
Message-ID: <Y/A67a6LovSYHhHz@T590> (raw)
In-Reply-To: <20230214171330.2722188-3-dhowells@redhat.com>
On Tue, Feb 14, 2023 at 05:13:15PM +0000, David Howells wrote:
> Provide a function to do splice read from a buffered file, pulling the
> folios out of the pagecache directly by calling filemap_get_pages() to do
> any required reading and then pasting the returned folios into the pipe.
>
> A helper function is provided to do the actual folio pasting and will
> handle multipage folios by splicing as many of the relevant subpages as
> will fit into the pipe.
>
> The code is loosely based on filemap_read() and might belong in
> mm/filemap.c with that as it needs to use filemap_get_pages().
>
> Signed-off-by: David Howells <dhowells@redhat.com>
> cc: Jens Axboe <axboe@kernel.dk>
> cc: Christoph Hellwig <hch@lst.de>
> cc: Al Viro <viro@zeniv.linux.org.uk>
> cc: David Hildenbrand <david@redhat.com>
> cc: John Hubbard <jhubbard@nvidia.com>
> cc: linux-mm@kvack.org
> cc: linux-block@vger.kernel.org
> cc: linux-fsdevel@vger.kernel.org
> ---
>
> Notes:
> ver #14)
> - Rename to filemap_splice_read().
> - Create a helper, pipe_head_buf(), to get the head buffer.
> - Use init_sync_kiocb().
> - Move to mm/filemap.c.
> - Split the implementation of filemap_splice_read() from the patch to
> make generic_file_splice_read() use it and direct_splice_read().
>
> include/linux/fs.h | 3 ++
> mm/filemap.c | 128 +++++++++++++++++++++++++++++++++++++++++++++
> mm/internal.h | 6 +++
> 3 files changed, 137 insertions(+)
>
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index c1769a2c5d70..28743e38df91 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3163,6 +3163,9 @@ ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
> struct iov_iter *iter);
>
> /* fs/splice.c */
> +ssize_t filemap_splice_read(struct file *in, loff_t *ppos,
> + struct pipe_inode_info *pipe,
> + size_t len, unsigned int flags);
> extern ssize_t generic_file_splice_read(struct file *, loff_t *,
> struct pipe_inode_info *, size_t, unsigned int);
> extern ssize_t iter_file_splice_write(struct pipe_inode_info *,
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 876e77278d2a..8c7b135c8e23 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -42,6 +42,8 @@
> #include <linux/ramfs.h>
> #include <linux/page_idle.h>
> #include <linux/migrate.h>
> +#include <linux/pipe_fs_i.h>
> +#include <linux/splice.h>
> #include <asm/pgalloc.h>
> #include <asm/tlbflush.h>
> #include "internal.h"
> @@ -2842,6 +2844,132 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
> }
> EXPORT_SYMBOL(generic_file_read_iter);
>
> +/*
> + * Splice subpages from a folio into a pipe.
> + */
> +size_t splice_folio_into_pipe(struct pipe_inode_info *pipe,
> + struct folio *folio, loff_t fpos, size_t size)
> +{
> + struct page *page;
> + size_t spliced = 0, offset = offset_in_folio(folio, fpos);
> +
> + page = folio_page(folio, offset / PAGE_SIZE);
> + size = min(size, folio_size(folio) - offset);
> + offset %= PAGE_SIZE;
> +
> + while (spliced < size &&
> + !pipe_full(pipe->head, pipe->tail, pipe->max_usage)) {
> + struct pipe_buffer *buf = pipe_head_buf(pipe);
> + size_t part = min_t(size_t, PAGE_SIZE - offset, size - spliced);
> +
> + *buf = (struct pipe_buffer) {
> + .ops = &page_cache_pipe_buf_ops,
> + .page = page,
> + .offset = offset,
> + .len = part,
> + };
> + folio_get(folio);
> + pipe->head++;
> + page++;
> + spliced += part;
> + offset = 0;
It should be better to replace above with add_to_pipe().
> + }
> +
> + return spliced;
> +}
> +
> +/*
> + * Splice folios from the pagecache of a buffered (ie. non-O_DIRECT) file into
> + * a pipe.
> + */
> +ssize_t filemap_splice_read(struct file *in, loff_t *ppos,
> + struct pipe_inode_info *pipe,
> + size_t len, unsigned int flags)
> +{
> + struct folio_batch fbatch;
> + struct kiocb iocb;
> + size_t total_spliced = 0, used, npages;
> + loff_t isize, end_offset;
> + bool writably_mapped;
> + int i, error = 0;
> +
> + init_sync_kiocb(&iocb, in);
> + iocb.ki_pos = *ppos;
> +
> + /* Work out how much data we can actually add into the pipe */
> + used = pipe_occupancy(pipe->head, pipe->tail);
> + npages = max_t(ssize_t, pipe->max_usage - used, 0);
> + len = min_t(size_t, len, npages * PAGE_SIZE);
Do we need to consider offset in 1st page here?
thanks,
Ming
next prev parent reply other threads:[~2023-02-18 2:43 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-14 17:13 [PATCH v14 00/17] iov_iter: Improve page extraction (pin or just list) David Howells
2023-02-14 17:13 ` [PATCH v14 01/17] mm: Pass info, not iter, into filemap_get_pages() David Howells
2023-02-14 17:13 ` [PATCH v14 02/17] splice: Add a func to do a splice from a buffered file without ITER_PIPE David Howells
2023-02-18 2:41 ` Ming Lei [this message]
2023-02-18 9:25 ` David Howells
2023-02-14 17:13 ` [PATCH v14 03/17] splice: Add a func to do a splice from an O_DIRECT " David Howells
2023-02-14 17:13 ` [PATCH v14 04/17] shmem: Implement splice-read David Howells
2023-02-14 17:13 ` [PATCH v14 05/17] overlayfs: " David Howells
2023-02-15 14:21 ` Miklos Szeredi
2023-02-15 15:03 ` David Howells
2023-02-15 15:32 ` Miklos Szeredi
2023-02-15 15:40 ` [PATCH v15 " David Howells
2023-02-15 15:50 ` Miklos Szeredi
2023-02-15 15:53 ` Matthew Wilcox
2023-02-15 16:38 ` Christoph Hellwig
2023-02-15 16:40 ` Miklos Szeredi
2023-02-15 15:58 ` David Howells
2023-02-14 17:13 ` [PATCH v14 06/17] coda: " David Howells
2023-02-14 18:04 ` Jan Harkes
2023-02-14 17:13 ` [PATCH v14 07/17] tty, proc, kernfs, random: Use direct_splice_read() David Howells
2023-02-14 17:13 ` [PATCH v14 08/17] splice: Do splice read from a file without using ITER_PIPE David Howells
2023-02-17 8:22 ` Ming Lei
2023-02-17 9:18 ` Ming Lei
2023-02-17 20:39 ` Alexander Egorenkov
2023-02-17 20:59 ` egorenar
2023-02-17 21:24 ` David Howells
2023-02-17 21:16 ` David Howells
2023-02-17 21:47 ` David Howells
2023-02-18 8:29 ` Alexander Egorenkov
2023-02-18 9:18 ` David Howells
2023-02-14 17:13 ` [PATCH v14 09/17] iov_iter: Kill ITER_PIPE David Howells
2023-02-14 17:13 ` [PATCH v14 10/17] iov_iter: Define flags to qualify page extraction David Howells
2023-02-14 17:13 ` [PATCH v14 11/17] iov_iter: Add a function to extract a page list from an iterator David Howells
2023-02-14 17:13 ` [PATCH v14 12/17] iomap: Don't get an reference on ZERO_PAGE for direct I/O block zeroing David Howells
2023-02-14 17:13 ` [PATCH v14 13/17] block: Fix bio_flagged() so that gcc can better optimise it David Howells
2023-02-14 17:13 ` [PATCH v14 14/17] block: Replace BIO_NO_PAGE_REF with BIO_PAGE_REFFED with inverted logic David Howells
2023-02-14 17:13 ` [PATCH v14 15/17] block: Add BIO_PAGE_PINNED and associated infrastructure David Howells
2023-02-14 17:13 ` [PATCH v14 16/17] block: Convert bio_iov_iter_get_pages to use iov_iter_extract_pages David Howells
2023-02-14 17:13 ` [PATCH v14 17/17] block: convert bio_map_user_iov " David Howells
2023-02-14 22:56 ` [PATCH v14 00/17] iov_iter: Improve page extraction (pin or just list) David Howells
2023-02-14 23:05 ` Jens Axboe
2023-02-15 8:07 ` David Howells
2023-02-15 14:23 ` Christoph Hellwig
2023-02-15 14:38 ` Christoph Hellwig
2023-02-15 15:43 ` David Howells
2023-02-15 8:20 ` David Howells
2023-02-14 23:01 ` David Howells
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y/A67a6LovSYHhHz@T590 \
--to=ming.lei@redhat.com \
--cc=axboe@kernel.dk \
--cc=david@redhat.com \
--cc=dhowells@redhat.com \
--cc=hch@infradead.org \
--cc=hch@lst.de \
--cc=hdanton@sina.com \
--cc=jack@suse.cz \
--cc=jgg@nvidia.com \
--cc=jhubbard@nvidia.com \
--cc=jlayton@kernel.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=logang@deltatee.com \
--cc=viro@zeniv.linux.org.uk \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).