From: Yongpeng Yang <[email protected]> Allow userspace to enable or disable inline extent format on a per-file basis through the FS_IOC_SETFLAGS/FS_IOC_GETFLAGS ioctl interface using the F2FS_EXTENT_FL flag.
When setting the flag, the file's direct block addresses are converted to inline extent format. Compressed files are excluded from this conversion as the two features are mutually exclusive. Clearing the flag converts back to direct block format without restrictions. Signed-off-by: Yongpeng Yang <[email protected]> --- fs/f2fs/file.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 2ca09ac1f3d4..a499dbcf53dd 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -33,6 +33,7 @@ #include "acl.h" #include "gc.h" #include "iostat.h" +#include "iextent.h" #include <trace/events/f2fs.h> #include <uapi/linux/f2fs.h> @@ -2117,6 +2118,58 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id) return 0; } +#ifdef CONFIG_F2FS_INLINE_EXTENT +static int f2fs_iext_enable_inline_extent(struct inode *inode) +{ + int ret = 0; + struct folio *ifolio = NULL; + + if (f2fs_has_inline_data(inode)) + goto out; + + ret = filemap_write_and_wait(inode->i_mapping); + if (ret) + goto out; + + ifolio = f2fs_get_inode_folio(F2FS_I_SB(inode), inode->i_ino); + if (IS_ERR(ifolio)) + return -ENOMEM; + + if (!f2fs_iext_convert_to_inline_extent(inode, ifolio)) { + f2fs_folio_put(ifolio, true); + f2fs_err(F2FS_I_SB(inode), "convert to inline extent failed!"); + ret = -EINVAL; + goto out; + } + folio_mark_dirty(ifolio); + f2fs_folio_put(ifolio, true); + +out: + return ret; +} + +static int f2fs_iext_disable_inline_extent(struct inode *inode) +{ + struct folio *ifolio; + int ret; + + ret = filemap_write_and_wait(inode->i_mapping); + if (ret) + return ret; + + ifolio = f2fs_get_inode_folio(F2FS_I_SB(inode), inode->i_ino); + if (IS_ERR(ifolio)) + return PTR_ERR(ifolio); + if (!f2fs_iext_support_inline_extent(inode, ifolio)) + goto out; + f2fs_iext_convert_to_direct_blocks(inode, ifolio); + folio_mark_dirty(ifolio); +out: + f2fs_folio_put(ifolio, true); + return 0; +} +#endif + static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) { struct f2fs_inode_info *fi = F2FS_I(inode); @@ -2129,6 +2182,30 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) if (IS_NOQUOTA(inode)) return -EPERM; +#ifdef CONFIG_F2FS_INLINE_EXTENT + if (iflags & F2FS_EXTENT_FL) { + int ret; + + if (!S_ISREG(inode->i_mode)) + return -EOPNOTSUPP; + if (iflags & F2FS_COMPR_FL) + return -EOPNOTSUPP; + if (f2fs_compressed_file(inode)) + return -EOPNOTSUPP; + ret = f2fs_iext_enable_inline_extent(inode); + if (ret) + return ret; + } + if ((iflags ^ masked_flags) & F2FS_EXTENT_FL) { + if (masked_flags & F2FS_EXTENT_FL) { + int ret = f2fs_iext_disable_inline_extent(inode); + + if (ret) + return ret; + } + } +#endif + if ((iflags ^ masked_flags) & F2FS_CASEFOLD_FL) { if (!f2fs_sb_has_casefold(F2FS_I_SB(inode))) return -EOPNOTSUPP; @@ -2224,6 +2301,7 @@ static const struct { FS_NOCOMP_FL | \ FS_INDEX_FL | \ FS_DIRSYNC_FL | \ + FS_EXTENT_FL | \ FS_PROJINHERIT_FL | \ FS_ENCRYPT_FL | \ FS_INLINE_DATA_FL | \ @@ -2240,6 +2318,7 @@ static const struct { FS_NOATIME_FL | \ FS_NOCOMP_FL | \ FS_DIRSYNC_FL | \ + FS_EXTENT_FL | \ FS_PROJINHERIT_FL | \ FS_CASEFOLD_FL) -- 2.43.0 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
