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]>
---
v2:
- Fix f2fs_iext_enable_inline_extent to use PTR_ERR(ifolio) instead of
  hardcoded -ENOMEM.
---
 fs/f2fs/file.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 7db9cef5bc65..a20f332a2354 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 PTR_ERR(ifolio);
+
+       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

Reply via email to