All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jaegeuk Kim via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: Chao Yu <chao@kernel.org>
Cc: Yongpeng Yang <yangyongpeng@xiaomi.com>,
	Yongpeng Yang <monty_pavel@sina.com>,
	Yongpeng Yang <yangyongpeng.storage@gmail.com>,
	linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH RESEND 5/5] f2fs: add ioctl to export read extent cache to userspace for debug
Date: Mon, 15 Jun 2026 15:51:52 +0000	[thread overview]
Message-ID: <ajAfmEHCgHAh1E0I@google.com> (raw)
In-Reply-To: <8738e84f-6fef-479d-a100-7df0e130f75a@kernel.org>

On 06/15, Chao Yu via Linux-f2fs-devel wrote:
> On 6/12/26 19:58, Yongpeng Yang wrote:
> > From: Yongpeng Yang <yangyongpeng@xiaomi.com>
> > 
> > Add F2FS_IOC_GET_READ_CACHE_EXTENTS ioctl that allows userspace to
> > retrieve all cached read extents for a given file. This uses a two-call
> > pattern similar to fiemap: the first call with ext_count=0 queries the
> > node_count, and the second call fetches the actual extent entries.
> 
> It looks a little bit heavy to maintain a debug purpose ioctl interface.
> 
> Maybe set ino via sysfs and dump extent cache via procfs? only enabled
> if F2FS_CHECK_FS=y?
> 
> Jaegeuk, do you have any suggestion?

Agreed, and even not sure we need sysfs or procfs. Can we dump the extents
via fsck?

> 
> Thanks,
> 
> > 
> > Signed-off-by: Yongpeng Yang <yangyongpeng@xiaomi.com>
> > ---
> >  fs/f2fs/extent_cache.c    | 70 +++++++++++++++++++++++++++++++++++++++
> >  fs/f2fs/f2fs.h            |  3 ++
> >  fs/f2fs/file.c            | 11 ++++++
> >  include/uapi/linux/f2fs.h | 21 ++++++++++++
> >  4 files changed, 105 insertions(+)
> > 
> > diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
> > index e141ffb64e5f..0c10d5639d68 100644
> > --- a/fs/f2fs/extent_cache.c
> > +++ b/fs/f2fs/extent_cache.c
> > @@ -14,6 +14,7 @@
> >  
> >  #include <linux/fs.h>
> >  #include <linux/f2fs_fs.h>
> > +#include <uapi/linux/f2fs.h>
> >  
> >  #include "f2fs.h"
> >  #include "node.h"
> > @@ -1267,6 +1268,75 @@ static void __init_extent_tree_info(struct extent_tree_info *eti)
> >  	atomic_set(&eti->total_ext_node, 0);
> >  }
> >  
> > +int f2fs_get_read_cache_extents(struct inode *inode,
> > +			struct f2fs_read_cache_extent __user *uarg)
> > +{
> > +	struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ];
> > +	struct f2fs_cache_extent_info *kbuf = NULL;
> > +	struct f2fs_cache_extent_info largest = {};
> > +	struct rb_node *node;
> > +	struct extent_node *en;
> > +	unsigned int capacity, count = 0;
> > +	__u32 flags = 0;
> > +	int ret = 0;
> > +
> > +	if (get_user(capacity, &uarg->ext_count))
> > +		return -EFAULT;
> > +
> > +	if (is_inode_flag_set(inode, FI_NO_EXTENT))
> > +		flags |= F2FS_EXT_FL_NO_EXTENT;
> > +
> > +	if (!et || (flags & F2FS_EXT_FL_NO_EXTENT)) {
> > +		if (put_user(0U, &uarg->ext_count) ||
> > +		    put_user(flags, &uarg->flags) ||
> > +		    put_user(0U, &uarg->node_count))
> > +			return -EFAULT;
> > +		return 0;
> > +	}
> > +
> > +	if (capacity) {
> > +		kbuf = f2fs_kvmalloc(F2FS_I_SB(inode), capacity * sizeof(*kbuf), GFP_KERNEL);
> > +		if (!kbuf)
> > +			return -ENOMEM;
> > +	}
> > +
> > +	read_lock(&et->lock);
> > +
> > +	largest.fofs = et->largest.fofs;
> > +	largest.blk = et->largest.blk;
> > +	largest.len = et->largest.len;
> > +	largest.last_access_mode = et->largest.last_access_mode;
> > +
> > +	for (node = rb_first_cached(&et->root); node; node = rb_next(node)) {
> > +		if (count >= capacity)
> > +			break;
> > +		en = rb_entry(node, struct extent_node, rb_node);
> > +
> > +		kbuf[count].fofs = en->ei.fofs;
> > +		kbuf[count].blk = en->ei.blk;
> > +		kbuf[count].len = en->ei.len;
> > +		kbuf[count].last_access_mode = en->ei.last_access_mode;
> > +		count++;
> > +	}
> > +
> > +	read_unlock(&et->lock);
> > +
> > +	if (count && copy_to_user(uarg->extents, kbuf,
> > +				  count * sizeof(*kbuf))) {
> > +		ret = -EFAULT;
> > +		goto out;
> > +	}
> > +
> > +	if (put_user(count, &uarg->ext_count) ||
> > +	    put_user(flags, &uarg->flags) ||
> > +	    put_user((u32)atomic_read(&et->node_cnt), &uarg->node_count) ||
> > +	    copy_to_user(&uarg->largest, &largest, sizeof(largest)))
> > +		ret = -EFAULT;
> > +out:
> > +	kvfree(kbuf);
> > +	return ret;
> > +}
> > +
> >  void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi)
> >  {
> >  	__init_extent_tree_info(&sbi->extent_tree[EX_READ]);
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index 1588b64d04a3..69641fc31c51 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -26,6 +26,7 @@
> >  #include <linux/part_stat.h>
> >  #include <linux/rw_hint.h>
> >  
> > +#include <uapi/linux/f2fs.h>
> >  #include <linux/fscrypt.h>
> >  #include <linux/fsverity.h>
> >  
> > @@ -4590,6 +4591,8 @@ void f2fs_update_read_extent_cache(struct dnode_of_data *dn);
> >  void f2fs_update_read_extent_cache_range(struct dnode_of_data *dn,
> >  				pgoff_t fofs, block_t blkaddr, unsigned int len,
> >  				enum extent_access_mode access_mode);
> > +int f2fs_get_read_cache_extents(struct inode *inode,
> > +			struct f2fs_read_cache_extent __user *uarg);
> >  unsigned int f2fs_shrink_read_extent_tree(struct f2fs_sb_info *sbi,
> >  			int nr_shrink);
> >  
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> > index a3a5d499eadf..66ec9927d667 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -3672,6 +3672,14 @@ static int f2fs_ioc_precache_extents(struct file *filp)
> >  	return f2fs_precache_extents(file_inode(filp));
> >  }
> >  
> > +static int f2fs_ioc_get_read_cache_extents(struct file *filp, unsigned long arg)
> > +{
> > +	struct inode *inode = file_inode(filp);
> > +
> > +	return f2fs_get_read_cache_extents(inode,
> > +			(struct f2fs_read_cache_extent __user *)arg);
> > +}
> > +
> >  static int f2fs_ioc_resize_fs(struct file *filp, unsigned long arg)
> >  {
> >  	struct f2fs_sb_info *sbi = F2FS_I_SB(file_inode(filp));
> > @@ -4744,6 +4752,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> >  		return f2fs_ioc_get_dev_alias_file(filp, arg);
> >  	case F2FS_IOC_IO_PRIO:
> >  		return f2fs_ioc_io_prio(filp, arg);
> > +	case F2FS_IOC_GET_READ_CACHE_EXTENTS:
> > +		return f2fs_ioc_get_read_cache_extents(filp, arg);
> >  	default:
> >  		return -ENOTTY;
> >  	}
> > @@ -5506,6 +5516,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> >  	case F2FS_IOC_COMPRESS_FILE:
> >  	case F2FS_IOC_GET_DEV_ALIAS_FILE:
> >  	case F2FS_IOC_IO_PRIO:
> > +	case F2FS_IOC_GET_READ_CACHE_EXTENTS:
> >  		break;
> >  	default:
> >  		return -ENOIOCTLCMD;
> > diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h
> > index 795e26258355..6ff9003bc030 100644
> > --- a/include/uapi/linux/f2fs.h
> > +++ b/include/uapi/linux/f2fs.h
> > @@ -45,6 +45,8 @@
> >  #define F2FS_IOC_START_ATOMIC_REPLACE	_IO(F2FS_IOCTL_MAGIC, 25)
> >  #define F2FS_IOC_GET_DEV_ALIAS_FILE	_IOR(F2FS_IOCTL_MAGIC, 26, __u32)
> >  #define F2FS_IOC_IO_PRIO		_IOW(F2FS_IOCTL_MAGIC, 27, __u32)
> > +#define F2FS_IOC_GET_READ_CACHE_EXTENTS	_IOWR(F2FS_IOCTL_MAGIC, 28,	\
> > +						struct f2fs_read_cache_extent)
> >  
> >  /*
> >   * should be same as XFS_IOC_GOINGDOWN.
> > @@ -104,4 +106,23 @@ struct f2fs_comp_option {
> >  	__u8 log_cluster_size;
> >  };
> >  
> > +struct f2fs_cache_extent_info {
> > +	__u32 fofs;		/* start file offset in blocks */
> > +	__u32 blk;		/* start block address */
> > +	__u32 len;		/* length in blocks */
> > +	__u32 last_access_mode; /* last access mode of extent_node */
> > +};
> > +
> > +/* flags for f2fs_read_cache_extent */
> > +#define F2FS_EXT_FL_NO_EXTENT	0x1	/* extent cache disabled for this inode */
> > +
> > +struct f2fs_read_cache_extent {
> > +	__u32 ext_count;	/* in: array capacity; out: mapped extent count */
> > +	__u32 flags;		/* out: status flags */
> > +	__u32 node_count;	/* out: total extent nodes in tree */
> > +	__u32 reserved;
> > +	struct f2fs_cache_extent_info largest;		/* out: largest extent */
> > +	struct f2fs_cache_extent_info extents[];	/* out: extent array */
> > +};
> > +
> >  #endif /* _UAPI_LINUX_F2FS_H */
> 
> 
> 
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


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

  reply	other threads:[~2026-06-15 15:52 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-12 11:58 [f2fs-dev] [PATCH RESEND 1/5] f2fs: fix extent merge failure when largest extent is not in rb-tree Yongpeng Yang
2026-06-12 11:58 ` [f2fs-dev] [PATCH RESEND 2/5] f2fs: only initialize largest extent without extent_node at inode init Yongpeng Yang
2026-06-15 11:55   ` Chao Yu via Linux-f2fs-devel
2026-06-12 11:58 ` [f2fs-dev] [PATCH RESEND 3/5] f2fs: punch largest extent instead of dropping it entirely on overlap Yongpeng Yang
2026-06-15 12:05   ` Chao Yu via Linux-f2fs-devel
2026-06-12 11:58 ` [f2fs-dev] [PATCH RESEND 4/5] f2fs: add extent_access_mode to track extent cache access patterns Yongpeng Yang
2026-06-15 12:05   ` Chao Yu via Linux-f2fs-devel
2026-06-12 11:58 ` [f2fs-dev] [PATCH RESEND 5/5] f2fs: add ioctl to export read extent cache to userspace for debug Yongpeng Yang
2026-06-15 12:20   ` Chao Yu via Linux-f2fs-devel
2026-06-15 15:51     ` Jaegeuk Kim via Linux-f2fs-devel [this message]
2026-06-15 11:26 ` [f2fs-dev] [PATCH RESEND 1/5] f2fs: fix extent merge failure when largest extent is not in rb-tree Chao Yu via Linux-f2fs-devel

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=ajAfmEHCgHAh1E0I@google.com \
    --to=linux-f2fs-devel@lists.sourceforge.net \
    --cc=chao@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=monty_pavel@sina.com \
    --cc=yangyongpeng.storage@gmail.com \
    --cc=yangyongpeng@xiaomi.com \
    /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.