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: 50+ 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-14 17:24 ` Mezgani Ali
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 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:01 ` David Howells
2023-02-14 23:01 ` David Howells
2023-02-14 23:05 ` Jens Axboe
2023-02-15 8:07 ` David Howells
2023-02-15 8:20 ` David Howells
2023-02-15 14:23 ` Christoph Hellwig
2023-02-15 14:38 ` Christoph Hellwig
2023-02-15 15:43 ` 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.