All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jaegeuk Kim via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: Christoph Hellwig <hch@infradead.org>
Cc: linux-kernel@vger.kernel.org,
	Matthew Wilcox <willy@infradead.org>,
	linux-f2fs-devel@lists.sourceforge.net, linux-mm@kvack.org,
	linux-fsdevel@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [f2fs-dev] [PATCH 1/2] f2fs: improve readahead for POSIX_FADV_WILLNEED
Date: Fri, 21 Nov 2025 18:05:01 +0000	[thread overview]
Message-ID: <aSCpzRW8mUhNnjHB@google.com> (raw)
In-Reply-To: <aSALfvLUObUGSx-e@infradead.org>

On 11/20, Christoph Hellwig wrote:
> On Fri, Nov 21, 2025 at 01:42:01AM +0000, Jaegeuk Kim wrote:
> > This patch boosts readahead for POSIX_FADV_WILLNEED.
> 
> How?  That's not a good changelog.
> 
> Also open coding the read-ahead logic is not a good idea.  The only
> f2fs-specific bits are the compression check, and the extent precaching,
> but you surely should be able to share a read-ahead helper with common
> code instead of duplicating the logic.

Ok, let me try to write up and post a generic version of the changes.

> 
> > 
> > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> > ---
> >  fs/f2fs/data.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  fs/f2fs/f2fs.h |  1 +
> >  fs/f2fs/file.c |  9 +++++---
> >  3 files changed, 68 insertions(+), 3 deletions(-)
> > 
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index a0433c8a4d84..d95974d79fb3 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -2710,6 +2710,67 @@ static void f2fs_readahead(struct readahead_control *rac)
> >  	f2fs_mpage_readpages(inode, rac, NULL);
> >  }
> >  
> > +int f2fs_readahead_pages(struct file *file, loff_t offset, loff_t len)
> > +{
> > +	struct inode *inode = file_inode(file);
> > +	struct address_space *mapping = file->f_mapping;
> > +	pgoff_t start_index = offset >> PAGE_SHIFT;
> > +	loff_t endbyte = offset + len;
> > +	pgoff_t end_index;
> > +	unsigned long nrpages;
> > +	unsigned long ra_pages = (16 * 1024 * 1024) / PAGE_SIZE;
> > +	DEFINE_READAHEAD(ractl, NULL, &file->f_ra, mapping, start_index);
> > +
> > +	if (!S_ISREG(inode->i_mode))
> > +		return -EOPNOTSUPP;
> > +
> > +	/* Should be read only. */
> > +	if (!(file->f_mode & FMODE_READ))
> > +		return -EBADF;
> > +
> > +	/* Do not support compressed file for large folio. */
> > +	if (f2fs_compressed_file(inode))
> > +		return -EINVAL;
> > +
> > +	if (!mapping || len < 0)
> > +		return -EINVAL;
> > +
> > +	if (unlikely(!mapping->a_ops->read_folio && !mapping->a_ops->readahead))
> > +		return -EINVAL;
> > +
> > +	/* Load extent cache at the first readahead. */
> > +	f2fs_precache_extents(inode);
> > +
> > +	/*
> > +	 * Careful about overflows. Len == 0 means "as much as possible".  Use
> > +	 * unsigned math because signed overflows are undefined and UBSan
> > +	 * complains.
> > +	 */
> > +	if (!len || endbyte > i_size_read(inode) || endbyte < len)
> > +		endbyte = i_size_read(inode) - 1;
> > +	else
> > +		endbyte--;		/* inclusive */
> > +
> > +	/* First and last PARTIAL page! */
> > +	end_index = endbyte >> PAGE_SHIFT;
> > +
> > +	if (start_index > end_index)
> > +		return 0;
> > +
> > +	nrpages = end_index - start_index + 1;
> > +
> > +	while (nrpages) {
> > +		unsigned long this_chunk = min(nrpages, ra_pages);
> > +
> > +		ractl.ra->ra_pages = this_chunk;
> > +
> > +		page_cache_sync_ra(&ractl, this_chunk << 1);
> > +
> > +		nrpages -= this_chunk;
> > +	}
> > +	return 0;
> > +}
> > +
> >  int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
> >  {
> >  	struct inode *inode = fio_inode(fio);
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index 3340db04a7c2..934287cc5624 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -4047,6 +4047,7 @@ int f2fs_init_bio_entry_cache(void);
> >  void f2fs_destroy_bio_entry_cache(void);
> >  void f2fs_submit_read_bio(struct f2fs_sb_info *sbi, struct bio *bio,
> >  			  enum page_type type);
> > +int f2fs_readahead_pages(struct file *file, loff_t offset, loff_t len);
> >  int f2fs_init_write_merge_io(struct f2fs_sb_info *sbi);
> >  void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type);
> >  void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> > index d7047ca6b98d..b6f71efd6d2a 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -5305,9 +5305,12 @@ static int f2fs_file_fadvise(struct file *filp, loff_t offset, loff_t len,
> >  		filp->f_mode &= ~FMODE_RANDOM;
> >  		spin_unlock(&filp->f_lock);
> >  		return 0;
> > -	} else if (advice == POSIX_FADV_WILLNEED && offset == 0) {
> > -		/* Load extent cache at the first readahead. */
> > -		f2fs_precache_extents(inode);
> > +	} else if (advice == POSIX_FADV_WILLNEED) {
> > +		if (offset == 0 && len == -1) {
> > +			f2fs_precache_extents(inode);
> > +			return 0;
> > +		}
> > +		return f2fs_readahead_pages(filp, offset, len);
> >  	}
> >  
> >  	err = generic_fadvise(filp, offset, len, advice);
> > -- 
> > 2.52.0.487.g5c8c507ade-goog
> > 
> > 
> ---end quoted text---


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

WARNING: multiple messages have this Message-ID (diff)
From: Jaegeuk Kim <jaegeuk@kernel.org>
To: Christoph Hellwig <hch@infradead.org>
Cc: linux-kernel@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net,
	Matthew Wilcox <willy@infradead.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	linux-fsdevel@vger.kernel.org, linux-mm@kvack.org
Subject: Re: [PATCH 1/2] f2fs: improve readahead for POSIX_FADV_WILLNEED
Date: Fri, 21 Nov 2025 18:05:01 +0000	[thread overview]
Message-ID: <aSCpzRW8mUhNnjHB@google.com> (raw)
In-Reply-To: <aSALfvLUObUGSx-e@infradead.org>

On 11/20, Christoph Hellwig wrote:
> On Fri, Nov 21, 2025 at 01:42:01AM +0000, Jaegeuk Kim wrote:
> > This patch boosts readahead for POSIX_FADV_WILLNEED.
> 
> How?  That's not a good changelog.
> 
> Also open coding the read-ahead logic is not a good idea.  The only
> f2fs-specific bits are the compression check, and the extent precaching,
> but you surely should be able to share a read-ahead helper with common
> code instead of duplicating the logic.

Ok, let me try to write up and post a generic version of the changes.

> 
> > 
> > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> > ---
> >  fs/f2fs/data.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  fs/f2fs/f2fs.h |  1 +
> >  fs/f2fs/file.c |  9 +++++---
> >  3 files changed, 68 insertions(+), 3 deletions(-)
> > 
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index a0433c8a4d84..d95974d79fb3 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -2710,6 +2710,67 @@ static void f2fs_readahead(struct readahead_control *rac)
> >  	f2fs_mpage_readpages(inode, rac, NULL);
> >  }
> >  
> > +int f2fs_readahead_pages(struct file *file, loff_t offset, loff_t len)
> > +{
> > +	struct inode *inode = file_inode(file);
> > +	struct address_space *mapping = file->f_mapping;
> > +	pgoff_t start_index = offset >> PAGE_SHIFT;
> > +	loff_t endbyte = offset + len;
> > +	pgoff_t end_index;
> > +	unsigned long nrpages;
> > +	unsigned long ra_pages = (16 * 1024 * 1024) / PAGE_SIZE;
> > +	DEFINE_READAHEAD(ractl, NULL, &file->f_ra, mapping, start_index);
> > +
> > +	if (!S_ISREG(inode->i_mode))
> > +		return -EOPNOTSUPP;
> > +
> > +	/* Should be read only. */
> > +	if (!(file->f_mode & FMODE_READ))
> > +		return -EBADF;
> > +
> > +	/* Do not support compressed file for large folio. */
> > +	if (f2fs_compressed_file(inode))
> > +		return -EINVAL;
> > +
> > +	if (!mapping || len < 0)
> > +		return -EINVAL;
> > +
> > +	if (unlikely(!mapping->a_ops->read_folio && !mapping->a_ops->readahead))
> > +		return -EINVAL;
> > +
> > +	/* Load extent cache at the first readahead. */
> > +	f2fs_precache_extents(inode);
> > +
> > +	/*
> > +	 * Careful about overflows. Len == 0 means "as much as possible".  Use
> > +	 * unsigned math because signed overflows are undefined and UBSan
> > +	 * complains.
> > +	 */
> > +	if (!len || endbyte > i_size_read(inode) || endbyte < len)
> > +		endbyte = i_size_read(inode) - 1;
> > +	else
> > +		endbyte--;		/* inclusive */
> > +
> > +	/* First and last PARTIAL page! */
> > +	end_index = endbyte >> PAGE_SHIFT;
> > +
> > +	if (start_index > end_index)
> > +		return 0;
> > +
> > +	nrpages = end_index - start_index + 1;
> > +
> > +	while (nrpages) {
> > +		unsigned long this_chunk = min(nrpages, ra_pages);
> > +
> > +		ractl.ra->ra_pages = this_chunk;
> > +
> > +		page_cache_sync_ra(&ractl, this_chunk << 1);
> > +
> > +		nrpages -= this_chunk;
> > +	}
> > +	return 0;
> > +}
> > +
> >  int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
> >  {
> >  	struct inode *inode = fio_inode(fio);
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index 3340db04a7c2..934287cc5624 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -4047,6 +4047,7 @@ int f2fs_init_bio_entry_cache(void);
> >  void f2fs_destroy_bio_entry_cache(void);
> >  void f2fs_submit_read_bio(struct f2fs_sb_info *sbi, struct bio *bio,
> >  			  enum page_type type);
> > +int f2fs_readahead_pages(struct file *file, loff_t offset, loff_t len);
> >  int f2fs_init_write_merge_io(struct f2fs_sb_info *sbi);
> >  void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type);
> >  void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> > index d7047ca6b98d..b6f71efd6d2a 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -5305,9 +5305,12 @@ static int f2fs_file_fadvise(struct file *filp, loff_t offset, loff_t len,
> >  		filp->f_mode &= ~FMODE_RANDOM;
> >  		spin_unlock(&filp->f_lock);
> >  		return 0;
> > -	} else if (advice == POSIX_FADV_WILLNEED && offset == 0) {
> > -		/* Load extent cache at the first readahead. */
> > -		f2fs_precache_extents(inode);
> > +	} else if (advice == POSIX_FADV_WILLNEED) {
> > +		if (offset == 0 && len == -1) {
> > +			f2fs_precache_extents(inode);
> > +			return 0;
> > +		}
> > +		return f2fs_readahead_pages(filp, offset, len);
> >  	}
> >  
> >  	err = generic_fadvise(filp, offset, len, advice);
> > -- 
> > 2.52.0.487.g5c8c507ade-goog
> > 
> > 
> ---end quoted text---


  reply	other threads:[~2025-11-21 18:05 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-21  1:42 [f2fs-dev] [PATCH 1/2] f2fs: improve readahead for POSIX_FADV_WILLNEED Jaegeuk Kim via Linux-f2fs-devel
2025-11-21  1:42 ` Jaegeuk Kim
2025-11-21  1:42 ` [f2fs-dev] [PATCH 2/2] f2fs: add a tracepoint for readahead pages Jaegeuk Kim via Linux-f2fs-devel
2025-11-21  1:42   ` Jaegeuk Kim
2025-11-21  6:49 ` [f2fs-dev] [PATCH 1/2] f2fs: improve readahead for POSIX_FADV_WILLNEED Christoph Hellwig
2025-11-21  6:49   ` Christoph Hellwig
2025-11-21 18:05   ` Jaegeuk Kim via Linux-f2fs-devel [this message]
2025-11-21 18:05     ` Jaegeuk Kim
2026-01-22  8:34     ` [f2fs-dev] " Christoph Hellwig
2026-01-22  8:34       ` Christoph Hellwig
2026-01-22 23:26       ` [f2fs-dev] " Jaegeuk Kim via Linux-f2fs-devel
2026-01-22 23:26         ` Jaegeuk Kim

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=aSCpzRW8mUhNnjHB@google.com \
    --to=linux-f2fs-devel@lists.sourceforge.net \
    --cc=akpm@linux-foundation.org \
    --cc=hch@infradead.org \
    --cc=jaegeuk@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --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.