On 06/15, Chao Yu via Linux-f2fs-devel wrote:
> On 6/12/26 19:58, Yongpeng Yang wrote:
> > From: Yongpeng Yang <[email protected]>
> > 
> > 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 <[email protected]>
> > ---
> >  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
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to