* [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages
@ 2025-01-13 18:39 ` Jaegeuk Kim
0 siblings, 0 replies; 24+ messages in thread
From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-01-13 18:39 UTC (permalink / raw)
To: linux-kernel, linux-f2fs-devel; +Cc: Jaegeuk Kim
This patch introduces an inode list to keep the page cache ranges that users
can donate pages together.
#define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \
struct f2fs_donate_range)
struct f2fs_donate_range {
__u64 start;
__u64 len;
};
e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range);
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fs/f2fs/debug.c | 3 +++
fs/f2fs/f2fs.h | 9 +++++++-
fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++
fs/f2fs/inode.c | 14 ++++++++++++
fs/f2fs/super.c | 1 +
include/uapi/linux/f2fs.h | 7 ++++++
6 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 468828288a4a..1b099c123670 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA);
si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE];
si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
+ si->ndonate_files = sbi->ndirty_inode[DONATE_INODE];
si->nquota_files = sbi->nquota_files;
si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
si->aw_cnt = atomic_read(&sbi->atomic_files);
@@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v)
si->compr_inode, si->compr_blocks);
seq_printf(s, " - Swapfile Inode: %u\n",
si->swapfile_inode);
+ seq_printf(s, " - Donate Inode: %d\n",
+ si->ndonate_files);
seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n",
si->orphans, si->append, si->update);
seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 4bfe162eefd3..7ce3e3eab17a 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -850,6 +850,11 @@ struct f2fs_inode_info {
#endif
struct list_head dirty_list; /* dirty list for dirs and files */
struct list_head gdirty_list; /* linked in global dirty list */
+
+ /* linked in global inode list for cache donation */
+ struct list_head gdonate_list;
+ loff_t donate_start, donate_end; /* inclusive */
+
struct task_struct *atomic_write_task; /* store atomic write task */
struct extent_tree *extent_tree[NR_EXTENT_CACHES];
/* cached extent_tree entry */
@@ -1274,6 +1279,7 @@ enum inode_type {
DIR_INODE, /* for dirty dir inode */
FILE_INODE, /* for dirty regular/symlink inode */
DIRTY_META, /* for all dirtied inode metadata */
+ DONATE_INODE, /* for all inode to donate pages */
NR_INODE_TYPE,
};
@@ -3984,7 +3990,8 @@ struct f2fs_stat_info {
unsigned long long allocated_data_blocks;
int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta;
int ndirty_data, ndirty_qdata;
- unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all;
+ unsigned int ndirty_dirs, ndirty_files, ndirty_all;
+ unsigned int nquota_files, ndonate_files;
int nats, dirty_nats, sits, dirty_sits;
int free_nids, avail_nids, alloc_nids;
int total_count, utilization;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 9980d17ef9f5..d6dea6258c2d 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2493,6 +2493,51 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
return ret;
}
+static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg)
+{
+ struct inode *inode = file_inode(filp);
+ struct mnt_idmap *idmap = file_mnt_idmap(filp);
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+ struct f2fs_donate_range range;
+ int ret;
+
+ if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg,
+ sizeof(range)))
+ return -EFAULT;
+
+ if (!inode_owner_or_capable(idmap, inode))
+ return -EACCES;
+
+ if (!S_ISREG(inode->i_mode))
+ return -EINVAL;
+
+ ret = mnt_want_write_file(filp);
+ if (ret)
+ return ret;
+
+ inode_lock(inode);
+
+ if (f2fs_is_atomic_file(inode))
+ goto out;
+
+ spin_lock(&sbi->inode_lock[DONATE_INODE]);
+ if (list_empty(&F2FS_I(inode)->gdonate_list)) {
+ list_add_tail(&F2FS_I(inode)->gdonate_list,
+ &sbi->inode_list[DONATE_INODE]);
+ stat_inc_dirty_inode(sbi, DONATE_INODE);
+ } else {
+ list_move_tail(&F2FS_I(inode)->gdonate_list,
+ &sbi->inode_list[DONATE_INODE]);
+ }
+ F2FS_I(inode)->donate_start = range.start;
+ F2FS_I(inode)->donate_end = range.start + range.len - 1;
+ spin_unlock(&sbi->inode_lock[DONATE_INODE]);
+out:
+ inode_unlock(inode);
+ mnt_drop_write_file(filp);
+ return ret;
+}
+
static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
@@ -4522,6 +4567,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EOPNOTSUPP;
case F2FS_IOC_SHUTDOWN:
return f2fs_ioc_shutdown(filp, arg);
+ case F2FS_IOC_DONATE_RANGE:
+ return f2fs_ioc_donate_range(filp, arg);
case FITRIM:
return f2fs_ioc_fitrim(filp, arg);
case FS_IOC_SET_ENCRYPTION_POLICY:
@@ -5273,6 +5320,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case F2FS_IOC_RELEASE_VOLATILE_WRITE:
case F2FS_IOC_ABORT_ATOMIC_WRITE:
case F2FS_IOC_SHUTDOWN:
+ case F2FS_IOC_DONATE_RANGE:
case FITRIM:
case FS_IOC_SET_ENCRYPTION_POLICY:
case FS_IOC_GET_ENCRYPTION_PWSALT:
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 7de33da8b3ea..e38dc5fe2f2e 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
return 0;
}
+static void f2fs_remove_donate_inode(struct inode *inode)
+{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+
+ if (list_empty(&F2FS_I(inode)->gdonate_list))
+ return;
+
+ spin_lock(&sbi->inode_lock[DONATE_INODE]);
+ list_del_init(&F2FS_I(inode)->gdonate_list);
+ stat_dec_dirty_inode(sbi, DONATE_INODE);
+ spin_unlock(&sbi->inode_lock[DONATE_INODE]);
+}
+
/*
* Called at the last iput() if i_nlink is zero
*/
@@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode)
f2fs_bug_on(sbi, get_dirty_pages(inode));
f2fs_remove_dirty_inode(inode);
+ f2fs_remove_donate_inode(inode);
if (!IS_DEVICE_ALIASING(inode))
f2fs_destroy_extent_tree(inode);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index fc7d463dee15..ef639a6d82e5 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
spin_lock_init(&fi->i_size_lock);
INIT_LIST_HEAD(&fi->dirty_list);
INIT_LIST_HEAD(&fi->gdirty_list);
+ INIT_LIST_HEAD(&fi->gdonate_list);
init_f2fs_rwsem(&fi->i_gc_rwsem[READ]);
init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]);
init_f2fs_rwsem(&fi->i_xattr_sem);
diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h
index f7aaf8d23e20..cd38a7c166e6 100644
--- a/include/uapi/linux/f2fs.h
+++ b/include/uapi/linux/f2fs.h
@@ -44,6 +44,8 @@
#define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24)
#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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \
+ struct f2fs_donate_range)
/*
* should be same as XFS_IOC_GOINGDOWN.
@@ -97,4 +99,9 @@ struct f2fs_comp_option {
__u8 log_cluster_size;
};
+struct f2fs_donate_range {
+ __u64 start;
+ __u64 len;
+};
+
#endif /* _UAPI_LINUX_F2FS_H */
--
2.47.1.688.g23fc6f90ad-goog
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH 1/2] f2fs: register inodes which is able to donate pages @ 2025-01-13 18:39 ` Jaegeuk Kim 0 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim @ 2025-01-13 18:39 UTC (permalink / raw) To: linux-kernel, linux-f2fs-devel; +Cc: Jaegeuk Kim This patch introduces an inode list to keep the page cache ranges that users can donate pages together. #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ struct f2fs_donate_range) struct f2fs_donate_range { __u64 start; __u64 len; }; e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> --- fs/f2fs/debug.c | 3 +++ fs/f2fs/f2fs.h | 9 +++++++- fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ fs/f2fs/inode.c | 14 ++++++++++++ fs/f2fs/super.c | 1 + include/uapi/linux/f2fs.h | 7 ++++++ 6 files changed, 81 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 468828288a4a..1b099c123670 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; si->nquota_files = sbi->nquota_files; si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; si->aw_cnt = atomic_read(&sbi->atomic_files); @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) si->compr_inode, si->compr_blocks); seq_printf(s, " - Swapfile Inode: %u\n", si->swapfile_inode); + seq_printf(s, " - Donate Inode: %d\n", + si->ndonate_files); seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", si->orphans, si->append, si->update); seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4bfe162eefd3..7ce3e3eab17a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -850,6 +850,11 @@ struct f2fs_inode_info { #endif struct list_head dirty_list; /* dirty list for dirs and files */ struct list_head gdirty_list; /* linked in global dirty list */ + + /* linked in global inode list for cache donation */ + struct list_head gdonate_list; + loff_t donate_start, donate_end; /* inclusive */ + struct task_struct *atomic_write_task; /* store atomic write task */ struct extent_tree *extent_tree[NR_EXTENT_CACHES]; /* cached extent_tree entry */ @@ -1274,6 +1279,7 @@ enum inode_type { DIR_INODE, /* for dirty dir inode */ FILE_INODE, /* for dirty regular/symlink inode */ DIRTY_META, /* for all dirtied inode metadata */ + DONATE_INODE, /* for all inode to donate pages */ NR_INODE_TYPE, }; @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { unsigned long long allocated_data_blocks; int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; int ndirty_data, ndirty_qdata; - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; + unsigned int ndirty_dirs, ndirty_files, ndirty_all; + unsigned int nquota_files, ndonate_files; int nats, dirty_nats, sits, dirty_sits; int free_nids, avail_nids, alloc_nids; int total_count, utilization; diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 9980d17ef9f5..d6dea6258c2d 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2493,6 +2493,51 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) return ret; } +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct mnt_idmap *idmap = file_mnt_idmap(filp); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_donate_range range; + int ret; + + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, + sizeof(range))) + return -EFAULT; + + if (!inode_owner_or_capable(idmap, inode)) + return -EACCES; + + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + + ret = mnt_want_write_file(filp); + if (ret) + return ret; + + inode_lock(inode); + + if (f2fs_is_atomic_file(inode)) + goto out; + + spin_lock(&sbi->inode_lock[DONATE_INODE]); + if (list_empty(&F2FS_I(inode)->gdonate_list)) { + list_add_tail(&F2FS_I(inode)->gdonate_list, + &sbi->inode_list[DONATE_INODE]); + stat_inc_dirty_inode(sbi, DONATE_INODE); + } else { + list_move_tail(&F2FS_I(inode)->gdonate_list, + &sbi->inode_list[DONATE_INODE]); + } + F2FS_I(inode)->donate_start = range.start; + F2FS_I(inode)->donate_end = range.start + range.len - 1; + spin_unlock(&sbi->inode_lock[DONATE_INODE]); +out: + inode_unlock(inode); + mnt_drop_write_file(filp); + return ret; +} + static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -4522,6 +4567,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EOPNOTSUPP; case F2FS_IOC_SHUTDOWN: return f2fs_ioc_shutdown(filp, arg); + case F2FS_IOC_DONATE_RANGE: + return f2fs_ioc_donate_range(filp, arg); case FITRIM: return f2fs_ioc_fitrim(filp, arg); case FS_IOC_SET_ENCRYPTION_POLICY: @@ -5273,6 +5320,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_RELEASE_VOLATILE_WRITE: case F2FS_IOC_ABORT_ATOMIC_WRITE: case F2FS_IOC_SHUTDOWN: + case F2FS_IOC_DONATE_RANGE: case FITRIM: case FS_IOC_SET_ENCRYPTION_POLICY: case FS_IOC_GET_ENCRYPTION_PWSALT: diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 7de33da8b3ea..e38dc5fe2f2e 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) return 0; } +static void f2fs_remove_donate_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + if (list_empty(&F2FS_I(inode)->gdonate_list)) + return; + + spin_lock(&sbi->inode_lock[DONATE_INODE]); + list_del_init(&F2FS_I(inode)->gdonate_list); + stat_dec_dirty_inode(sbi, DONATE_INODE); + spin_unlock(&sbi->inode_lock[DONATE_INODE]); +} + /* * Called at the last iput() if i_nlink is zero */ @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) f2fs_bug_on(sbi, get_dirty_pages(inode)); f2fs_remove_dirty_inode(inode); + f2fs_remove_donate_inode(inode); if (!IS_DEVICE_ALIASING(inode)) f2fs_destroy_extent_tree(inode); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index fc7d463dee15..ef639a6d82e5 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) spin_lock_init(&fi->i_size_lock); INIT_LIST_HEAD(&fi->dirty_list); INIT_LIST_HEAD(&fi->gdirty_list); + INIT_LIST_HEAD(&fi->gdonate_list); init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); init_f2fs_rwsem(&fi->i_xattr_sem); diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h index f7aaf8d23e20..cd38a7c166e6 100644 --- a/include/uapi/linux/f2fs.h +++ b/include/uapi/linux/f2fs.h @@ -44,6 +44,8 @@ #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ + struct f2fs_donate_range) /* * should be same as XFS_IOC_GOINGDOWN. @@ -97,4 +99,9 @@ struct f2fs_comp_option { __u8 log_cluster_size; }; +struct f2fs_donate_range { + __u64 start; + __u64 len; +}; + #endif /* _UAPI_LINUX_F2FS_H */ -- 2.47.1.688.g23fc6f90ad-goog ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [f2fs-dev] [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages 2025-01-13 18:39 ` Jaegeuk Kim @ 2025-01-13 18:39 ` Jaegeuk Kim -1 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-01-13 18:39 UTC (permalink / raw) To: linux-kernel, linux-f2fs-devel; +Cc: Jaegeuk Kim 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); 4. echo 3 > /sys/fs/f2fs/blk/donate_caches will reclaim 3 page cache ranges, registered by #1, #2, and #3. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> --- Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ fs/f2fs/f2fs.h | 4 ++++ fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ fs/f2fs/sysfs.c | 8 ++++++++ 4 files changed, 46 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 3e1630c70d8a..6f9d8b8889fd 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -828,3 +828,10 @@ Date: November 2024 Contact: "Chao Yu" <chao@kernel.org> Description: It controls max read extent count for per-inode, the value of threshold is 10240 by default. + +What: /sys/fs/f2fs/<disk>/donate_caches +Date: December 2024 +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> +Description: It reclaims the certian file-backed pages registered by + ioctl(F2FS_IOC_DONATE_RANGE). + For example, writing N tries to drop N address spaces in LRU. diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 7ce3e3eab17a..6c434ae94cb1 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { unsigned int warm_data_age_threshold; unsigned int last_age_weight; + /* control donate caches */ + unsigned int donate_caches; + /* basic filesystem units */ unsigned int log_sectors_per_block; /* log2 sectors per block */ unsigned int log_blocksize; /* log2 block size */ @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, struct shrink_control *sc); unsigned long f2fs_shrink_scan(struct shrinker *shrink, struct shrink_control *sc); +void f2fs_donate_caches(struct f2fs_sb_info *sbi); void f2fs_join_shrinker(struct f2fs_sb_info *sbi); void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index 83d6fb97dcae..a3e2063392a7 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, return freed; } +void f2fs_donate_caches(struct f2fs_sb_info *sbi) +{ + struct inode *inode = NULL; + struct f2fs_inode_info *fi; + int nfiles = sbi->donate_caches; +next: + spin_lock(&sbi->inode_lock[DONATE_INODE]); + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { + spin_unlock(&sbi->inode_lock[DONATE_INODE]); + return; + } + + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], + struct f2fs_inode_info, gdonate_list); + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); + inode = igrab(&fi->vfs_inode); + spin_unlock(&sbi->inode_lock[DONATE_INODE]); + + if (inode) { + invalidate_inode_pages2_range(inode->i_mapping, + fi->donate_start, fi->donate_end); + iput(inode); + } + if (nfiles--) + goto next; +} + void f2fs_join_shrinker(struct f2fs_sb_info *sbi) { spin_lock(&f2fs_list_lock); diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 6b99dc49f776..7570580ec3c0 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, return count; } + if (!strcmp(a->attr.name, "donate_caches")) { + sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); + f2fs_donate_caches(sbi); + return count; + } + *ui = (unsigned int)t; return count; @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); F2FS_SBI_GENERAL_RW_ATTR(dir_level); +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); #ifdef CONFIG_F2FS_IOSTAT F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(migration_granularity), ATTR_LIST(migration_window_granularity), ATTR_LIST(dir_level), + ATTR_LIST(donate_caches), ATTR_LIST(ram_thresh), ATTR_LIST(ra_nid_pages), ATTR_LIST(dirty_nats_ratio), -- 2.47.1.688.g23fc6f90ad-goog _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages @ 2025-01-13 18:39 ` Jaegeuk Kim 0 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim @ 2025-01-13 18:39 UTC (permalink / raw) To: linux-kernel, linux-f2fs-devel; +Cc: Jaegeuk Kim 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); 4. echo 3 > /sys/fs/f2fs/blk/donate_caches will reclaim 3 page cache ranges, registered by #1, #2, and #3. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> --- Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ fs/f2fs/f2fs.h | 4 ++++ fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ fs/f2fs/sysfs.c | 8 ++++++++ 4 files changed, 46 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 3e1630c70d8a..6f9d8b8889fd 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -828,3 +828,10 @@ Date: November 2024 Contact: "Chao Yu" <chao@kernel.org> Description: It controls max read extent count for per-inode, the value of threshold is 10240 by default. + +What: /sys/fs/f2fs/<disk>/donate_caches +Date: December 2024 +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> +Description: It reclaims the certian file-backed pages registered by + ioctl(F2FS_IOC_DONATE_RANGE). + For example, writing N tries to drop N address spaces in LRU. diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 7ce3e3eab17a..6c434ae94cb1 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { unsigned int warm_data_age_threshold; unsigned int last_age_weight; + /* control donate caches */ + unsigned int donate_caches; + /* basic filesystem units */ unsigned int log_sectors_per_block; /* log2 sectors per block */ unsigned int log_blocksize; /* log2 block size */ @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, struct shrink_control *sc); unsigned long f2fs_shrink_scan(struct shrinker *shrink, struct shrink_control *sc); +void f2fs_donate_caches(struct f2fs_sb_info *sbi); void f2fs_join_shrinker(struct f2fs_sb_info *sbi); void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index 83d6fb97dcae..a3e2063392a7 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, return freed; } +void f2fs_donate_caches(struct f2fs_sb_info *sbi) +{ + struct inode *inode = NULL; + struct f2fs_inode_info *fi; + int nfiles = sbi->donate_caches; +next: + spin_lock(&sbi->inode_lock[DONATE_INODE]); + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { + spin_unlock(&sbi->inode_lock[DONATE_INODE]); + return; + } + + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], + struct f2fs_inode_info, gdonate_list); + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); + inode = igrab(&fi->vfs_inode); + spin_unlock(&sbi->inode_lock[DONATE_INODE]); + + if (inode) { + invalidate_inode_pages2_range(inode->i_mapping, + fi->donate_start, fi->donate_end); + iput(inode); + } + if (nfiles--) + goto next; +} + void f2fs_join_shrinker(struct f2fs_sb_info *sbi) { spin_lock(&f2fs_list_lock); diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 6b99dc49f776..7570580ec3c0 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, return count; } + if (!strcmp(a->attr.name, "donate_caches")) { + sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); + f2fs_donate_caches(sbi); + return count; + } + *ui = (unsigned int)t; return count; @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); F2FS_SBI_GENERAL_RW_ATTR(dir_level); +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); #ifdef CONFIG_F2FS_IOSTAT F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(migration_granularity), ATTR_LIST(migration_window_granularity), ATTR_LIST(dir_level), + ATTR_LIST(donate_caches), ATTR_LIST(ram_thresh), ATTR_LIST(ra_nid_pages), ATTR_LIST(dirty_nats_ratio), -- 2.47.1.688.g23fc6f90ad-goog ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages 2025-01-13 18:39 ` Jaegeuk Kim @ 2025-01-14 7:34 ` Chao Yu -1 siblings, 0 replies; 24+ messages in thread From: Chao Yu via Linux-f2fs-devel @ 2025-01-14 7:34 UTC (permalink / raw) To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: > 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); > 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); > 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); > 4. echo 3 > /sys/fs/f2fs/blk/donate_caches > > will reclaim 3 page cache ranges, registered by #1, #2, and #3. > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > --- > Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ > fs/f2fs/f2fs.h | 4 ++++ > fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ > fs/f2fs/sysfs.c | 8 ++++++++ > 4 files changed, 46 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs > index 3e1630c70d8a..6f9d8b8889fd 100644 > --- a/Documentation/ABI/testing/sysfs-fs-f2fs > +++ b/Documentation/ABI/testing/sysfs-fs-f2fs > @@ -828,3 +828,10 @@ Date: November 2024 > Contact: "Chao Yu" <chao@kernel.org> > Description: It controls max read extent count for per-inode, the value of threshold > is 10240 by default. > + > +What: /sys/fs/f2fs/<disk>/donate_caches > +Date: December 2024 > +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> > +Description: It reclaims the certian file-backed pages registered by > + ioctl(F2FS_IOC_DONATE_RANGE). > + For example, writing N tries to drop N address spaces in LRU. > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index 7ce3e3eab17a..6c434ae94cb1 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { > unsigned int warm_data_age_threshold; > unsigned int last_age_weight; > > + /* control donate caches */ > + unsigned int donate_caches; > + > /* basic filesystem units */ > unsigned int log_sectors_per_block; /* log2 sectors per block */ > unsigned int log_blocksize; /* log2 block size */ > @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, > struct shrink_control *sc); > unsigned long f2fs_shrink_scan(struct shrinker *shrink, > struct shrink_control *sc); > +void f2fs_donate_caches(struct f2fs_sb_info *sbi); > void f2fs_join_shrinker(struct f2fs_sb_info *sbi); > void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); > > diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c > index 83d6fb97dcae..a3e2063392a7 100644 > --- a/fs/f2fs/shrinker.c > +++ b/fs/f2fs/shrinker.c > @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, > return freed; > } > > +void f2fs_donate_caches(struct f2fs_sb_info *sbi) > +{ > + struct inode *inode = NULL; > + struct f2fs_inode_info *fi; > + int nfiles = sbi->donate_caches; > +next: > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > + return; > + } > + > + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], > + struct f2fs_inode_info, gdonate_list); > + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); Not needed to drop it from the global list, right? Thanks, > + inode = igrab(&fi->vfs_inode); > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > + > + if (inode) { > + invalidate_inode_pages2_range(inode->i_mapping, > + fi->donate_start, fi->donate_end); > + iput(inode); > + } > + if (nfiles--) > + goto next; > +} > + > void f2fs_join_shrinker(struct f2fs_sb_info *sbi) > { > spin_lock(&f2fs_list_lock); > diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c > index 6b99dc49f776..7570580ec3c0 100644 > --- a/fs/f2fs/sysfs.c > +++ b/fs/f2fs/sysfs.c > @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, > return count; > } > > + if (!strcmp(a->attr.name, "donate_caches")) { > + sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); > + f2fs_donate_caches(sbi); > + return count; > + } > + > *ui = (unsigned int)t; > > return count; > @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); > F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); > F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); > F2FS_SBI_GENERAL_RW_ATTR(dir_level); > +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); > #ifdef CONFIG_F2FS_IOSTAT > F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); > F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); > @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { > ATTR_LIST(migration_granularity), > ATTR_LIST(migration_window_granularity), > ATTR_LIST(dir_level), > + ATTR_LIST(donate_caches), > ATTR_LIST(ram_thresh), > ATTR_LIST(ra_nid_pages), > ATTR_LIST(dirty_nats_ratio), _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages @ 2025-01-14 7:34 ` Chao Yu 0 siblings, 0 replies; 24+ messages in thread From: Chao Yu @ 2025-01-14 7:34 UTC (permalink / raw) To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel; +Cc: chao On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: > 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); > 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); > 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); > 4. echo 3 > /sys/fs/f2fs/blk/donate_caches > > will reclaim 3 page cache ranges, registered by #1, #2, and #3. > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > --- > Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ > fs/f2fs/f2fs.h | 4 ++++ > fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ > fs/f2fs/sysfs.c | 8 ++++++++ > 4 files changed, 46 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs > index 3e1630c70d8a..6f9d8b8889fd 100644 > --- a/Documentation/ABI/testing/sysfs-fs-f2fs > +++ b/Documentation/ABI/testing/sysfs-fs-f2fs > @@ -828,3 +828,10 @@ Date: November 2024 > Contact: "Chao Yu" <chao@kernel.org> > Description: It controls max read extent count for per-inode, the value of threshold > is 10240 by default. > + > +What: /sys/fs/f2fs/<disk>/donate_caches > +Date: December 2024 > +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> > +Description: It reclaims the certian file-backed pages registered by > + ioctl(F2FS_IOC_DONATE_RANGE). > + For example, writing N tries to drop N address spaces in LRU. > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index 7ce3e3eab17a..6c434ae94cb1 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { > unsigned int warm_data_age_threshold; > unsigned int last_age_weight; > > + /* control donate caches */ > + unsigned int donate_caches; > + > /* basic filesystem units */ > unsigned int log_sectors_per_block; /* log2 sectors per block */ > unsigned int log_blocksize; /* log2 block size */ > @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, > struct shrink_control *sc); > unsigned long f2fs_shrink_scan(struct shrinker *shrink, > struct shrink_control *sc); > +void f2fs_donate_caches(struct f2fs_sb_info *sbi); > void f2fs_join_shrinker(struct f2fs_sb_info *sbi); > void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); > > diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c > index 83d6fb97dcae..a3e2063392a7 100644 > --- a/fs/f2fs/shrinker.c > +++ b/fs/f2fs/shrinker.c > @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, > return freed; > } > > +void f2fs_donate_caches(struct f2fs_sb_info *sbi) > +{ > + struct inode *inode = NULL; > + struct f2fs_inode_info *fi; > + int nfiles = sbi->donate_caches; > +next: > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > + return; > + } > + > + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], > + struct f2fs_inode_info, gdonate_list); > + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); Not needed to drop it from the global list, right? Thanks, > + inode = igrab(&fi->vfs_inode); > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > + > + if (inode) { > + invalidate_inode_pages2_range(inode->i_mapping, > + fi->donate_start, fi->donate_end); > + iput(inode); > + } > + if (nfiles--) > + goto next; > +} > + > void f2fs_join_shrinker(struct f2fs_sb_info *sbi) > { > spin_lock(&f2fs_list_lock); > diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c > index 6b99dc49f776..7570580ec3c0 100644 > --- a/fs/f2fs/sysfs.c > +++ b/fs/f2fs/sysfs.c > @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, > return count; > } > > + if (!strcmp(a->attr.name, "donate_caches")) { > + sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); > + f2fs_donate_caches(sbi); > + return count; > + } > + > *ui = (unsigned int)t; > > return count; > @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); > F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); > F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); > F2FS_SBI_GENERAL_RW_ATTR(dir_level); > +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); > #ifdef CONFIG_F2FS_IOSTAT > F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); > F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); > @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { > ATTR_LIST(migration_granularity), > ATTR_LIST(migration_window_granularity), > ATTR_LIST(dir_level), > + ATTR_LIST(donate_caches), > ATTR_LIST(ram_thresh), > ATTR_LIST(ra_nid_pages), > ATTR_LIST(dirty_nats_ratio), ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages 2025-01-14 7:34 ` Chao Yu @ 2025-01-14 17:18 ` Jaegeuk Kim -1 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-01-14 17:18 UTC (permalink / raw) To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel On 01/14, Chao Yu wrote: > On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: > > 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); > > 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); > > 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); > > 4. echo 3 > /sys/fs/f2fs/blk/donate_caches > > > > will reclaim 3 page cache ranges, registered by #1, #2, and #3. > > > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > > --- > > Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ > > fs/f2fs/f2fs.h | 4 ++++ > > fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ > > fs/f2fs/sysfs.c | 8 ++++++++ > > 4 files changed, 46 insertions(+) > > > > diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs > > index 3e1630c70d8a..6f9d8b8889fd 100644 > > --- a/Documentation/ABI/testing/sysfs-fs-f2fs > > +++ b/Documentation/ABI/testing/sysfs-fs-f2fs > > @@ -828,3 +828,10 @@ Date: November 2024 > > Contact: "Chao Yu" <chao@kernel.org> > > Description: It controls max read extent count for per-inode, the value of threshold > > is 10240 by default. > > + > > +What: /sys/fs/f2fs/<disk>/donate_caches > > +Date: December 2024 > > +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> > > +Description: It reclaims the certian file-backed pages registered by > > + ioctl(F2FS_IOC_DONATE_RANGE). > > + For example, writing N tries to drop N address spaces in LRU. > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > > index 7ce3e3eab17a..6c434ae94cb1 100644 > > --- a/fs/f2fs/f2fs.h > > +++ b/fs/f2fs/f2fs.h > > @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { > > unsigned int warm_data_age_threshold; > > unsigned int last_age_weight; > > + /* control donate caches */ > > + unsigned int donate_caches; > > + > > /* basic filesystem units */ > > unsigned int log_sectors_per_block; /* log2 sectors per block */ > > unsigned int log_blocksize; /* log2 block size */ > > @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, > > struct shrink_control *sc); > > unsigned long f2fs_shrink_scan(struct shrinker *shrink, > > struct shrink_control *sc); > > +void f2fs_donate_caches(struct f2fs_sb_info *sbi); > > void f2fs_join_shrinker(struct f2fs_sb_info *sbi); > > void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); > > diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c > > index 83d6fb97dcae..a3e2063392a7 100644 > > --- a/fs/f2fs/shrinker.c > > +++ b/fs/f2fs/shrinker.c > > @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, > > return freed; > > } > > +void f2fs_donate_caches(struct f2fs_sb_info *sbi) > > +{ > > + struct inode *inode = NULL; > > + struct f2fs_inode_info *fi; > > + int nfiles = sbi->donate_caches; > > +next: > > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > > + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { > > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > > + return; > > + } > > + > > + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], > > + struct f2fs_inode_info, gdonate_list); > > + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); > > Not needed to drop it from the global list, right? Yea, there're two paths to drop: 1) waiting for evict_inode, 2) setting a new range having len=0. > > Thanks, > > > + inode = igrab(&fi->vfs_inode); > > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > > + > > + if (inode) { > > + invalidate_inode_pages2_range(inode->i_mapping, > > + fi->donate_start, fi->donate_end); > > + iput(inode); > > + } > > + if (nfiles--) > > + goto next; > > +} > > + > > void f2fs_join_shrinker(struct f2fs_sb_info *sbi) > > { > > spin_lock(&f2fs_list_lock); > > diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c > > index 6b99dc49f776..7570580ec3c0 100644 > > --- a/fs/f2fs/sysfs.c > > +++ b/fs/f2fs/sysfs.c > > @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, > > return count; > > } > > + if (!strcmp(a->attr.name, "donate_caches")) { > > + sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); > > + f2fs_donate_caches(sbi); > > + return count; > > + } > > + > > *ui = (unsigned int)t; > > return count; > > @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); > > F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); > > F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); > > F2FS_SBI_GENERAL_RW_ATTR(dir_level); > > +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); > > #ifdef CONFIG_F2FS_IOSTAT > > F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); > > F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); > > @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { > > ATTR_LIST(migration_granularity), > > ATTR_LIST(migration_window_granularity), > > ATTR_LIST(dir_level), > > + ATTR_LIST(donate_caches), > > ATTR_LIST(ram_thresh), > > ATTR_LIST(ra_nid_pages), > > ATTR_LIST(dirty_nats_ratio), _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages @ 2025-01-14 17:18 ` Jaegeuk Kim 0 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim @ 2025-01-14 17:18 UTC (permalink / raw) To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel On 01/14, Chao Yu wrote: > On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: > > 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); > > 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); > > 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); > > 4. echo 3 > /sys/fs/f2fs/blk/donate_caches > > > > will reclaim 3 page cache ranges, registered by #1, #2, and #3. > > > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > > --- > > Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ > > fs/f2fs/f2fs.h | 4 ++++ > > fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ > > fs/f2fs/sysfs.c | 8 ++++++++ > > 4 files changed, 46 insertions(+) > > > > diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs > > index 3e1630c70d8a..6f9d8b8889fd 100644 > > --- a/Documentation/ABI/testing/sysfs-fs-f2fs > > +++ b/Documentation/ABI/testing/sysfs-fs-f2fs > > @@ -828,3 +828,10 @@ Date: November 2024 > > Contact: "Chao Yu" <chao@kernel.org> > > Description: It controls max read extent count for per-inode, the value of threshold > > is 10240 by default. > > + > > +What: /sys/fs/f2fs/<disk>/donate_caches > > +Date: December 2024 > > +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> > > +Description: It reclaims the certian file-backed pages registered by > > + ioctl(F2FS_IOC_DONATE_RANGE). > > + For example, writing N tries to drop N address spaces in LRU. > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > > index 7ce3e3eab17a..6c434ae94cb1 100644 > > --- a/fs/f2fs/f2fs.h > > +++ b/fs/f2fs/f2fs.h > > @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { > > unsigned int warm_data_age_threshold; > > unsigned int last_age_weight; > > + /* control donate caches */ > > + unsigned int donate_caches; > > + > > /* basic filesystem units */ > > unsigned int log_sectors_per_block; /* log2 sectors per block */ > > unsigned int log_blocksize; /* log2 block size */ > > @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, > > struct shrink_control *sc); > > unsigned long f2fs_shrink_scan(struct shrinker *shrink, > > struct shrink_control *sc); > > +void f2fs_donate_caches(struct f2fs_sb_info *sbi); > > void f2fs_join_shrinker(struct f2fs_sb_info *sbi); > > void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); > > diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c > > index 83d6fb97dcae..a3e2063392a7 100644 > > --- a/fs/f2fs/shrinker.c > > +++ b/fs/f2fs/shrinker.c > > @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, > > return freed; > > } > > +void f2fs_donate_caches(struct f2fs_sb_info *sbi) > > +{ > > + struct inode *inode = NULL; > > + struct f2fs_inode_info *fi; > > + int nfiles = sbi->donate_caches; > > +next: > > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > > + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { > > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > > + return; > > + } > > + > > + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], > > + struct f2fs_inode_info, gdonate_list); > > + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); > > Not needed to drop it from the global list, right? Yea, there're two paths to drop: 1) waiting for evict_inode, 2) setting a new range having len=0. > > Thanks, > > > + inode = igrab(&fi->vfs_inode); > > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > > + > > + if (inode) { > > + invalidate_inode_pages2_range(inode->i_mapping, > > + fi->donate_start, fi->donate_end); > > + iput(inode); > > + } > > + if (nfiles--) > > + goto next; > > +} > > + > > void f2fs_join_shrinker(struct f2fs_sb_info *sbi) > > { > > spin_lock(&f2fs_list_lock); > > diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c > > index 6b99dc49f776..7570580ec3c0 100644 > > --- a/fs/f2fs/sysfs.c > > +++ b/fs/f2fs/sysfs.c > > @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, > > return count; > > } > > + if (!strcmp(a->attr.name, "donate_caches")) { > > + sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); > > + f2fs_donate_caches(sbi); > > + return count; > > + } > > + > > *ui = (unsigned int)t; > > return count; > > @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); > > F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); > > F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); > > F2FS_SBI_GENERAL_RW_ATTR(dir_level); > > +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); > > #ifdef CONFIG_F2FS_IOSTAT > > F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); > > F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); > > @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { > > ATTR_LIST(migration_granularity), > > ATTR_LIST(migration_window_granularity), > > ATTR_LIST(dir_level), > > + ATTR_LIST(donate_caches), > > ATTR_LIST(ram_thresh), > > ATTR_LIST(ra_nid_pages), > > ATTR_LIST(dirty_nats_ratio), ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages 2025-01-14 17:18 ` Jaegeuk Kim @ 2025-01-15 2:17 ` Chao Yu -1 siblings, 0 replies; 24+ messages in thread From: Chao Yu via Linux-f2fs-devel @ 2025-01-15 2:17 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel On 1/15/25 01:18, Jaegeuk Kim wrote: > On 01/14, Chao Yu wrote: >> On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: >>> 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); >>> 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); >>> 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); >>> 4. echo 3 > /sys/fs/f2fs/blk/donate_caches >>> >>> will reclaim 3 page cache ranges, registered by #1, #2, and #3. >>> >>> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> >>> --- >>> Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ >>> fs/f2fs/f2fs.h | 4 ++++ >>> fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ >>> fs/f2fs/sysfs.c | 8 ++++++++ >>> 4 files changed, 46 insertions(+) >>> >>> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs >>> index 3e1630c70d8a..6f9d8b8889fd 100644 >>> --- a/Documentation/ABI/testing/sysfs-fs-f2fs >>> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs >>> @@ -828,3 +828,10 @@ Date: November 2024 >>> Contact: "Chao Yu" <chao@kernel.org> >>> Description: It controls max read extent count for per-inode, the value of threshold >>> is 10240 by default. >>> + >>> +What: /sys/fs/f2fs/<disk>/donate_caches >>> +Date: December 2024 >>> +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> >>> +Description: It reclaims the certian file-backed pages registered by >>> + ioctl(F2FS_IOC_DONATE_RANGE). >>> + For example, writing N tries to drop N address spaces in LRU. >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h >>> index 7ce3e3eab17a..6c434ae94cb1 100644 >>> --- a/fs/f2fs/f2fs.h >>> +++ b/fs/f2fs/f2fs.h >>> @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { >>> unsigned int warm_data_age_threshold; >>> unsigned int last_age_weight; >>> + /* control donate caches */ >>> + unsigned int donate_caches; >>> + >>> /* basic filesystem units */ >>> unsigned int log_sectors_per_block; /* log2 sectors per block */ >>> unsigned int log_blocksize; /* log2 block size */ >>> @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, >>> struct shrink_control *sc); >>> unsigned long f2fs_shrink_scan(struct shrinker *shrink, >>> struct shrink_control *sc); >>> +void f2fs_donate_caches(struct f2fs_sb_info *sbi); >>> void f2fs_join_shrinker(struct f2fs_sb_info *sbi); >>> void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); >>> diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c >>> index 83d6fb97dcae..a3e2063392a7 100644 >>> --- a/fs/f2fs/shrinker.c >>> +++ b/fs/f2fs/shrinker.c >>> @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, >>> return freed; >>> } >>> +void f2fs_donate_caches(struct f2fs_sb_info *sbi) >>> +{ >>> + struct inode *inode = NULL; >>> + struct f2fs_inode_info *fi; >>> + int nfiles = sbi->donate_caches; >>> +next: >>> + spin_lock(&sbi->inode_lock[DONATE_INODE]); >>> + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { >>> + spin_unlock(&sbi->inode_lock[DONATE_INODE]); >>> + return; >>> + } >>> + >>> + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], >>> + struct f2fs_inode_info, gdonate_list); >>> + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); >> >> Not needed to drop it from the global list, right? > > Yea, there're two paths to drop: 1) waiting for evict_inode, 2) setting a new > range having len=0. Second way just relocate entry to list tail, not drop it from list? Thanks, > >> >> Thanks, >> >>> + inode = igrab(&fi->vfs_inode); >>> + spin_unlock(&sbi->inode_lock[DONATE_INODE]); >>> + >>> + if (inode) { >>> + invalidate_inode_pages2_range(inode->i_mapping, >>> + fi->donate_start, fi->donate_end); >>> + iput(inode); >>> + } >>> + if (nfiles--) >>> + goto next; >>> +} >>> + >>> void f2fs_join_shrinker(struct f2fs_sb_info *sbi) >>> { >>> spin_lock(&f2fs_list_lock); >>> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c >>> index 6b99dc49f776..7570580ec3c0 100644 >>> --- a/fs/f2fs/sysfs.c >>> +++ b/fs/f2fs/sysfs.c >>> @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, >>> return count; >>> } >>> + if (!strcmp(a->attr.name, "donate_caches")) { >>> + sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); >>> + f2fs_donate_caches(sbi); >>> + return count; >>> + } >>> + >>> *ui = (unsigned int)t; >>> return count; >>> @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); >>> F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); >>> F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); >>> F2FS_SBI_GENERAL_RW_ATTR(dir_level); >>> +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); >>> #ifdef CONFIG_F2FS_IOSTAT >>> F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); >>> F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); >>> @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { >>> ATTR_LIST(migration_granularity), >>> ATTR_LIST(migration_window_granularity), >>> ATTR_LIST(dir_level), >>> + ATTR_LIST(donate_caches), >>> ATTR_LIST(ram_thresh), >>> ATTR_LIST(ra_nid_pages), >>> ATTR_LIST(dirty_nats_ratio), _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages @ 2025-01-15 2:17 ` Chao Yu 0 siblings, 0 replies; 24+ messages in thread From: Chao Yu @ 2025-01-15 2:17 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: chao, linux-kernel, linux-f2fs-devel On 1/15/25 01:18, Jaegeuk Kim wrote: > On 01/14, Chao Yu wrote: >> On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: >>> 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); >>> 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); >>> 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); >>> 4. echo 3 > /sys/fs/f2fs/blk/donate_caches >>> >>> will reclaim 3 page cache ranges, registered by #1, #2, and #3. >>> >>> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> >>> --- >>> Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ >>> fs/f2fs/f2fs.h | 4 ++++ >>> fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ >>> fs/f2fs/sysfs.c | 8 ++++++++ >>> 4 files changed, 46 insertions(+) >>> >>> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs >>> index 3e1630c70d8a..6f9d8b8889fd 100644 >>> --- a/Documentation/ABI/testing/sysfs-fs-f2fs >>> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs >>> @@ -828,3 +828,10 @@ Date: November 2024 >>> Contact: "Chao Yu" <chao@kernel.org> >>> Description: It controls max read extent count for per-inode, the value of threshold >>> is 10240 by default. >>> + >>> +What: /sys/fs/f2fs/<disk>/donate_caches >>> +Date: December 2024 >>> +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> >>> +Description: It reclaims the certian file-backed pages registered by >>> + ioctl(F2FS_IOC_DONATE_RANGE). >>> + For example, writing N tries to drop N address spaces in LRU. >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h >>> index 7ce3e3eab17a..6c434ae94cb1 100644 >>> --- a/fs/f2fs/f2fs.h >>> +++ b/fs/f2fs/f2fs.h >>> @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { >>> unsigned int warm_data_age_threshold; >>> unsigned int last_age_weight; >>> + /* control donate caches */ >>> + unsigned int donate_caches; >>> + >>> /* basic filesystem units */ >>> unsigned int log_sectors_per_block; /* log2 sectors per block */ >>> unsigned int log_blocksize; /* log2 block size */ >>> @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, >>> struct shrink_control *sc); >>> unsigned long f2fs_shrink_scan(struct shrinker *shrink, >>> struct shrink_control *sc); >>> +void f2fs_donate_caches(struct f2fs_sb_info *sbi); >>> void f2fs_join_shrinker(struct f2fs_sb_info *sbi); >>> void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); >>> diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c >>> index 83d6fb97dcae..a3e2063392a7 100644 >>> --- a/fs/f2fs/shrinker.c >>> +++ b/fs/f2fs/shrinker.c >>> @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, >>> return freed; >>> } >>> +void f2fs_donate_caches(struct f2fs_sb_info *sbi) >>> +{ >>> + struct inode *inode = NULL; >>> + struct f2fs_inode_info *fi; >>> + int nfiles = sbi->donate_caches; >>> +next: >>> + spin_lock(&sbi->inode_lock[DONATE_INODE]); >>> + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { >>> + spin_unlock(&sbi->inode_lock[DONATE_INODE]); >>> + return; >>> + } >>> + >>> + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], >>> + struct f2fs_inode_info, gdonate_list); >>> + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); >> >> Not needed to drop it from the global list, right? > > Yea, there're two paths to drop: 1) waiting for evict_inode, 2) setting a new > range having len=0. Second way just relocate entry to list tail, not drop it from list? Thanks, > >> >> Thanks, >> >>> + inode = igrab(&fi->vfs_inode); >>> + spin_unlock(&sbi->inode_lock[DONATE_INODE]); >>> + >>> + if (inode) { >>> + invalidate_inode_pages2_range(inode->i_mapping, >>> + fi->donate_start, fi->donate_end); >>> + iput(inode); >>> + } >>> + if (nfiles--) >>> + goto next; >>> +} >>> + >>> void f2fs_join_shrinker(struct f2fs_sb_info *sbi) >>> { >>> spin_lock(&f2fs_list_lock); >>> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c >>> index 6b99dc49f776..7570580ec3c0 100644 >>> --- a/fs/f2fs/sysfs.c >>> +++ b/fs/f2fs/sysfs.c >>> @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, >>> return count; >>> } >>> + if (!strcmp(a->attr.name, "donate_caches")) { >>> + sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); >>> + f2fs_donate_caches(sbi); >>> + return count; >>> + } >>> + >>> *ui = (unsigned int)t; >>> return count; >>> @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); >>> F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); >>> F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); >>> F2FS_SBI_GENERAL_RW_ATTR(dir_level); >>> +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); >>> #ifdef CONFIG_F2FS_IOSTAT >>> F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); >>> F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); >>> @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { >>> ATTR_LIST(migration_granularity), >>> ATTR_LIST(migration_window_granularity), >>> ATTR_LIST(dir_level), >>> + ATTR_LIST(donate_caches), >>> ATTR_LIST(ram_thresh), >>> ATTR_LIST(ra_nid_pages), >>> ATTR_LIST(dirty_nats_ratio), ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages 2025-01-13 18:39 ` Jaegeuk Kim (?) (?) @ 2025-01-14 19:11 ` kernel test robot -1 siblings, 0 replies; 24+ messages in thread From: kernel test robot @ 2025-01-14 19:11 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: llvm, oe-kbuild-all Hi Jaegeuk, kernel test robot noticed the following build errors: [auto build test ERROR on jaegeuk-f2fs/dev] [also build test ERROR on linus/master v6.13-rc7 next-20250114] [cannot apply to jaegeuk-f2fs/dev-test] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Jaegeuk-Kim/f2fs-add-a-sysfs-entry-to-request-donate-file-backed-pages/20250114-025051 base: https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git dev patch link: https://lore.kernel.org/r/20250113183933.1268282-2-jaegeuk%40kernel.org patch subject: [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages config: i386-buildonly-randconfig-003-20250114 (https://download.01.org/0day-ci/archive/20250115/202501150239.3M7Ho3di-lkp@intel.com/config) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250115/202501150239.3M7Ho3di-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202501150239.3M7Ho3di-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from fs/f2fs/sysfs.c:11: In file included from include/linux/f2fs_fs.h:11: In file included from include/linux/pagemap.h:8: In file included from include/linux/mm.h:2223: include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion] 518 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" | ~~~~~~~~~~~ ^ ~~~ >> fs/f2fs/sysfs.c:815:36: error: no member named 'ndirty_inode' in 'struct f2fs_sb_info' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ~~~ ^ include/linux/minmax.h:129:41: note: expanded from macro 'min' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^ include/linux/minmax.h:105:28: note: expanded from macro '__careful_cmp' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^ include/linux/minmax.h:99:42: note: expanded from macro '__careful_cmp_once' 99 | __auto_type ux = (x); __auto_type uy = (y); \ | ^ >> fs/f2fs/sysfs.c:815:36: error: no member named 'ndirty_inode' in 'struct f2fs_sb_info' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ~~~ ^ include/linux/minmax.h:129:41: note: expanded from macro 'min' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^ include/linux/minmax.h:105:28: note: expanded from macro '__careful_cmp' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^ include/linux/minmax.h:100:33: note: expanded from macro '__careful_cmp_once' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^ note: (skipping 6 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) include/linux/compiler_types.h:542:22: note: expanded from macro 'compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~ include/linux/compiler_types.h:530:23: note: expanded from macro '_compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~ include/linux/compiler_types.h:522:9: note: expanded from macro '__compiletime_assert' 522 | if (!(condition)) \ | ^~~~~~~~~ >> fs/f2fs/sysfs.c:815:36: error: no member named 'ndirty_inode' in 'struct f2fs_sb_info' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ~~~ ^ include/linux/minmax.h:129:41: note: expanded from macro 'min' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^ include/linux/minmax.h:105:28: note: expanded from macro '__careful_cmp' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^ include/linux/minmax.h:100:33: note: expanded from macro '__careful_cmp_once' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^ note: (skipping 6 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) include/linux/compiler_types.h:542:22: note: expanded from macro 'compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~ include/linux/compiler_types.h:530:23: note: expanded from macro '_compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~ include/linux/compiler_types.h:522:9: note: expanded from macro '__compiletime_assert' 522 | if (!(condition)) \ | ^~~~~~~~~ 1 warning and 3 errors generated. vim +815 fs/f2fs/sysfs.c 676 677 if (!strcmp(a->attr.name, "atgc_candidate_ratio")) { 678 if (t > 100) 679 return -EINVAL; 680 sbi->am.candidate_ratio = t; 681 return count; 682 } 683 684 if (!strcmp(a->attr.name, "atgc_age_weight")) { 685 if (t > 100) 686 return -EINVAL; 687 sbi->am.age_weight = t; 688 return count; 689 } 690 691 if (!strcmp(a->attr.name, "gc_segment_mode")) { 692 if (t < MAX_GC_MODE) 693 sbi->gc_segment_mode = t; 694 else 695 return -EINVAL; 696 return count; 697 } 698 699 if (!strcmp(a->attr.name, "gc_pin_file_threshold")) { 700 if (t > MAX_GC_FAILED_PINNED_FILES) 701 return -EINVAL; 702 sbi->gc_pin_file_threshold = t; 703 return count; 704 } 705 706 if (!strcmp(a->attr.name, "gc_reclaimed_segments")) { 707 if (t != 0) 708 return -EINVAL; 709 sbi->gc_reclaimed_segs[sbi->gc_segment_mode] = 0; 710 return count; 711 } 712 713 if (!strcmp(a->attr.name, "seq_file_ra_mul")) { 714 if (t >= MIN_RA_MUL && t <= MAX_RA_MUL) 715 sbi->seq_file_ra_mul = t; 716 else 717 return -EINVAL; 718 return count; 719 } 720 721 if (!strcmp(a->attr.name, "max_fragment_chunk")) { 722 if (t >= MIN_FRAGMENT_SIZE && t <= MAX_FRAGMENT_SIZE) 723 sbi->max_fragment_chunk = t; 724 else 725 return -EINVAL; 726 return count; 727 } 728 729 if (!strcmp(a->attr.name, "max_fragment_hole")) { 730 if (t >= MIN_FRAGMENT_SIZE && t <= MAX_FRAGMENT_SIZE) 731 sbi->max_fragment_hole = t; 732 else 733 return -EINVAL; 734 return count; 735 } 736 737 if (!strcmp(a->attr.name, "peak_atomic_write")) { 738 if (t != 0) 739 return -EINVAL; 740 sbi->peak_atomic_write = 0; 741 return count; 742 } 743 744 if (!strcmp(a->attr.name, "committed_atomic_block")) { 745 if (t != 0) 746 return -EINVAL; 747 sbi->committed_atomic_block = 0; 748 return count; 749 } 750 751 if (!strcmp(a->attr.name, "revoked_atomic_block")) { 752 if (t != 0) 753 return -EINVAL; 754 sbi->revoked_atomic_block = 0; 755 return count; 756 } 757 758 if (!strcmp(a->attr.name, "readdir_ra")) { 759 sbi->readdir_ra = !!t; 760 return count; 761 } 762 763 if (!strcmp(a->attr.name, "hot_data_age_threshold")) { 764 if (t == 0 || t >= sbi->warm_data_age_threshold) 765 return -EINVAL; 766 if (t == *ui) 767 return count; 768 *ui = (unsigned int)t; 769 return count; 770 } 771 772 if (!strcmp(a->attr.name, "warm_data_age_threshold")) { 773 if (t <= sbi->hot_data_age_threshold) 774 return -EINVAL; 775 if (t == *ui) 776 return count; 777 *ui = (unsigned int)t; 778 return count; 779 } 780 781 if (!strcmp(a->attr.name, "last_age_weight")) { 782 if (t > 100) 783 return -EINVAL; 784 if (t == *ui) 785 return count; 786 *ui = (unsigned int)t; 787 return count; 788 } 789 790 if (!strcmp(a->attr.name, "max_read_extent_count")) { 791 if (t > UINT_MAX) 792 return -EINVAL; 793 *ui = (unsigned int)t; 794 return count; 795 } 796 797 if (!strcmp(a->attr.name, "ipu_policy")) { 798 if (t >= BIT(F2FS_IPU_MAX)) 799 return -EINVAL; 800 /* allow F2FS_IPU_NOCACHE only for IPU in the pinned file */ 801 if (f2fs_lfs_mode(sbi) && (t & ~BIT(F2FS_IPU_NOCACHE))) 802 return -EINVAL; 803 SM_I(sbi)->ipu_policy = (unsigned int)t; 804 return count; 805 } 806 807 if (!strcmp(a->attr.name, "dir_level")) { 808 if (t > MAX_DIR_HASH_DEPTH) 809 return -EINVAL; 810 sbi->dir_level = t; 811 return count; 812 } 813 814 if (!strcmp(a->attr.name, "donate_caches")) { > 815 sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); 816 f2fs_donate_caches(sbi); 817 return count; 818 } 819 820 *ui = (unsigned int)t; 821 822 return count; 823 } 824 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages 2025-01-13 18:39 ` Jaegeuk Kim ` (2 preceding siblings ...) (?) @ 2025-01-14 19:43 ` kernel test robot -1 siblings, 0 replies; 24+ messages in thread From: kernel test robot @ 2025-01-14 19:43 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: oe-kbuild-all Hi Jaegeuk, kernel test robot noticed the following build errors: [auto build test ERROR on jaegeuk-f2fs/dev] [also build test ERROR on linus/master v6.13-rc7 next-20250114] [cannot apply to jaegeuk-f2fs/dev-test] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Jaegeuk-Kim/f2fs-add-a-sysfs-entry-to-request-donate-file-backed-pages/20250114-025051 base: https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git dev patch link: https://lore.kernel.org/r/20250113183933.1268282-2-jaegeuk%40kernel.org patch subject: [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages config: i386-buildonly-randconfig-004-20250114 (https://download.01.org/0day-ci/archive/20250115/202501150319.8pSlgSSX-lkp@intel.com/config) compiler: gcc-12 (Debian 12.2.0-14) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250115/202501150319.8pSlgSSX-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202501150319.8pSlgSSX-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from include/linux/kernel.h:28, from include/linux/cpumask.h:11, from include/linux/smp.h:13, from include/linux/lockdep.h:14, from include/linux/spinlock.h:63, from include/linux/wait.h:9, from include/linux/wait_bit.h:8, from include/linux/fs.h:6, from include/linux/proc_fs.h:10, from fs/f2fs/sysfs.c:10: fs/f2fs/sysfs.c: In function '__sbi_store': >> fs/f2fs/sysfs.c:815:48: error: 'struct f2fs_sb_info' has no member named 'ndirty_inode' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~ include/linux/minmax.h:99:49: note: in definition of macro '__careful_cmp_once' 99 | __auto_type ux = (x); __auto_type uy = (y); \ | ^ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ In file included from fs/f2fs/sysfs.c:9: >> include/linux/compiler.h:189:45: error: '__UNIQUE_ID_y_948' undeclared (first use in this function); did you mean '__UNIQUE_ID_x_947'? 189 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) | ^~~~~~~~~~~~ include/linux/compiler.h:57:52: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:56:27: note: in expansion of macro 'is_signed_type' 56 | #define __sign_use(x,ux) (is_signed_type(typeof(ux))? \ | ^~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:84:22: note: in expansion of macro '___PASTE' 84 | #define __PASTE(a,b) ___PASTE(a,b) | ^~~~~~~~ include/linux/compiler.h:189:29: note: in expansion of macro '__PASTE' 189 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) | ^~~~~~~ include/linux/compiler_types.h:84:22: note: in expansion of macro '___PASTE' 84 | #define __PASTE(a,b) ___PASTE(a,b) | ^~~~~~~~ include/linux/compiler.h:189:37: note: in expansion of macro '__PASTE' 189 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) | ^~~~~~~ include/linux/minmax.h:105:55: note: in expansion of macro '__UNIQUE_ID' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ include/linux/compiler.h:189:45: note: each undeclared identifier is reported only once for each function it appears in 189 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) | ^~~~~~~~~~~~ include/linux/compiler.h:57:52: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:56:27: note: in expansion of macro 'is_signed_type' 56 | #define __sign_use(x,ux) (is_signed_type(typeof(ux))? \ | ^~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:84:22: note: in expansion of macro '___PASTE' 84 | #define __PASTE(a,b) ___PASTE(a,b) | ^~~~~~~~ include/linux/compiler.h:189:29: note: in expansion of macro '__PASTE' 189 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) | ^~~~~~~ include/linux/compiler_types.h:84:22: note: in expansion of macro '___PASTE' 84 | #define __PASTE(a,b) ___PASTE(a,b) | ^~~~~~~~ include/linux/compiler.h:189:37: note: in expansion of macro '__PASTE' 189 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) | ^~~~~~~ include/linux/minmax.h:105:55: note: in expansion of macro '__UNIQUE_ID' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> include/linux/minmax.h:77:36: error: first argument to '__builtin_choose_expr' not a constant 77 | #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) | ^~~~~~~~~~~~~~~~~~~~~ include/linux/compiler.h:57:52: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:79:44: note: in expansion of macro '__signed_type' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> fs/f2fs/sysfs.c:815:48: error: 'struct f2fs_sb_info' has no member named 'ndirty_inode' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~ include/linux/compiler.h:57:52: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> include/linux/minmax.h:77:36: error: first argument to '__builtin_choose_expr' not a constant 77 | #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) | ^~~~~~~~~~~~~~~~~~~~~ include/linux/compiler.h:57:52: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:79:44: note: in expansion of macro '__signed_type' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> fs/f2fs/sysfs.c:815:48: error: 'struct f2fs_sb_info' has no member named 'ndirty_inode' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~ include/linux/compiler.h:57:52: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> include/linux/minmax.h:77:36: error: first argument to '__builtin_choose_expr' not a constant 77 | #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) | ^~~~~~~~~~~~~~~~~~~~~ include/linux/compiler.h:57:61: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:79:44: note: in expansion of macro '__signed_type' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> fs/f2fs/sysfs.c:815:48: error: 'struct f2fs_sb_info' has no member named 'ndirty_inode' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~ include/linux/compiler.h:57:61: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> include/linux/minmax.h:77:36: error: first argument to '__builtin_choose_expr' not a constant 77 | #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) | ^~~~~~~~~~~~~~~~~~~~~ include/linux/compiler.h:57:61: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:79:44: note: in expansion of macro '__signed_type' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> fs/f2fs/sysfs.c:815:48: error: 'struct f2fs_sb_info' has no member named 'ndirty_inode' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~ include/linux/compiler.h:57:61: note: in definition of macro '__trace_if_var' 57 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) | ^~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> include/linux/minmax.h:77:36: error: first argument to '__builtin_choose_expr' not a constant 77 | #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) | ^~~~~~~~~~~~~~~~~~~~~ include/linux/compiler.h:68:10: note: in definition of macro '__trace_if_value' 68 | (cond) ? \ | ^~~~ include/linux/compiler.h:55:28: note: in expansion of macro '__trace_if_var' 55 | #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) ) | ^~~~~~~~~~~~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:79:44: note: in expansion of macro '__signed_type' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> fs/f2fs/sysfs.c:815:48: error: 'struct f2fs_sb_info' has no member named 'ndirty_inode' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~ include/linux/compiler.h:68:10: note: in definition of macro '__trace_if_value' 68 | (cond) ? \ | ^~~~ include/linux/compiler.h:55:28: note: in expansion of macro '__trace_if_var' 55 | #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) ) | ^~~~~~~~~~~~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> include/linux/minmax.h:77:36: error: first argument to '__builtin_choose_expr' not a constant 77 | #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) | ^~~~~~~~~~~~~~~~~~~~~ include/linux/compiler.h:68:10: note: in definition of macro '__trace_if_value' 68 | (cond) ? \ | ^~~~ include/linux/compiler.h:55:28: note: in expansion of macro '__trace_if_var' 55 | #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) ) | ^~~~~~~~~~~~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:79:44: note: in expansion of macro '__signed_type' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ >> fs/f2fs/sysfs.c:815:48: error: 'struct f2fs_sb_info' has no member named 'ndirty_inode' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~ include/linux/compiler.h:68:10: note: in definition of macro '__trace_if_value' 68 | (cond) ? \ | ^~~~ include/linux/compiler.h:55:28: note: in expansion of macro '__trace_if_var' 55 | #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) ) | ^~~~~~~~~~~~~~ include/linux/compiler_types.h:522:17: note: in expansion of macro 'if' 522 | if (!(condition)) \ | ^~ include/linux/compiler_types.h:530:9: note: in expansion of macro '__compiletime_assert' 530 | __compiletime_assert(condition, msg, prefix, suffix) | ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert' 542 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert' 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:100:9: note: in expansion of macro 'BUILD_BUG_ON_MSG' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~~~~~~~ include/linux/minmax.h:79:27: note: in expansion of macro 'statically_true' 79 | #define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) | ^~~~~~~~~~~~~~~ include/linux/minmax.h:54:36: note: in expansion of macro '__is_nonneg' 54 | #define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) | ^~~~~~~~~~~ include/linux/minmax.h:57:9: note: in expansion of macro '__signed_type_use' 57 | __signed_type_use(x,ux):__unsigned_type_use(x,ux)) | ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:82:29: note: in expansion of macro '__sign_use' 82 | (__sign_use(x,ux) & __sign_use(y,uy)) | ^~~~~~~~~~ include/linux/minmax.h:100:27: note: in expansion of macro '__types_ok' 100 | BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ | ^~~~~~~~~~ include/linux/minmax.h:105:9: note: in expansion of macro '__careful_cmp_once' 105 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) | ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:129:25: note: in expansion of macro '__careful_cmp' 129 | #define min(x, y) __careful_cmp(min, x, y) | ^~~~~~~~~~~~~ fs/f2fs/sysfs.c:815:38: note: in expansion of macro 'min' 815 | sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); | ^~~ .. vim +815 fs/f2fs/sysfs.c 676 677 if (!strcmp(a->attr.name, "atgc_candidate_ratio")) { 678 if (t > 100) 679 return -EINVAL; 680 sbi->am.candidate_ratio = t; 681 return count; 682 } 683 684 if (!strcmp(a->attr.name, "atgc_age_weight")) { 685 if (t > 100) 686 return -EINVAL; 687 sbi->am.age_weight = t; 688 return count; 689 } 690 691 if (!strcmp(a->attr.name, "gc_segment_mode")) { 692 if (t < MAX_GC_MODE) 693 sbi->gc_segment_mode = t; 694 else 695 return -EINVAL; 696 return count; 697 } 698 699 if (!strcmp(a->attr.name, "gc_pin_file_threshold")) { 700 if (t > MAX_GC_FAILED_PINNED_FILES) 701 return -EINVAL; 702 sbi->gc_pin_file_threshold = t; 703 return count; 704 } 705 706 if (!strcmp(a->attr.name, "gc_reclaimed_segments")) { 707 if (t != 0) 708 return -EINVAL; 709 sbi->gc_reclaimed_segs[sbi->gc_segment_mode] = 0; 710 return count; 711 } 712 713 if (!strcmp(a->attr.name, "seq_file_ra_mul")) { 714 if (t >= MIN_RA_MUL && t <= MAX_RA_MUL) 715 sbi->seq_file_ra_mul = t; 716 else 717 return -EINVAL; 718 return count; 719 } 720 721 if (!strcmp(a->attr.name, "max_fragment_chunk")) { 722 if (t >= MIN_FRAGMENT_SIZE && t <= MAX_FRAGMENT_SIZE) 723 sbi->max_fragment_chunk = t; 724 else 725 return -EINVAL; 726 return count; 727 } 728 729 if (!strcmp(a->attr.name, "max_fragment_hole")) { 730 if (t >= MIN_FRAGMENT_SIZE && t <= MAX_FRAGMENT_SIZE) 731 sbi->max_fragment_hole = t; 732 else 733 return -EINVAL; 734 return count; 735 } 736 737 if (!strcmp(a->attr.name, "peak_atomic_write")) { 738 if (t != 0) 739 return -EINVAL; 740 sbi->peak_atomic_write = 0; 741 return count; 742 } 743 744 if (!strcmp(a->attr.name, "committed_atomic_block")) { 745 if (t != 0) 746 return -EINVAL; 747 sbi->committed_atomic_block = 0; 748 return count; 749 } 750 751 if (!strcmp(a->attr.name, "revoked_atomic_block")) { 752 if (t != 0) 753 return -EINVAL; 754 sbi->revoked_atomic_block = 0; 755 return count; 756 } 757 758 if (!strcmp(a->attr.name, "readdir_ra")) { 759 sbi->readdir_ra = !!t; 760 return count; 761 } 762 763 if (!strcmp(a->attr.name, "hot_data_age_threshold")) { 764 if (t == 0 || t >= sbi->warm_data_age_threshold) 765 return -EINVAL; 766 if (t == *ui) 767 return count; 768 *ui = (unsigned int)t; 769 return count; 770 } 771 772 if (!strcmp(a->attr.name, "warm_data_age_threshold")) { 773 if (t <= sbi->hot_data_age_threshold) 774 return -EINVAL; 775 if (t == *ui) 776 return count; 777 *ui = (unsigned int)t; 778 return count; 779 } 780 781 if (!strcmp(a->attr.name, "last_age_weight")) { 782 if (t > 100) 783 return -EINVAL; 784 if (t == *ui) 785 return count; 786 *ui = (unsigned int)t; 787 return count; 788 } 789 790 if (!strcmp(a->attr.name, "max_read_extent_count")) { 791 if (t > UINT_MAX) 792 return -EINVAL; 793 *ui = (unsigned int)t; 794 return count; 795 } 796 797 if (!strcmp(a->attr.name, "ipu_policy")) { 798 if (t >= BIT(F2FS_IPU_MAX)) 799 return -EINVAL; 800 /* allow F2FS_IPU_NOCACHE only for IPU in the pinned file */ 801 if (f2fs_lfs_mode(sbi) && (t & ~BIT(F2FS_IPU_NOCACHE))) 802 return -EINVAL; 803 SM_I(sbi)->ipu_policy = (unsigned int)t; 804 return count; 805 } 806 807 if (!strcmp(a->attr.name, "dir_level")) { 808 if (t > MAX_DIR_HASH_DEPTH) 809 return -EINVAL; 810 sbi->dir_level = t; 811 return count; 812 } 813 814 if (!strcmp(a->attr.name, "donate_caches")) { > 815 sbi->donate_caches = min(t, sbi->ndirty_inode[DONATE_INODE]); 816 f2fs_donate_caches(sbi); 817 return count; 818 } 819 820 *ui = (unsigned int)t; 821 822 return count; 823 } 824 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 2/2 v2] f2fs: add a sysfs entry to request donate file-backed pages 2025-01-13 18:39 ` Jaegeuk Kim @ 2025-01-14 20:50 ` Jaegeuk Kim -1 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-01-14 20:50 UTC (permalink / raw) To: linux-kernel, linux-f2fs-devel 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); 4. echo 3 > /sys/fs/f2fs/blk/donate_caches will reclaim 3 page cache ranges, registered by #1, #2, and #3. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> --- Change log from v1: - don't use sbi->ndirty_inode which is not defined by default Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ fs/f2fs/f2fs.h | 4 ++++ fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ fs/f2fs/sysfs.c | 8 ++++++++ 4 files changed, 46 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 3e1630c70d8a..6f9d8b8889fd 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -828,3 +828,10 @@ Date: November 2024 Contact: "Chao Yu" <chao@kernel.org> Description: It controls max read extent count for per-inode, the value of threshold is 10240 by default. + +What: /sys/fs/f2fs/<disk>/donate_caches +Date: December 2024 +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> +Description: It reclaims the certian file-backed pages registered by + ioctl(F2FS_IOC_DONATE_RANGE). + For example, writing N tries to drop N address spaces in LRU. diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 7ce3e3eab17a..6c434ae94cb1 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { unsigned int warm_data_age_threshold; unsigned int last_age_weight; + /* control donate caches */ + unsigned int donate_caches; + /* basic filesystem units */ unsigned int log_sectors_per_block; /* log2 sectors per block */ unsigned int log_blocksize; /* log2 block size */ @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, struct shrink_control *sc); unsigned long f2fs_shrink_scan(struct shrinker *shrink, struct shrink_control *sc); +void f2fs_donate_caches(struct f2fs_sb_info *sbi); void f2fs_join_shrinker(struct f2fs_sb_info *sbi); void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index 83d6fb97dcae..a3e2063392a7 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, return freed; } +void f2fs_donate_caches(struct f2fs_sb_info *sbi) +{ + struct inode *inode = NULL; + struct f2fs_inode_info *fi; + int nfiles = sbi->donate_caches; +next: + spin_lock(&sbi->inode_lock[DONATE_INODE]); + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { + spin_unlock(&sbi->inode_lock[DONATE_INODE]); + return; + } + + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], + struct f2fs_inode_info, gdonate_list); + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); + inode = igrab(&fi->vfs_inode); + spin_unlock(&sbi->inode_lock[DONATE_INODE]); + + if (inode) { + invalidate_inode_pages2_range(inode->i_mapping, + fi->donate_start, fi->donate_end); + iput(inode); + } + if (nfiles--) + goto next; +} + void f2fs_join_shrinker(struct f2fs_sb_info *sbi) { spin_lock(&f2fs_list_lock); diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 6b99dc49f776..2a6b01257ad8 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, return count; } + if (!strcmp(a->attr.name, "donate_caches")) { + sbi->donate_caches = t; + f2fs_donate_caches(sbi); + return count; + } + *ui = (unsigned int)t; return count; @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); F2FS_SBI_GENERAL_RW_ATTR(dir_level); +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); #ifdef CONFIG_F2FS_IOSTAT F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(migration_granularity), ATTR_LIST(migration_window_granularity), ATTR_LIST(dir_level), + ATTR_LIST(donate_caches), ATTR_LIST(ram_thresh), ATTR_LIST(ra_nid_pages), ATTR_LIST(dirty_nats_ratio), -- 2.48.0.rc2.279.g1de40edade-goog _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2 v2] f2fs: add a sysfs entry to request donate file-backed pages @ 2025-01-14 20:50 ` Jaegeuk Kim 0 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim @ 2025-01-14 20:50 UTC (permalink / raw) To: linux-kernel, linux-f2fs-devel 1. ioctl(fd1, F2FS_IOC_DONATE_RANGE, {0,3}); 2. ioctl(fd2, F2FS_IOC_DONATE_RANGE, {1,2}); 3. ioctl(fd3, F2FS_IOC_DONATE_RANGE, {3,1}); 4. echo 3 > /sys/fs/f2fs/blk/donate_caches will reclaim 3 page cache ranges, registered by #1, #2, and #3. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> --- Change log from v1: - don't use sbi->ndirty_inode which is not defined by default Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++++ fs/f2fs/f2fs.h | 4 ++++ fs/f2fs/shrinker.c | 27 +++++++++++++++++++++++++ fs/f2fs/sysfs.c | 8 ++++++++ 4 files changed, 46 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 3e1630c70d8a..6f9d8b8889fd 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -828,3 +828,10 @@ Date: November 2024 Contact: "Chao Yu" <chao@kernel.org> Description: It controls max read extent count for per-inode, the value of threshold is 10240 by default. + +What: /sys/fs/f2fs/<disk>/donate_caches +Date: December 2024 +Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> +Description: It reclaims the certian file-backed pages registered by + ioctl(F2FS_IOC_DONATE_RANGE). + For example, writing N tries to drop N address spaces in LRU. diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 7ce3e3eab17a..6c434ae94cb1 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1635,6 +1635,9 @@ struct f2fs_sb_info { unsigned int warm_data_age_threshold; unsigned int last_age_weight; + /* control donate caches */ + unsigned int donate_caches; + /* basic filesystem units */ unsigned int log_sectors_per_block; /* log2 sectors per block */ unsigned int log_blocksize; /* log2 block size */ @@ -4256,6 +4259,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, struct shrink_control *sc); unsigned long f2fs_shrink_scan(struct shrinker *shrink, struct shrink_control *sc); +void f2fs_donate_caches(struct f2fs_sb_info *sbi); void f2fs_join_shrinker(struct f2fs_sb_info *sbi); void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index 83d6fb97dcae..a3e2063392a7 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c @@ -130,6 +130,33 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink, return freed; } +void f2fs_donate_caches(struct f2fs_sb_info *sbi) +{ + struct inode *inode = NULL; + struct f2fs_inode_info *fi; + int nfiles = sbi->donate_caches; +next: + spin_lock(&sbi->inode_lock[DONATE_INODE]); + if (list_empty(&sbi->inode_list[DONATE_INODE]) || !nfiles) { + spin_unlock(&sbi->inode_lock[DONATE_INODE]); + return; + } + + fi = list_first_entry(&sbi->inode_list[DONATE_INODE], + struct f2fs_inode_info, gdonate_list); + list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]); + inode = igrab(&fi->vfs_inode); + spin_unlock(&sbi->inode_lock[DONATE_INODE]); + + if (inode) { + invalidate_inode_pages2_range(inode->i_mapping, + fi->donate_start, fi->donate_end); + iput(inode); + } + if (nfiles--) + goto next; +} + void f2fs_join_shrinker(struct f2fs_sb_info *sbi) { spin_lock(&f2fs_list_lock); diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 6b99dc49f776..2a6b01257ad8 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -811,6 +811,12 @@ static ssize_t __sbi_store(struct f2fs_attr *a, return count; } + if (!strcmp(a->attr.name, "donate_caches")) { + sbi->donate_caches = t; + f2fs_donate_caches(sbi); + return count; + } + *ui = (unsigned int)t; return count; @@ -1030,6 +1036,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search); F2FS_SBI_GENERAL_RW_ATTR(migration_granularity); F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity); F2FS_SBI_GENERAL_RW_ATTR(dir_level); +F2FS_SBI_GENERAL_RW_ATTR(donate_caches); #ifdef CONFIG_F2FS_IOSTAT F2FS_SBI_GENERAL_RW_ATTR(iostat_enable); F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); @@ -1178,6 +1185,7 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(migration_granularity), ATTR_LIST(migration_window_granularity), ATTR_LIST(dir_level), + ATTR_LIST(donate_caches), ATTR_LIST(ram_thresh), ATTR_LIST(ra_nid_pages), ATTR_LIST(dirty_nats_ratio), -- 2.48.0.rc2.279.g1de40edade-goog ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages 2025-01-13 18:39 ` Jaegeuk Kim @ 2025-01-14 6:34 ` Chao Yu -1 siblings, 0 replies; 24+ messages in thread From: Chao Yu via Linux-f2fs-devel @ 2025-01-14 6:34 UTC (permalink / raw) To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: > This patch introduces an inode list to keep the page cache ranges that users > can donate pages together. > > #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > struct f2fs_donate_range) > struct f2fs_donate_range { > __u64 start; > __u64 len; > }; > > e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); I guess we need to add documentation for all ioctls including this one, maybe later? :) > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > --- > fs/f2fs/debug.c | 3 +++ > fs/f2fs/f2fs.h | 9 +++++++- > fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ > fs/f2fs/inode.c | 14 ++++++++++++ > fs/f2fs/super.c | 1 + > include/uapi/linux/f2fs.h | 7 ++++++ > 6 files changed, 81 insertions(+), 1 deletion(-) > > diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c > index 468828288a4a..1b099c123670 100644 > --- a/fs/f2fs/debug.c > +++ b/fs/f2fs/debug.c > @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) > si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); > si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; > si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; > + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; > si->nquota_files = sbi->nquota_files; > si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; > si->aw_cnt = atomic_read(&sbi->atomic_files); > @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) > si->compr_inode, si->compr_blocks); > seq_printf(s, " - Swapfile Inode: %u\n", > si->swapfile_inode); > + seq_printf(s, " - Donate Inode: %d\n", %u instead of %d due to si->ndonate_files is type of unsigned int. > + si->ndonate_files); > seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", > si->orphans, si->append, si->update); > seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index 4bfe162eefd3..7ce3e3eab17a 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -850,6 +850,11 @@ struct f2fs_inode_info { > #endif > struct list_head dirty_list; /* dirty list for dirs and files */ > struct list_head gdirty_list; /* linked in global dirty list */ > + > + /* linked in global inode list for cache donation */ > + struct list_head gdonate_list; > + loff_t donate_start, donate_end; /* inclusive */ > + > struct task_struct *atomic_write_task; /* store atomic write task */ > struct extent_tree *extent_tree[NR_EXTENT_CACHES]; > /* cached extent_tree entry */ > @@ -1274,6 +1279,7 @@ enum inode_type { > DIR_INODE, /* for dirty dir inode */ > FILE_INODE, /* for dirty regular/symlink inode */ > DIRTY_META, /* for all dirtied inode metadata */ > + DONATE_INODE, /* for all inode to donate pages */ > NR_INODE_TYPE, > }; > > @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { > unsigned long long allocated_data_blocks; > int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; > int ndirty_data, ndirty_qdata; > - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; > + unsigned int ndirty_dirs, ndirty_files, ndirty_all; > + unsigned int nquota_files, ndonate_files; > int nats, dirty_nats, sits, dirty_sits; > int free_nids, avail_nids, alloc_nids; > int total_count, utilization; > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > index 9980d17ef9f5..d6dea6258c2d 100644 > --- a/fs/f2fs/file.c > +++ b/fs/f2fs/file.c > @@ -2493,6 +2493,51 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) > return ret; > } > > +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) > +{ > + struct inode *inode = file_inode(filp); > + struct mnt_idmap *idmap = file_mnt_idmap(filp); > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > + struct f2fs_donate_range range; > + int ret; > + > + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, > + sizeof(range))) > + return -EFAULT; What about doing sanity check on donate range here? in order to avoid overflow during fi->donate_end calculation. F2FS_I(inode)->donate_end = range.start + range.len - 1; > + > + if (!inode_owner_or_capable(idmap, inode)) > + return -EACCES; > + > + if (!S_ISREG(inode->i_mode)) > + return -EINVAL; > + > + ret = mnt_want_write_file(filp); > + if (ret) > + return ret; > + > + inode_lock(inode); > + > + if (f2fs_is_atomic_file(inode)) > + goto out; > + > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > + if (list_empty(&F2FS_I(inode)->gdonate_list)) { > + list_add_tail(&F2FS_I(inode)->gdonate_list, > + &sbi->inode_list[DONATE_INODE]); > + stat_inc_dirty_inode(sbi, DONATE_INODE); > + } else { > + list_move_tail(&F2FS_I(inode)->gdonate_list, > + &sbi->inode_list[DONATE_INODE]); > + } > + F2FS_I(inode)->donate_start = range.start; > + F2FS_I(inode)->donate_end = range.start + range.len - 1; > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > +out: > + inode_unlock(inode); > + mnt_drop_write_file(filp); > + return ret; > +} > + > static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) > { > struct inode *inode = file_inode(filp); > @@ -4522,6 +4567,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) > return -EOPNOTSUPP; > case F2FS_IOC_SHUTDOWN: > return f2fs_ioc_shutdown(filp, arg); > + case F2FS_IOC_DONATE_RANGE: > + return f2fs_ioc_donate_range(filp, arg); > case FITRIM: > return f2fs_ioc_fitrim(filp, arg); > case FS_IOC_SET_ENCRYPTION_POLICY: > @@ -5273,6 +5320,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > case F2FS_IOC_RELEASE_VOLATILE_WRITE: > case F2FS_IOC_ABORT_ATOMIC_WRITE: > case F2FS_IOC_SHUTDOWN: > + case F2FS_IOC_DONATE_RANGE: > case FITRIM: > case FS_IOC_SET_ENCRYPTION_POLICY: > case FS_IOC_GET_ENCRYPTION_PWSALT: > diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c > index 7de33da8b3ea..e38dc5fe2f2e 100644 > --- a/fs/f2fs/inode.c > +++ b/fs/f2fs/inode.c > @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) > return 0; > } > > +static void f2fs_remove_donate_inode(struct inode *inode) > +{ > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > + > + if (list_empty(&F2FS_I(inode)->gdonate_list)) It will be more safe to access gdonate_list w/ inode_lock[DONATE_INODE]? Thanks, > + return; > + > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > + list_del_init(&F2FS_I(inode)->gdonate_list); > + stat_dec_dirty_inode(sbi, DONATE_INODE); > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > +} > + > /* > * Called at the last iput() if i_nlink is zero > */ > @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) > > f2fs_bug_on(sbi, get_dirty_pages(inode)); > f2fs_remove_dirty_inode(inode); > + f2fs_remove_donate_inode(inode); > > if (!IS_DEVICE_ALIASING(inode)) > f2fs_destroy_extent_tree(inode); > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > index fc7d463dee15..ef639a6d82e5 100644 > --- a/fs/f2fs/super.c > +++ b/fs/f2fs/super.c > @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) > spin_lock_init(&fi->i_size_lock); > INIT_LIST_HEAD(&fi->dirty_list); > INIT_LIST_HEAD(&fi->gdirty_list); > + INIT_LIST_HEAD(&fi->gdonate_list); > init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); > init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); > init_f2fs_rwsem(&fi->i_xattr_sem); > diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h > index f7aaf8d23e20..cd38a7c166e6 100644 > --- a/include/uapi/linux/f2fs.h > +++ b/include/uapi/linux/f2fs.h > @@ -44,6 +44,8 @@ > #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) > #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > + struct f2fs_donate_range) > > /* > * should be same as XFS_IOC_GOINGDOWN. > @@ -97,4 +99,9 @@ struct f2fs_comp_option { > __u8 log_cluster_size; > }; > > +struct f2fs_donate_range { > + __u64 start; > + __u64 len; > +}; > + > #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 ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages @ 2025-01-14 6:34 ` Chao Yu 0 siblings, 0 replies; 24+ messages in thread From: Chao Yu @ 2025-01-14 6:34 UTC (permalink / raw) To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel; +Cc: chao On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: > This patch introduces an inode list to keep the page cache ranges that users > can donate pages together. > > #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > struct f2fs_donate_range) > struct f2fs_donate_range { > __u64 start; > __u64 len; > }; > > e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); I guess we need to add documentation for all ioctls including this one, maybe later? :) > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > --- > fs/f2fs/debug.c | 3 +++ > fs/f2fs/f2fs.h | 9 +++++++- > fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ > fs/f2fs/inode.c | 14 ++++++++++++ > fs/f2fs/super.c | 1 + > include/uapi/linux/f2fs.h | 7 ++++++ > 6 files changed, 81 insertions(+), 1 deletion(-) > > diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c > index 468828288a4a..1b099c123670 100644 > --- a/fs/f2fs/debug.c > +++ b/fs/f2fs/debug.c > @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) > si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); > si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; > si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; > + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; > si->nquota_files = sbi->nquota_files; > si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; > si->aw_cnt = atomic_read(&sbi->atomic_files); > @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) > si->compr_inode, si->compr_blocks); > seq_printf(s, " - Swapfile Inode: %u\n", > si->swapfile_inode); > + seq_printf(s, " - Donate Inode: %d\n", %u instead of %d due to si->ndonate_files is type of unsigned int. > + si->ndonate_files); > seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", > si->orphans, si->append, si->update); > seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index 4bfe162eefd3..7ce3e3eab17a 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -850,6 +850,11 @@ struct f2fs_inode_info { > #endif > struct list_head dirty_list; /* dirty list for dirs and files */ > struct list_head gdirty_list; /* linked in global dirty list */ > + > + /* linked in global inode list for cache donation */ > + struct list_head gdonate_list; > + loff_t donate_start, donate_end; /* inclusive */ > + > struct task_struct *atomic_write_task; /* store atomic write task */ > struct extent_tree *extent_tree[NR_EXTENT_CACHES]; > /* cached extent_tree entry */ > @@ -1274,6 +1279,7 @@ enum inode_type { > DIR_INODE, /* for dirty dir inode */ > FILE_INODE, /* for dirty regular/symlink inode */ > DIRTY_META, /* for all dirtied inode metadata */ > + DONATE_INODE, /* for all inode to donate pages */ > NR_INODE_TYPE, > }; > > @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { > unsigned long long allocated_data_blocks; > int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; > int ndirty_data, ndirty_qdata; > - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; > + unsigned int ndirty_dirs, ndirty_files, ndirty_all; > + unsigned int nquota_files, ndonate_files; > int nats, dirty_nats, sits, dirty_sits; > int free_nids, avail_nids, alloc_nids; > int total_count, utilization; > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > index 9980d17ef9f5..d6dea6258c2d 100644 > --- a/fs/f2fs/file.c > +++ b/fs/f2fs/file.c > @@ -2493,6 +2493,51 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) > return ret; > } > > +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) > +{ > + struct inode *inode = file_inode(filp); > + struct mnt_idmap *idmap = file_mnt_idmap(filp); > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > + struct f2fs_donate_range range; > + int ret; > + > + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, > + sizeof(range))) > + return -EFAULT; What about doing sanity check on donate range here? in order to avoid overflow during fi->donate_end calculation. F2FS_I(inode)->donate_end = range.start + range.len - 1; > + > + if (!inode_owner_or_capable(idmap, inode)) > + return -EACCES; > + > + if (!S_ISREG(inode->i_mode)) > + return -EINVAL; > + > + ret = mnt_want_write_file(filp); > + if (ret) > + return ret; > + > + inode_lock(inode); > + > + if (f2fs_is_atomic_file(inode)) > + goto out; > + > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > + if (list_empty(&F2FS_I(inode)->gdonate_list)) { > + list_add_tail(&F2FS_I(inode)->gdonate_list, > + &sbi->inode_list[DONATE_INODE]); > + stat_inc_dirty_inode(sbi, DONATE_INODE); > + } else { > + list_move_tail(&F2FS_I(inode)->gdonate_list, > + &sbi->inode_list[DONATE_INODE]); > + } > + F2FS_I(inode)->donate_start = range.start; > + F2FS_I(inode)->donate_end = range.start + range.len - 1; > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > +out: > + inode_unlock(inode); > + mnt_drop_write_file(filp); > + return ret; > +} > + > static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) > { > struct inode *inode = file_inode(filp); > @@ -4522,6 +4567,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) > return -EOPNOTSUPP; > case F2FS_IOC_SHUTDOWN: > return f2fs_ioc_shutdown(filp, arg); > + case F2FS_IOC_DONATE_RANGE: > + return f2fs_ioc_donate_range(filp, arg); > case FITRIM: > return f2fs_ioc_fitrim(filp, arg); > case FS_IOC_SET_ENCRYPTION_POLICY: > @@ -5273,6 +5320,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > case F2FS_IOC_RELEASE_VOLATILE_WRITE: > case F2FS_IOC_ABORT_ATOMIC_WRITE: > case F2FS_IOC_SHUTDOWN: > + case F2FS_IOC_DONATE_RANGE: > case FITRIM: > case FS_IOC_SET_ENCRYPTION_POLICY: > case FS_IOC_GET_ENCRYPTION_PWSALT: > diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c > index 7de33da8b3ea..e38dc5fe2f2e 100644 > --- a/fs/f2fs/inode.c > +++ b/fs/f2fs/inode.c > @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) > return 0; > } > > +static void f2fs_remove_donate_inode(struct inode *inode) > +{ > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > + > + if (list_empty(&F2FS_I(inode)->gdonate_list)) It will be more safe to access gdonate_list w/ inode_lock[DONATE_INODE]? Thanks, > + return; > + > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > + list_del_init(&F2FS_I(inode)->gdonate_list); > + stat_dec_dirty_inode(sbi, DONATE_INODE); > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > +} > + > /* > * Called at the last iput() if i_nlink is zero > */ > @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) > > f2fs_bug_on(sbi, get_dirty_pages(inode)); > f2fs_remove_dirty_inode(inode); > + f2fs_remove_donate_inode(inode); > > if (!IS_DEVICE_ALIASING(inode)) > f2fs_destroy_extent_tree(inode); > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > index fc7d463dee15..ef639a6d82e5 100644 > --- a/fs/f2fs/super.c > +++ b/fs/f2fs/super.c > @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) > spin_lock_init(&fi->i_size_lock); > INIT_LIST_HEAD(&fi->dirty_list); > INIT_LIST_HEAD(&fi->gdirty_list); > + INIT_LIST_HEAD(&fi->gdonate_list); > init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); > init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); > init_f2fs_rwsem(&fi->i_xattr_sem); > diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h > index f7aaf8d23e20..cd38a7c166e6 100644 > --- a/include/uapi/linux/f2fs.h > +++ b/include/uapi/linux/f2fs.h > @@ -44,6 +44,8 @@ > #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) > #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > + struct f2fs_donate_range) > > /* > * should be same as XFS_IOC_GOINGDOWN. > @@ -97,4 +99,9 @@ struct f2fs_comp_option { > __u8 log_cluster_size; > }; > > +struct f2fs_donate_range { > + __u64 start; > + __u64 len; > +}; > + > #endif /* _UAPI_LINUX_F2FS_H */ ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages 2025-01-14 6:34 ` Chao Yu @ 2025-01-14 17:15 ` Jaegeuk Kim -1 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-01-14 17:15 UTC (permalink / raw) To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel On 01/14, Chao Yu wrote: > On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: > > This patch introduces an inode list to keep the page cache ranges that users > > can donate pages together. > > > > #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > > struct f2fs_donate_range) > > struct f2fs_donate_range { > > __u64 start; > > __u64 len; > > }; > > > > e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); > > I guess we need to add documentation for all ioctls including this one, maybe > later? :) Yeah, later. > > > > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > > --- > > fs/f2fs/debug.c | 3 +++ > > fs/f2fs/f2fs.h | 9 +++++++- > > fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ > > fs/f2fs/inode.c | 14 ++++++++++++ > > fs/f2fs/super.c | 1 + > > include/uapi/linux/f2fs.h | 7 ++++++ > > 6 files changed, 81 insertions(+), 1 deletion(-) > > > > diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c > > index 468828288a4a..1b099c123670 100644 > > --- a/fs/f2fs/debug.c > > +++ b/fs/f2fs/debug.c > > @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) > > si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); > > si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; > > si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; > > + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; > > si->nquota_files = sbi->nquota_files; > > si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; > > si->aw_cnt = atomic_read(&sbi->atomic_files); > > @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) > > si->compr_inode, si->compr_blocks); > > seq_printf(s, " - Swapfile Inode: %u\n", > > si->swapfile_inode); > > + seq_printf(s, " - Donate Inode: %d\n", > > %u instead of %d due to si->ndonate_files is type of unsigned int. > > > + si->ndonate_files); > > seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", > > si->orphans, si->append, si->update); > > seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > > index 4bfe162eefd3..7ce3e3eab17a 100644 > > --- a/fs/f2fs/f2fs.h > > +++ b/fs/f2fs/f2fs.h > > @@ -850,6 +850,11 @@ struct f2fs_inode_info { > > #endif > > struct list_head dirty_list; /* dirty list for dirs and files */ > > struct list_head gdirty_list; /* linked in global dirty list */ > > + > > + /* linked in global inode list for cache donation */ > > + struct list_head gdonate_list; > > + loff_t donate_start, donate_end; /* inclusive */ > > + > > struct task_struct *atomic_write_task; /* store atomic write task */ > > struct extent_tree *extent_tree[NR_EXTENT_CACHES]; > > /* cached extent_tree entry */ > > @@ -1274,6 +1279,7 @@ enum inode_type { > > DIR_INODE, /* for dirty dir inode */ > > FILE_INODE, /* for dirty regular/symlink inode */ > > DIRTY_META, /* for all dirtied inode metadata */ > > + DONATE_INODE, /* for all inode to donate pages */ > > NR_INODE_TYPE, > > }; > > @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { > > unsigned long long allocated_data_blocks; > > int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; > > int ndirty_data, ndirty_qdata; > > - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; > > + unsigned int ndirty_dirs, ndirty_files, ndirty_all; > > + unsigned int nquota_files, ndonate_files; > > int nats, dirty_nats, sits, dirty_sits; > > int free_nids, avail_nids, alloc_nids; > > int total_count, utilization; > > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > > index 9980d17ef9f5..d6dea6258c2d 100644 > > --- a/fs/f2fs/file.c > > +++ b/fs/f2fs/file.c > > @@ -2493,6 +2493,51 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) > > return ret; > > } > > +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) > > +{ > > + struct inode *inode = file_inode(filp); > > + struct mnt_idmap *idmap = file_mnt_idmap(filp); > > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > > + struct f2fs_donate_range range; > > + int ret; > > + > > + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, > > + sizeof(range))) > > + return -EFAULT; > > What about doing sanity check on donate range here? in order to avoid overflow > during fi->donate_end calculation. > > F2FS_I(inode)->donate_end = range.start + range.len - 1; > > > + > > + if (!inode_owner_or_capable(idmap, inode)) > > + return -EACCES; > > + > > + if (!S_ISREG(inode->i_mode)) > > + return -EINVAL; > > + > > + ret = mnt_want_write_file(filp); > > + if (ret) > > + return ret; > > + > > + inode_lock(inode); > > + > > + if (f2fs_is_atomic_file(inode)) > > + goto out; > > + > > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > > + if (list_empty(&F2FS_I(inode)->gdonate_list)) { > > + list_add_tail(&F2FS_I(inode)->gdonate_list, > > + &sbi->inode_list[DONATE_INODE]); > > + stat_inc_dirty_inode(sbi, DONATE_INODE); > > + } else { > > + list_move_tail(&F2FS_I(inode)->gdonate_list, > > + &sbi->inode_list[DONATE_INODE]); > > + } > > + F2FS_I(inode)->donate_start = range.start; > > + F2FS_I(inode)->donate_end = range.start + range.len - 1; > > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > > +out: > > + inode_unlock(inode); > > + mnt_drop_write_file(filp); > > + return ret; > > +} > > + > > static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) > > { > > struct inode *inode = file_inode(filp); > > @@ -4522,6 +4567,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) > > return -EOPNOTSUPP; > > case F2FS_IOC_SHUTDOWN: > > return f2fs_ioc_shutdown(filp, arg); > > + case F2FS_IOC_DONATE_RANGE: > > + return f2fs_ioc_donate_range(filp, arg); > > case FITRIM: > > return f2fs_ioc_fitrim(filp, arg); > > case FS_IOC_SET_ENCRYPTION_POLICY: > > @@ -5273,6 +5320,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > > case F2FS_IOC_RELEASE_VOLATILE_WRITE: > > case F2FS_IOC_ABORT_ATOMIC_WRITE: > > case F2FS_IOC_SHUTDOWN: > > + case F2FS_IOC_DONATE_RANGE: > > case FITRIM: > > case FS_IOC_SET_ENCRYPTION_POLICY: > > case FS_IOC_GET_ENCRYPTION_PWSALT: > > diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c > > index 7de33da8b3ea..e38dc5fe2f2e 100644 > > --- a/fs/f2fs/inode.c > > +++ b/fs/f2fs/inode.c > > @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) > > return 0; > > } > > +static void f2fs_remove_donate_inode(struct inode *inode) > > +{ > > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > > + > > + if (list_empty(&F2FS_I(inode)->gdonate_list)) > > It will be more safe to access gdonate_list w/ inode_lock[DONATE_INODE]? It's unnecessary as this is called from evict_inode. > > Thanks, > > > + return; > > + > > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > > + list_del_init(&F2FS_I(inode)->gdonate_list); > > + stat_dec_dirty_inode(sbi, DONATE_INODE); > > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > > +} > > + > > /* > > * Called at the last iput() if i_nlink is zero > > */ > > @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) > > f2fs_bug_on(sbi, get_dirty_pages(inode)); > > f2fs_remove_dirty_inode(inode); > > + f2fs_remove_donate_inode(inode); > > if (!IS_DEVICE_ALIASING(inode)) > > f2fs_destroy_extent_tree(inode); > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > > index fc7d463dee15..ef639a6d82e5 100644 > > --- a/fs/f2fs/super.c > > +++ b/fs/f2fs/super.c > > @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) > > spin_lock_init(&fi->i_size_lock); > > INIT_LIST_HEAD(&fi->dirty_list); > > INIT_LIST_HEAD(&fi->gdirty_list); > > + INIT_LIST_HEAD(&fi->gdonate_list); > > init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); > > init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); > > init_f2fs_rwsem(&fi->i_xattr_sem); > > diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h > > index f7aaf8d23e20..cd38a7c166e6 100644 > > --- a/include/uapi/linux/f2fs.h > > +++ b/include/uapi/linux/f2fs.h > > @@ -44,6 +44,8 @@ > > #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) > > #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > > + struct f2fs_donate_range) > > /* > > * should be same as XFS_IOC_GOINGDOWN. > > @@ -97,4 +99,9 @@ struct f2fs_comp_option { > > __u8 log_cluster_size; > > }; > > +struct f2fs_donate_range { > > + __u64 start; > > + __u64 len; > > +}; > > + > > #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 ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages @ 2025-01-14 17:15 ` Jaegeuk Kim 0 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim @ 2025-01-14 17:15 UTC (permalink / raw) To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel On 01/14, Chao Yu wrote: > On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: > > This patch introduces an inode list to keep the page cache ranges that users > > can donate pages together. > > > > #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > > struct f2fs_donate_range) > > struct f2fs_donate_range { > > __u64 start; > > __u64 len; > > }; > > > > e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); > > I guess we need to add documentation for all ioctls including this one, maybe > later? :) Yeah, later. > > > > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > > --- > > fs/f2fs/debug.c | 3 +++ > > fs/f2fs/f2fs.h | 9 +++++++- > > fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ > > fs/f2fs/inode.c | 14 ++++++++++++ > > fs/f2fs/super.c | 1 + > > include/uapi/linux/f2fs.h | 7 ++++++ > > 6 files changed, 81 insertions(+), 1 deletion(-) > > > > diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c > > index 468828288a4a..1b099c123670 100644 > > --- a/fs/f2fs/debug.c > > +++ b/fs/f2fs/debug.c > > @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) > > si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); > > si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; > > si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; > > + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; > > si->nquota_files = sbi->nquota_files; > > si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; > > si->aw_cnt = atomic_read(&sbi->atomic_files); > > @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) > > si->compr_inode, si->compr_blocks); > > seq_printf(s, " - Swapfile Inode: %u\n", > > si->swapfile_inode); > > + seq_printf(s, " - Donate Inode: %d\n", > > %u instead of %d due to si->ndonate_files is type of unsigned int. > > > + si->ndonate_files); > > seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", > > si->orphans, si->append, si->update); > > seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > > index 4bfe162eefd3..7ce3e3eab17a 100644 > > --- a/fs/f2fs/f2fs.h > > +++ b/fs/f2fs/f2fs.h > > @@ -850,6 +850,11 @@ struct f2fs_inode_info { > > #endif > > struct list_head dirty_list; /* dirty list for dirs and files */ > > struct list_head gdirty_list; /* linked in global dirty list */ > > + > > + /* linked in global inode list for cache donation */ > > + struct list_head gdonate_list; > > + loff_t donate_start, donate_end; /* inclusive */ > > + > > struct task_struct *atomic_write_task; /* store atomic write task */ > > struct extent_tree *extent_tree[NR_EXTENT_CACHES]; > > /* cached extent_tree entry */ > > @@ -1274,6 +1279,7 @@ enum inode_type { > > DIR_INODE, /* for dirty dir inode */ > > FILE_INODE, /* for dirty regular/symlink inode */ > > DIRTY_META, /* for all dirtied inode metadata */ > > + DONATE_INODE, /* for all inode to donate pages */ > > NR_INODE_TYPE, > > }; > > @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { > > unsigned long long allocated_data_blocks; > > int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; > > int ndirty_data, ndirty_qdata; > > - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; > > + unsigned int ndirty_dirs, ndirty_files, ndirty_all; > > + unsigned int nquota_files, ndonate_files; > > int nats, dirty_nats, sits, dirty_sits; > > int free_nids, avail_nids, alloc_nids; > > int total_count, utilization; > > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > > index 9980d17ef9f5..d6dea6258c2d 100644 > > --- a/fs/f2fs/file.c > > +++ b/fs/f2fs/file.c > > @@ -2493,6 +2493,51 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) > > return ret; > > } > > +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) > > +{ > > + struct inode *inode = file_inode(filp); > > + struct mnt_idmap *idmap = file_mnt_idmap(filp); > > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > > + struct f2fs_donate_range range; > > + int ret; > > + > > + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, > > + sizeof(range))) > > + return -EFAULT; > > What about doing sanity check on donate range here? in order to avoid overflow > during fi->donate_end calculation. > > F2FS_I(inode)->donate_end = range.start + range.len - 1; > > > + > > + if (!inode_owner_or_capable(idmap, inode)) > > + return -EACCES; > > + > > + if (!S_ISREG(inode->i_mode)) > > + return -EINVAL; > > + > > + ret = mnt_want_write_file(filp); > > + if (ret) > > + return ret; > > + > > + inode_lock(inode); > > + > > + if (f2fs_is_atomic_file(inode)) > > + goto out; > > + > > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > > + if (list_empty(&F2FS_I(inode)->gdonate_list)) { > > + list_add_tail(&F2FS_I(inode)->gdonate_list, > > + &sbi->inode_list[DONATE_INODE]); > > + stat_inc_dirty_inode(sbi, DONATE_INODE); > > + } else { > > + list_move_tail(&F2FS_I(inode)->gdonate_list, > > + &sbi->inode_list[DONATE_INODE]); > > + } > > + F2FS_I(inode)->donate_start = range.start; > > + F2FS_I(inode)->donate_end = range.start + range.len - 1; > > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > > +out: > > + inode_unlock(inode); > > + mnt_drop_write_file(filp); > > + return ret; > > +} > > + > > static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) > > { > > struct inode *inode = file_inode(filp); > > @@ -4522,6 +4567,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) > > return -EOPNOTSUPP; > > case F2FS_IOC_SHUTDOWN: > > return f2fs_ioc_shutdown(filp, arg); > > + case F2FS_IOC_DONATE_RANGE: > > + return f2fs_ioc_donate_range(filp, arg); > > case FITRIM: > > return f2fs_ioc_fitrim(filp, arg); > > case FS_IOC_SET_ENCRYPTION_POLICY: > > @@ -5273,6 +5320,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > > case F2FS_IOC_RELEASE_VOLATILE_WRITE: > > case F2FS_IOC_ABORT_ATOMIC_WRITE: > > case F2FS_IOC_SHUTDOWN: > > + case F2FS_IOC_DONATE_RANGE: > > case FITRIM: > > case FS_IOC_SET_ENCRYPTION_POLICY: > > case FS_IOC_GET_ENCRYPTION_PWSALT: > > diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c > > index 7de33da8b3ea..e38dc5fe2f2e 100644 > > --- a/fs/f2fs/inode.c > > +++ b/fs/f2fs/inode.c > > @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) > > return 0; > > } > > +static void f2fs_remove_donate_inode(struct inode *inode) > > +{ > > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > > + > > + if (list_empty(&F2FS_I(inode)->gdonate_list)) > > It will be more safe to access gdonate_list w/ inode_lock[DONATE_INODE]? It's unnecessary as this is called from evict_inode. > > Thanks, > > > + return; > > + > > + spin_lock(&sbi->inode_lock[DONATE_INODE]); > > + list_del_init(&F2FS_I(inode)->gdonate_list); > > + stat_dec_dirty_inode(sbi, DONATE_INODE); > > + spin_unlock(&sbi->inode_lock[DONATE_INODE]); > > +} > > + > > /* > > * Called at the last iput() if i_nlink is zero > > */ > > @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) > > f2fs_bug_on(sbi, get_dirty_pages(inode)); > > f2fs_remove_dirty_inode(inode); > > + f2fs_remove_donate_inode(inode); > > if (!IS_DEVICE_ALIASING(inode)) > > f2fs_destroy_extent_tree(inode); > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > > index fc7d463dee15..ef639a6d82e5 100644 > > --- a/fs/f2fs/super.c > > +++ b/fs/f2fs/super.c > > @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) > > spin_lock_init(&fi->i_size_lock); > > INIT_LIST_HEAD(&fi->dirty_list); > > INIT_LIST_HEAD(&fi->gdirty_list); > > + INIT_LIST_HEAD(&fi->gdonate_list); > > init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); > > init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); > > init_f2fs_rwsem(&fi->i_xattr_sem); > > diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h > > index f7aaf8d23e20..cd38a7c166e6 100644 > > --- a/include/uapi/linux/f2fs.h > > +++ b/include/uapi/linux/f2fs.h > > @@ -44,6 +44,8 @@ > > #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) > > #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > > + struct f2fs_donate_range) > > /* > > * should be same as XFS_IOC_GOINGDOWN. > > @@ -97,4 +99,9 @@ struct f2fs_comp_option { > > __u8 log_cluster_size; > > }; > > +struct f2fs_donate_range { > > + __u64 start; > > + __u64 len; > > +}; > > + > > #endif /* _UAPI_LINUX_F2FS_H */ ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages 2025-01-14 17:15 ` Jaegeuk Kim @ 2025-01-15 2:12 ` Chao Yu -1 siblings, 0 replies; 24+ messages in thread From: Chao Yu via Linux-f2fs-devel @ 2025-01-15 2:12 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel On 1/15/25 01:15, Jaegeuk Kim wrote: > On 01/14, Chao Yu wrote: >> On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: >>> This patch introduces an inode list to keep the page cache ranges that users >>> can donate pages together. >>> >>> #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ >>> struct f2fs_donate_range) >>> struct f2fs_donate_range { >>> __u64 start; >>> __u64 len; >>> }; >>> >>> e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); >> >> I guess we need to add documentation for all ioctls including this one, maybe >> later? :) > > Yeah, later. > >> >>> >>> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> >>> --- >>> fs/f2fs/debug.c | 3 +++ >>> fs/f2fs/f2fs.h | 9 +++++++- >>> fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ >>> fs/f2fs/inode.c | 14 ++++++++++++ >>> fs/f2fs/super.c | 1 + >>> include/uapi/linux/f2fs.h | 7 ++++++ >>> 6 files changed, 81 insertions(+), 1 deletion(-) >>> >>> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c >>> index 468828288a4a..1b099c123670 100644 >>> --- a/fs/f2fs/debug.c >>> +++ b/fs/f2fs/debug.c >>> @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) >>> si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); >>> si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; >>> si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; >>> + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; >>> si->nquota_files = sbi->nquota_files; >>> si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; >>> si->aw_cnt = atomic_read(&sbi->atomic_files); >>> @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) >>> si->compr_inode, si->compr_blocks); >>> seq_printf(s, " - Swapfile Inode: %u\n", >>> si->swapfile_inode); >>> + seq_printf(s, " - Donate Inode: %d\n", >> >> %u instead of %d due to si->ndonate_files is type of unsigned int. >> >>> + si->ndonate_files); >>> seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", >>> si->orphans, si->append, si->update); >>> seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h >>> index 4bfe162eefd3..7ce3e3eab17a 100644 >>> --- a/fs/f2fs/f2fs.h >>> +++ b/fs/f2fs/f2fs.h >>> @@ -850,6 +850,11 @@ struct f2fs_inode_info { >>> #endif >>> struct list_head dirty_list; /* dirty list for dirs and files */ >>> struct list_head gdirty_list; /* linked in global dirty list */ >>> + >>> + /* linked in global inode list for cache donation */ >>> + struct list_head gdonate_list; >>> + loff_t donate_start, donate_end; /* inclusive */ >>> + >>> struct task_struct *atomic_write_task; /* store atomic write task */ >>> struct extent_tree *extent_tree[NR_EXTENT_CACHES]; >>> /* cached extent_tree entry */ >>> @@ -1274,6 +1279,7 @@ enum inode_type { >>> DIR_INODE, /* for dirty dir inode */ >>> FILE_INODE, /* for dirty regular/symlink inode */ >>> DIRTY_META, /* for all dirtied inode metadata */ >>> + DONATE_INODE, /* for all inode to donate pages */ >>> NR_INODE_TYPE, >>> }; >>> @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { >>> unsigned long long allocated_data_blocks; >>> int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; >>> int ndirty_data, ndirty_qdata; >>> - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; >>> + unsigned int ndirty_dirs, ndirty_files, ndirty_all; >>> + unsigned int nquota_files, ndonate_files; >>> int nats, dirty_nats, sits, dirty_sits; >>> int free_nids, avail_nids, alloc_nids; >>> int total_count, utilization; >>> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c >>> index 9980d17ef9f5..d6dea6258c2d 100644 >>> --- a/fs/f2fs/file.c >>> +++ b/fs/f2fs/file.c >>> @@ -2493,6 +2493,51 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) >>> return ret; >>> } >>> +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) >>> +{ >>> + struct inode *inode = file_inode(filp); >>> + struct mnt_idmap *idmap = file_mnt_idmap(filp); >>> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); >>> + struct f2fs_donate_range range; >>> + int ret; >>> + >>> + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, >>> + sizeof(range))) >>> + return -EFAULT; >> >> What about doing sanity check on donate range here? in order to avoid overflow >> during fi->donate_end calculation. >> >> F2FS_I(inode)->donate_end = range.start + range.len - 1; >> >>> + >>> + if (!inode_owner_or_capable(idmap, inode)) >>> + return -EACCES; >>> + >>> + if (!S_ISREG(inode->i_mode)) >>> + return -EINVAL; >>> + >>> + ret = mnt_want_write_file(filp); >>> + if (ret) >>> + return ret; >>> + >>> + inode_lock(inode); >>> + >>> + if (f2fs_is_atomic_file(inode)) >>> + goto out; >>> + >>> + spin_lock(&sbi->inode_lock[DONATE_INODE]); >>> + if (list_empty(&F2FS_I(inode)->gdonate_list)) { >>> + list_add_tail(&F2FS_I(inode)->gdonate_list, >>> + &sbi->inode_list[DONATE_INODE]); >>> + stat_inc_dirty_inode(sbi, DONATE_INODE); >>> + } else { >>> + list_move_tail(&F2FS_I(inode)->gdonate_list, >>> + &sbi->inode_list[DONATE_INODE]); >>> + } >>> + F2FS_I(inode)->donate_start = range.start; >>> + F2FS_I(inode)->donate_end = range.start + range.len - 1; >>> + spin_unlock(&sbi->inode_lock[DONATE_INODE]); >>> +out: >>> + inode_unlock(inode); >>> + mnt_drop_write_file(filp); >>> + return ret; >>> +} >>> + >>> static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) >>> { >>> struct inode *inode = file_inode(filp); >>> @@ -4522,6 +4567,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) >>> return -EOPNOTSUPP; >>> case F2FS_IOC_SHUTDOWN: >>> return f2fs_ioc_shutdown(filp, arg); >>> + case F2FS_IOC_DONATE_RANGE: >>> + return f2fs_ioc_donate_range(filp, arg); >>> case FITRIM: >>> return f2fs_ioc_fitrim(filp, arg); >>> case FS_IOC_SET_ENCRYPTION_POLICY: >>> @@ -5273,6 +5320,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) >>> case F2FS_IOC_RELEASE_VOLATILE_WRITE: >>> case F2FS_IOC_ABORT_ATOMIC_WRITE: >>> case F2FS_IOC_SHUTDOWN: >>> + case F2FS_IOC_DONATE_RANGE: >>> case FITRIM: >>> case FS_IOC_SET_ENCRYPTION_POLICY: >>> case FS_IOC_GET_ENCRYPTION_PWSALT: >>> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c >>> index 7de33da8b3ea..e38dc5fe2f2e 100644 >>> --- a/fs/f2fs/inode.c >>> +++ b/fs/f2fs/inode.c >>> @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) >>> return 0; >>> } >>> +static void f2fs_remove_donate_inode(struct inode *inode) >>> +{ >>> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); >>> + >>> + if (list_empty(&F2FS_I(inode)->gdonate_list)) >> >> It will be more safe to access gdonate_list w/ inode_lock[DONATE_INODE]? > > It's unnecessary as this is called from evict_inode. I just concerned about the case fi->gdonate_list's prev and next pointer can be updated in race condition due to insertion or deletion of its adjacent entry. No risk now as I checked. :) Thanks, > >> >> Thanks, >> >>> + return; >>> + >>> + spin_lock(&sbi->inode_lock[DONATE_INODE]); >>> + list_del_init(&F2FS_I(inode)->gdonate_list); >>> + stat_dec_dirty_inode(sbi, DONATE_INODE); >>> + spin_unlock(&sbi->inode_lock[DONATE_INODE]); >>> +} >>> + >>> /* >>> * Called at the last iput() if i_nlink is zero >>> */ >>> @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) >>> f2fs_bug_on(sbi, get_dirty_pages(inode)); >>> f2fs_remove_dirty_inode(inode); >>> + f2fs_remove_donate_inode(inode); >>> if (!IS_DEVICE_ALIASING(inode)) >>> f2fs_destroy_extent_tree(inode); >>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c >>> index fc7d463dee15..ef639a6d82e5 100644 >>> --- a/fs/f2fs/super.c >>> +++ b/fs/f2fs/super.c >>> @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) >>> spin_lock_init(&fi->i_size_lock); >>> INIT_LIST_HEAD(&fi->dirty_list); >>> INIT_LIST_HEAD(&fi->gdirty_list); >>> + INIT_LIST_HEAD(&fi->gdonate_list); >>> init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); >>> init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); >>> init_f2fs_rwsem(&fi->i_xattr_sem); >>> diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h >>> index f7aaf8d23e20..cd38a7c166e6 100644 >>> --- a/include/uapi/linux/f2fs.h >>> +++ b/include/uapi/linux/f2fs.h >>> @@ -44,6 +44,8 @@ >>> #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) >>> #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ >>> + struct f2fs_donate_range) >>> /* >>> * should be same as XFS_IOC_GOINGDOWN. >>> @@ -97,4 +99,9 @@ struct f2fs_comp_option { >>> __u8 log_cluster_size; >>> }; >>> +struct f2fs_donate_range { >>> + __u64 start; >>> + __u64 len; >>> +}; >>> + >>> #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 ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages @ 2025-01-15 2:12 ` Chao Yu 0 siblings, 0 replies; 24+ messages in thread From: Chao Yu @ 2025-01-15 2:12 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: chao, linux-kernel, linux-f2fs-devel On 1/15/25 01:15, Jaegeuk Kim wrote: > On 01/14, Chao Yu wrote: >> On 1/14/25 02:39, Jaegeuk Kim via Linux-f2fs-devel wrote: >>> This patch introduces an inode list to keep the page cache ranges that users >>> can donate pages together. >>> >>> #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ >>> struct f2fs_donate_range) >>> struct f2fs_donate_range { >>> __u64 start; >>> __u64 len; >>> }; >>> >>> e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); >> >> I guess we need to add documentation for all ioctls including this one, maybe >> later? :) > > Yeah, later. > >> >>> >>> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> >>> --- >>> fs/f2fs/debug.c | 3 +++ >>> fs/f2fs/f2fs.h | 9 +++++++- >>> fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ >>> fs/f2fs/inode.c | 14 ++++++++++++ >>> fs/f2fs/super.c | 1 + >>> include/uapi/linux/f2fs.h | 7 ++++++ >>> 6 files changed, 81 insertions(+), 1 deletion(-) >>> >>> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c >>> index 468828288a4a..1b099c123670 100644 >>> --- a/fs/f2fs/debug.c >>> +++ b/fs/f2fs/debug.c >>> @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) >>> si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); >>> si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; >>> si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; >>> + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; >>> si->nquota_files = sbi->nquota_files; >>> si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; >>> si->aw_cnt = atomic_read(&sbi->atomic_files); >>> @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) >>> si->compr_inode, si->compr_blocks); >>> seq_printf(s, " - Swapfile Inode: %u\n", >>> si->swapfile_inode); >>> + seq_printf(s, " - Donate Inode: %d\n", >> >> %u instead of %d due to si->ndonate_files is type of unsigned int. >> >>> + si->ndonate_files); >>> seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", >>> si->orphans, si->append, si->update); >>> seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h >>> index 4bfe162eefd3..7ce3e3eab17a 100644 >>> --- a/fs/f2fs/f2fs.h >>> +++ b/fs/f2fs/f2fs.h >>> @@ -850,6 +850,11 @@ struct f2fs_inode_info { >>> #endif >>> struct list_head dirty_list; /* dirty list for dirs and files */ >>> struct list_head gdirty_list; /* linked in global dirty list */ >>> + >>> + /* linked in global inode list for cache donation */ >>> + struct list_head gdonate_list; >>> + loff_t donate_start, donate_end; /* inclusive */ >>> + >>> struct task_struct *atomic_write_task; /* store atomic write task */ >>> struct extent_tree *extent_tree[NR_EXTENT_CACHES]; >>> /* cached extent_tree entry */ >>> @@ -1274,6 +1279,7 @@ enum inode_type { >>> DIR_INODE, /* for dirty dir inode */ >>> FILE_INODE, /* for dirty regular/symlink inode */ >>> DIRTY_META, /* for all dirtied inode metadata */ >>> + DONATE_INODE, /* for all inode to donate pages */ >>> NR_INODE_TYPE, >>> }; >>> @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { >>> unsigned long long allocated_data_blocks; >>> int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; >>> int ndirty_data, ndirty_qdata; >>> - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; >>> + unsigned int ndirty_dirs, ndirty_files, ndirty_all; >>> + unsigned int nquota_files, ndonate_files; >>> int nats, dirty_nats, sits, dirty_sits; >>> int free_nids, avail_nids, alloc_nids; >>> int total_count, utilization; >>> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c >>> index 9980d17ef9f5..d6dea6258c2d 100644 >>> --- a/fs/f2fs/file.c >>> +++ b/fs/f2fs/file.c >>> @@ -2493,6 +2493,51 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) >>> return ret; >>> } >>> +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) >>> +{ >>> + struct inode *inode = file_inode(filp); >>> + struct mnt_idmap *idmap = file_mnt_idmap(filp); >>> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); >>> + struct f2fs_donate_range range; >>> + int ret; >>> + >>> + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, >>> + sizeof(range))) >>> + return -EFAULT; >> >> What about doing sanity check on donate range here? in order to avoid overflow >> during fi->donate_end calculation. >> >> F2FS_I(inode)->donate_end = range.start + range.len - 1; >> >>> + >>> + if (!inode_owner_or_capable(idmap, inode)) >>> + return -EACCES; >>> + >>> + if (!S_ISREG(inode->i_mode)) >>> + return -EINVAL; >>> + >>> + ret = mnt_want_write_file(filp); >>> + if (ret) >>> + return ret; >>> + >>> + inode_lock(inode); >>> + >>> + if (f2fs_is_atomic_file(inode)) >>> + goto out; >>> + >>> + spin_lock(&sbi->inode_lock[DONATE_INODE]); >>> + if (list_empty(&F2FS_I(inode)->gdonate_list)) { >>> + list_add_tail(&F2FS_I(inode)->gdonate_list, >>> + &sbi->inode_list[DONATE_INODE]); >>> + stat_inc_dirty_inode(sbi, DONATE_INODE); >>> + } else { >>> + list_move_tail(&F2FS_I(inode)->gdonate_list, >>> + &sbi->inode_list[DONATE_INODE]); >>> + } >>> + F2FS_I(inode)->donate_start = range.start; >>> + F2FS_I(inode)->donate_end = range.start + range.len - 1; >>> + spin_unlock(&sbi->inode_lock[DONATE_INODE]); >>> +out: >>> + inode_unlock(inode); >>> + mnt_drop_write_file(filp); >>> + return ret; >>> +} >>> + >>> static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) >>> { >>> struct inode *inode = file_inode(filp); >>> @@ -4522,6 +4567,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) >>> return -EOPNOTSUPP; >>> case F2FS_IOC_SHUTDOWN: >>> return f2fs_ioc_shutdown(filp, arg); >>> + case F2FS_IOC_DONATE_RANGE: >>> + return f2fs_ioc_donate_range(filp, arg); >>> case FITRIM: >>> return f2fs_ioc_fitrim(filp, arg); >>> case FS_IOC_SET_ENCRYPTION_POLICY: >>> @@ -5273,6 +5320,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) >>> case F2FS_IOC_RELEASE_VOLATILE_WRITE: >>> case F2FS_IOC_ABORT_ATOMIC_WRITE: >>> case F2FS_IOC_SHUTDOWN: >>> + case F2FS_IOC_DONATE_RANGE: >>> case FITRIM: >>> case FS_IOC_SET_ENCRYPTION_POLICY: >>> case FS_IOC_GET_ENCRYPTION_PWSALT: >>> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c >>> index 7de33da8b3ea..e38dc5fe2f2e 100644 >>> --- a/fs/f2fs/inode.c >>> +++ b/fs/f2fs/inode.c >>> @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) >>> return 0; >>> } >>> +static void f2fs_remove_donate_inode(struct inode *inode) >>> +{ >>> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); >>> + >>> + if (list_empty(&F2FS_I(inode)->gdonate_list)) >> >> It will be more safe to access gdonate_list w/ inode_lock[DONATE_INODE]? > > It's unnecessary as this is called from evict_inode. I just concerned about the case fi->gdonate_list's prev and next pointer can be updated in race condition due to insertion or deletion of its adjacent entry. No risk now as I checked. :) Thanks, > >> >> Thanks, >> >>> + return; >>> + >>> + spin_lock(&sbi->inode_lock[DONATE_INODE]); >>> + list_del_init(&F2FS_I(inode)->gdonate_list); >>> + stat_dec_dirty_inode(sbi, DONATE_INODE); >>> + spin_unlock(&sbi->inode_lock[DONATE_INODE]); >>> +} >>> + >>> /* >>> * Called at the last iput() if i_nlink is zero >>> */ >>> @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) >>> f2fs_bug_on(sbi, get_dirty_pages(inode)); >>> f2fs_remove_dirty_inode(inode); >>> + f2fs_remove_donate_inode(inode); >>> if (!IS_DEVICE_ALIASING(inode)) >>> f2fs_destroy_extent_tree(inode); >>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c >>> index fc7d463dee15..ef639a6d82e5 100644 >>> --- a/fs/f2fs/super.c >>> +++ b/fs/f2fs/super.c >>> @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) >>> spin_lock_init(&fi->i_size_lock); >>> INIT_LIST_HEAD(&fi->dirty_list); >>> INIT_LIST_HEAD(&fi->gdirty_list); >>> + INIT_LIST_HEAD(&fi->gdonate_list); >>> init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); >>> init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); >>> init_f2fs_rwsem(&fi->i_xattr_sem); >>> diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h >>> index f7aaf8d23e20..cd38a7c166e6 100644 >>> --- a/include/uapi/linux/f2fs.h >>> +++ b/include/uapi/linux/f2fs.h >>> @@ -44,6 +44,8 @@ >>> #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) >>> #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ >>> + struct f2fs_donate_range) >>> /* >>> * should be same as XFS_IOC_GOINGDOWN. >>> @@ -97,4 +99,9 @@ struct f2fs_comp_option { >>> __u8 log_cluster_size; >>> }; >>> +struct f2fs_donate_range { >>> + __u64 start; >>> + __u64 len; >>> +}; >>> + >>> #endif /* _UAPI_LINUX_F2FS_H */ ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 1/2 v2] f2fs: register inodes which is able to donate pages 2025-01-13 18:39 ` Jaegeuk Kim @ 2025-01-14 17:20 ` Jaegeuk Kim -1 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-01-14 17:20 UTC (permalink / raw) To: linux-kernel, linux-f2fs-devel This patch introduces an inode list to keep the page cache ranges that users can donate pages together. #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ struct f2fs_donate_range) struct f2fs_donate_range { __u64 start; __u64 len; }; e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> --- Change log from v1: - change %u print format - check range boundary fs/f2fs/debug.c | 3 +++ fs/f2fs/f2fs.h | 9 ++++++- fs/f2fs/file.c | 52 +++++++++++++++++++++++++++++++++++++++ fs/f2fs/inode.c | 14 +++++++++++ fs/f2fs/super.c | 1 + include/uapi/linux/f2fs.h | 7 ++++++ 6 files changed, 85 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 468828288a4a..f7aea4dc9565 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; si->nquota_files = sbi->nquota_files; si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; si->aw_cnt = atomic_read(&sbi->atomic_files); @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) si->compr_inode, si->compr_blocks); seq_printf(s, " - Swapfile Inode: %u\n", si->swapfile_inode); + seq_printf(s, " - Donate Inode: %u\n", + si->ndonate_files); seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", si->orphans, si->append, si->update); seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4bfe162eefd3..7ce3e3eab17a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -850,6 +850,11 @@ struct f2fs_inode_info { #endif struct list_head dirty_list; /* dirty list for dirs and files */ struct list_head gdirty_list; /* linked in global dirty list */ + + /* linked in global inode list for cache donation */ + struct list_head gdonate_list; + loff_t donate_start, donate_end; /* inclusive */ + struct task_struct *atomic_write_task; /* store atomic write task */ struct extent_tree *extent_tree[NR_EXTENT_CACHES]; /* cached extent_tree entry */ @@ -1274,6 +1279,7 @@ enum inode_type { DIR_INODE, /* for dirty dir inode */ FILE_INODE, /* for dirty regular/symlink inode */ DIRTY_META, /* for all dirtied inode metadata */ + DONATE_INODE, /* for all inode to donate pages */ NR_INODE_TYPE, }; @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { unsigned long long allocated_data_blocks; int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; int ndirty_data, ndirty_qdata; - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; + unsigned int ndirty_dirs, ndirty_files, ndirty_all; + unsigned int nquota_files, ndonate_files; int nats, dirty_nats, sits, dirty_sits; int free_nids, avail_nids, alloc_nids; int total_count, utilization; diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 9980d17ef9f5..eb44999bb079 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2493,6 +2493,55 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) return ret; } +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct mnt_idmap *idmap = file_mnt_idmap(filp); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_donate_range range; + int ret; + + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, + sizeof(range))) + return -EFAULT; + + if (!inode_owner_or_capable(idmap, inode)) + return -EACCES; + + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + + if (unlikely((range.start + range.len) >> PAGE_SHIFT > + max_file_blocks(inode))) + return -EINVAL; + + ret = mnt_want_write_file(filp); + if (ret) + return ret; + + inode_lock(inode); + + if (f2fs_is_atomic_file(inode)) + goto out; + + spin_lock(&sbi->inode_lock[DONATE_INODE]); + if (list_empty(&F2FS_I(inode)->gdonate_list)) { + list_add_tail(&F2FS_I(inode)->gdonate_list, + &sbi->inode_list[DONATE_INODE]); + stat_inc_dirty_inode(sbi, DONATE_INODE); + } else { + list_move_tail(&F2FS_I(inode)->gdonate_list, + &sbi->inode_list[DONATE_INODE]); + } + F2FS_I(inode)->donate_start = range.start; + F2FS_I(inode)->donate_end = range.start + range.len - 1; + spin_unlock(&sbi->inode_lock[DONATE_INODE]); +out: + inode_unlock(inode); + mnt_drop_write_file(filp); + return ret; +} + static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -4522,6 +4571,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EOPNOTSUPP; case F2FS_IOC_SHUTDOWN: return f2fs_ioc_shutdown(filp, arg); + case F2FS_IOC_DONATE_RANGE: + return f2fs_ioc_donate_range(filp, arg); case FITRIM: return f2fs_ioc_fitrim(filp, arg); case FS_IOC_SET_ENCRYPTION_POLICY: @@ -5273,6 +5324,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_RELEASE_VOLATILE_WRITE: case F2FS_IOC_ABORT_ATOMIC_WRITE: case F2FS_IOC_SHUTDOWN: + case F2FS_IOC_DONATE_RANGE: case FITRIM: case FS_IOC_SET_ENCRYPTION_POLICY: case FS_IOC_GET_ENCRYPTION_PWSALT: diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 7de33da8b3ea..e38dc5fe2f2e 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) return 0; } +static void f2fs_remove_donate_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + if (list_empty(&F2FS_I(inode)->gdonate_list)) + return; + + spin_lock(&sbi->inode_lock[DONATE_INODE]); + list_del_init(&F2FS_I(inode)->gdonate_list); + stat_dec_dirty_inode(sbi, DONATE_INODE); + spin_unlock(&sbi->inode_lock[DONATE_INODE]); +} + /* * Called at the last iput() if i_nlink is zero */ @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) f2fs_bug_on(sbi, get_dirty_pages(inode)); f2fs_remove_dirty_inode(inode); + f2fs_remove_donate_inode(inode); if (!IS_DEVICE_ALIASING(inode)) f2fs_destroy_extent_tree(inode); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index fc7d463dee15..ef639a6d82e5 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) spin_lock_init(&fi->i_size_lock); INIT_LIST_HEAD(&fi->dirty_list); INIT_LIST_HEAD(&fi->gdirty_list); + INIT_LIST_HEAD(&fi->gdonate_list); init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); init_f2fs_rwsem(&fi->i_xattr_sem); diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h index f7aaf8d23e20..cd38a7c166e6 100644 --- a/include/uapi/linux/f2fs.h +++ b/include/uapi/linux/f2fs.h @@ -44,6 +44,8 @@ #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ + struct f2fs_donate_range) /* * should be same as XFS_IOC_GOINGDOWN. @@ -97,4 +99,9 @@ struct f2fs_comp_option { __u8 log_cluster_size; }; +struct f2fs_donate_range { + __u64 start; + __u64 len; +}; + #endif /* _UAPI_LINUX_F2FS_H */ -- 2.47.1.688.g23fc6f90ad-goog _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 1/2 v2] f2fs: register inodes which is able to donate pages @ 2025-01-14 17:20 ` Jaegeuk Kim 0 siblings, 0 replies; 24+ messages in thread From: Jaegeuk Kim @ 2025-01-14 17:20 UTC (permalink / raw) To: linux-kernel, linux-f2fs-devel This patch introduces an inode list to keep the page cache ranges that users can donate pages together. #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ struct f2fs_donate_range) struct f2fs_donate_range { __u64 start; __u64 len; }; e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> --- Change log from v1: - change %u print format - check range boundary fs/f2fs/debug.c | 3 +++ fs/f2fs/f2fs.h | 9 ++++++- fs/f2fs/file.c | 52 +++++++++++++++++++++++++++++++++++++++ fs/f2fs/inode.c | 14 +++++++++++ fs/f2fs/super.c | 1 + include/uapi/linux/f2fs.h | 7 ++++++ 6 files changed, 85 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 468828288a4a..f7aea4dc9565 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -164,6 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; + si->ndonate_files = sbi->ndirty_inode[DONATE_INODE]; si->nquota_files = sbi->nquota_files; si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; si->aw_cnt = atomic_read(&sbi->atomic_files); @@ -501,6 +502,8 @@ static int stat_show(struct seq_file *s, void *v) si->compr_inode, si->compr_blocks); seq_printf(s, " - Swapfile Inode: %u\n", si->swapfile_inode); + seq_printf(s, " - Donate Inode: %u\n", + si->ndonate_files); seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n", si->orphans, si->append, si->update); seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4bfe162eefd3..7ce3e3eab17a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -850,6 +850,11 @@ struct f2fs_inode_info { #endif struct list_head dirty_list; /* dirty list for dirs and files */ struct list_head gdirty_list; /* linked in global dirty list */ + + /* linked in global inode list for cache donation */ + struct list_head gdonate_list; + loff_t donate_start, donate_end; /* inclusive */ + struct task_struct *atomic_write_task; /* store atomic write task */ struct extent_tree *extent_tree[NR_EXTENT_CACHES]; /* cached extent_tree entry */ @@ -1274,6 +1279,7 @@ enum inode_type { DIR_INODE, /* for dirty dir inode */ FILE_INODE, /* for dirty regular/symlink inode */ DIRTY_META, /* for all dirtied inode metadata */ + DONATE_INODE, /* for all inode to donate pages */ NR_INODE_TYPE, }; @@ -3984,7 +3990,8 @@ struct f2fs_stat_info { unsigned long long allocated_data_blocks; int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; int ndirty_data, ndirty_qdata; - unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; + unsigned int ndirty_dirs, ndirty_files, ndirty_all; + unsigned int nquota_files, ndonate_files; int nats, dirty_nats, sits, dirty_sits; int free_nids, avail_nids, alloc_nids; int total_count, utilization; diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 9980d17ef9f5..eb44999bb079 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2493,6 +2493,55 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) return ret; } +static int f2fs_ioc_donate_range(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct mnt_idmap *idmap = file_mnt_idmap(filp); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_donate_range range; + int ret; + + if (copy_from_user(&range, (struct f2fs_donate_range __user *)arg, + sizeof(range))) + return -EFAULT; + + if (!inode_owner_or_capable(idmap, inode)) + return -EACCES; + + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + + if (unlikely((range.start + range.len) >> PAGE_SHIFT > + max_file_blocks(inode))) + return -EINVAL; + + ret = mnt_want_write_file(filp); + if (ret) + return ret; + + inode_lock(inode); + + if (f2fs_is_atomic_file(inode)) + goto out; + + spin_lock(&sbi->inode_lock[DONATE_INODE]); + if (list_empty(&F2FS_I(inode)->gdonate_list)) { + list_add_tail(&F2FS_I(inode)->gdonate_list, + &sbi->inode_list[DONATE_INODE]); + stat_inc_dirty_inode(sbi, DONATE_INODE); + } else { + list_move_tail(&F2FS_I(inode)->gdonate_list, + &sbi->inode_list[DONATE_INODE]); + } + F2FS_I(inode)->donate_start = range.start; + F2FS_I(inode)->donate_end = range.start + range.len - 1; + spin_unlock(&sbi->inode_lock[DONATE_INODE]); +out: + inode_unlock(inode); + mnt_drop_write_file(filp); + return ret; +} + static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -4522,6 +4571,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EOPNOTSUPP; case F2FS_IOC_SHUTDOWN: return f2fs_ioc_shutdown(filp, arg); + case F2FS_IOC_DONATE_RANGE: + return f2fs_ioc_donate_range(filp, arg); case FITRIM: return f2fs_ioc_fitrim(filp, arg); case FS_IOC_SET_ENCRYPTION_POLICY: @@ -5273,6 +5324,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_RELEASE_VOLATILE_WRITE: case F2FS_IOC_ABORT_ATOMIC_WRITE: case F2FS_IOC_SHUTDOWN: + case F2FS_IOC_DONATE_RANGE: case FITRIM: case FS_IOC_SET_ENCRYPTION_POLICY: case FS_IOC_GET_ENCRYPTION_PWSALT: diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 7de33da8b3ea..e38dc5fe2f2e 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -804,6 +804,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) return 0; } +static void f2fs_remove_donate_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + if (list_empty(&F2FS_I(inode)->gdonate_list)) + return; + + spin_lock(&sbi->inode_lock[DONATE_INODE]); + list_del_init(&F2FS_I(inode)->gdonate_list); + stat_dec_dirty_inode(sbi, DONATE_INODE); + spin_unlock(&sbi->inode_lock[DONATE_INODE]); +} + /* * Called at the last iput() if i_nlink is zero */ @@ -838,6 +851,7 @@ void f2fs_evict_inode(struct inode *inode) f2fs_bug_on(sbi, get_dirty_pages(inode)); f2fs_remove_dirty_inode(inode); + f2fs_remove_donate_inode(inode); if (!IS_DEVICE_ALIASING(inode)) f2fs_destroy_extent_tree(inode); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index fc7d463dee15..ef639a6d82e5 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1441,6 +1441,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) spin_lock_init(&fi->i_size_lock); INIT_LIST_HEAD(&fi->dirty_list); INIT_LIST_HEAD(&fi->gdirty_list); + INIT_LIST_HEAD(&fi->gdonate_list); init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); init_f2fs_rwsem(&fi->i_xattr_sem); diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h index f7aaf8d23e20..cd38a7c166e6 100644 --- a/include/uapi/linux/f2fs.h +++ b/include/uapi/linux/f2fs.h @@ -44,6 +44,8 @@ #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) #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_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ + struct f2fs_donate_range) /* * should be same as XFS_IOC_GOINGDOWN. @@ -97,4 +99,9 @@ struct f2fs_comp_option { __u8 log_cluster_size; }; +struct f2fs_donate_range { + __u64 start; + __u64 len; +}; + #endif /* _UAPI_LINUX_F2FS_H */ -- 2.47.1.688.g23fc6f90ad-goog ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages 2025-01-13 18:39 ` Jaegeuk Kim @ 2025-01-14 21:16 ` Eric Biggers -1 siblings, 0 replies; 24+ messages in thread From: Eric Biggers via Linux-f2fs-devel @ 2025-01-14 21:16 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel On Mon, Jan 13, 2025 at 06:39:32PM +0000, Jaegeuk Kim via Linux-f2fs-devel wrote: > This patch introduces an inode list to keep the page cache ranges that users > can donate pages together. > > #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > struct f2fs_donate_range) > struct f2fs_donate_range { > __u64 start; > __u64 len; > }; > > e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > --- > fs/f2fs/debug.c | 3 +++ > fs/f2fs/f2fs.h | 9 +++++++- > fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ > fs/f2fs/inode.c | 14 ++++++++++++ > fs/f2fs/super.c | 1 + > include/uapi/linux/f2fs.h | 7 ++++++ > 6 files changed, 81 insertions(+), 1 deletion(-) Missing a rationale, documentation, tests, and fuzzing. - Eric _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 1/2] f2fs: register inodes which is able to donate pages @ 2025-01-14 21:16 ` Eric Biggers 0 siblings, 0 replies; 24+ messages in thread From: Eric Biggers @ 2025-01-14 21:16 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel On Mon, Jan 13, 2025 at 06:39:32PM +0000, Jaegeuk Kim via Linux-f2fs-devel wrote: > This patch introduces an inode list to keep the page cache ranges that users > can donate pages together. > > #define F2FS_IOC_DONATE_RANGE _IOW(F2FS_IOCTL_MAGIC, 27, \ > struct f2fs_donate_range) > struct f2fs_donate_range { > __u64 start; > __u64 len; > }; > > e.g., ioctl(F2FS_IOC_DONATE_RANGE, &range); > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> > --- > fs/f2fs/debug.c | 3 +++ > fs/f2fs/f2fs.h | 9 +++++++- > fs/f2fs/file.c | 48 +++++++++++++++++++++++++++++++++++++++ > fs/f2fs/inode.c | 14 ++++++++++++ > fs/f2fs/super.c | 1 + > include/uapi/linux/f2fs.h | 7 ++++++ > 6 files changed, 81 insertions(+), 1 deletion(-) Missing a rationale, documentation, tests, and fuzzing. - Eric ^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2025-01-15 2:17 UTC | newest] Thread overview: 24+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-01-13 18:39 [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages Jaegeuk Kim via Linux-f2fs-devel 2025-01-13 18:39 ` Jaegeuk Kim 2025-01-13 18:39 ` [f2fs-dev] [PATCH 2/2] f2fs: add a sysfs entry to request donate file-backed pages Jaegeuk Kim via Linux-f2fs-devel 2025-01-13 18:39 ` Jaegeuk Kim 2025-01-14 7:34 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel 2025-01-14 7:34 ` Chao Yu 2025-01-14 17:18 ` Jaegeuk Kim via Linux-f2fs-devel 2025-01-14 17:18 ` Jaegeuk Kim 2025-01-15 2:17 ` Chao Yu via Linux-f2fs-devel 2025-01-15 2:17 ` Chao Yu 2025-01-14 19:11 ` kernel test robot 2025-01-14 19:43 ` kernel test robot 2025-01-14 20:50 ` [f2fs-dev] [PATCH 2/2 v2] " Jaegeuk Kim via Linux-f2fs-devel 2025-01-14 20:50 ` Jaegeuk Kim 2025-01-14 6:34 ` [f2fs-dev] [PATCH 1/2] f2fs: register inodes which is able to donate pages Chao Yu via Linux-f2fs-devel 2025-01-14 6:34 ` Chao Yu 2025-01-14 17:15 ` Jaegeuk Kim via Linux-f2fs-devel 2025-01-14 17:15 ` Jaegeuk Kim 2025-01-15 2:12 ` Chao Yu via Linux-f2fs-devel 2025-01-15 2:12 ` Chao Yu 2025-01-14 17:20 ` [f2fs-dev] [PATCH 1/2 v2] " Jaegeuk Kim via Linux-f2fs-devel 2025-01-14 17:20 ` Jaegeuk Kim 2025-01-14 21:16 ` [f2fs-dev] [PATCH 1/2] " Eric Biggers via Linux-f2fs-devel 2025-01-14 21:16 ` Eric Biggers
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.