When inline tail is enabled, use a compact block address array. And the
rest space is used to save file tail data. The layout of an inode block
as following:

| inode block     | 4096 |     inline tail enable    |
| --------------- | ---- | --------------------------|
| inode info      | 360  |                           |
| --------------- | ---- | --------------------------|
|                 |      | extra info         | 0~36 |
|                 |      | **compact_addr[16] | 64   |
| addr table[923] | 3692 | reserved           | 4    |
|                 |      | **tail data        |      |
|                 |      | inline_xattr       | 200  |
| --------------- | ---- | --------------------------|
| nid table[5]    | 20   |
| node footer     | 24   |

So if we define compact address array size is 16, then we can have
3392~3428 bytes to store tail data.

Signed-off-by: Wu Bo <bo...@vivo.com>
---
 fs/f2fs/f2fs.h  | 27 ++++++++++++++++++++++++++-
 fs/f2fs/inode.c |  6 ++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 3956740ca7e2..e02a6619b90a 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -476,12 +476,17 @@ static inline bool __has_cursum_space(struct f2fs_journal 
*journal,
 
 /* for inline stuff */
 #define DEF_INLINE_RESERVED_SIZE       1
+#define COMPACT_ADDRS_PER_INODE                16
 static inline int get_extra_isize(struct inode *inode);
 static inline int get_inline_xattr_addrs(struct inode *inode);
+static inline int get_reserved_addrs(struct inode *inode);
 #define MAX_INLINE_DATA(inode) (sizeof(__le32) *                       \
                                (CUR_ADDRS_PER_INODE(inode) -           \
                                get_inline_xattr_addrs(inode) - \
-                               DEF_INLINE_RESERVED_SIZE))
+                               get_reserved_addrs(inode)))
+
+#define MAX_INLINE_TAIL(inode) (MAX_INLINE_DATA(inode) + \
+               (PAGE_SIZE * COMPACT_ADDRS_PER_INODE))
 
 /* for inline dir */
 #define NR_INLINE_DENTRY(inode)        (MAX_INLINE_DATA(inode) * BITS_PER_BYTE 
/ \
@@ -805,6 +810,7 @@ enum {
        FI_ATOMIC_COMMITTED,    /* indicate atomic commit completed except disk 
sync */
        FI_ATOMIC_REPLACE,      /* indicate atomic replace */
        FI_OPENED_FILE,         /* indicate file has been opened */
+       FI_INLINE_TAIL,         /* used for inline tail */
        FI_MAX,                 /* max flag, never be used */
 };
 
@@ -3002,6 +3008,7 @@ static inline void f2fs_change_bit(unsigned int nr, char 
*addr)
 #define F2FS_DIRSYNC_FL                        0x00010000 /* dirsync behaviour 
(directories only) */
 #define F2FS_PROJINHERIT_FL            0x20000000 /* Create with parents 
projid */
 #define F2FS_CASEFOLD_FL               0x40000000 /* Casefolded file */
+#define F2FS_INLINE_TAIL               0x80000000 /* Has inline tail */
 
 #define F2FS_QUOTA_DEFAULT_FL          (F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL)
 
@@ -3263,6 +3270,11 @@ static inline int f2fs_has_inline_data(struct inode 
*inode)
        return is_inode_flag_set(inode, FI_INLINE_DATA);
 }
 
+static inline int f2fs_has_inline_tail(struct inode *inode)
+{
+       return is_inode_flag_set(inode, FI_INLINE_TAIL);
+}
+
 static inline int f2fs_exist_data(struct inode *inode)
 {
        return is_inode_flag_set(inode, FI_DATA_EXIST);
@@ -3299,6 +3311,9 @@ static inline void *inline_data_addr(struct inode *inode, 
struct page *page)
 {
        __le32 *addr = get_dnode_addr(inode, page);
 
+       if (f2fs_has_inline_tail(inode))
+               addr += COMPACT_ADDRS_PER_INODE;
+
        return (void *)(addr + DEF_INLINE_RESERVED_SIZE);
 }
 
@@ -3428,6 +3443,16 @@ static inline int get_extra_isize(struct inode *inode)
        return F2FS_I(inode)->i_extra_isize / sizeof(__le32);
 }
 
+static inline int get_reserved_addrs(struct inode *inode)
+{
+       int size = DEF_INLINE_RESERVED_SIZE;
+
+       if (f2fs_has_inline_tail(inode))
+               size += COMPACT_ADDRS_PER_INODE;
+
+       return size;
+}
+
 static inline int get_inline_xattr_addrs(struct inode *inode)
 {
        return F2FS_I(inode)->i_inline_xattr_size;
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index aef57172014f..88dfcf16da0e 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -425,6 +425,8 @@ static int do_read_inode(struct inode *inode)
        fi->i_dir_level = ri->i_dir_level;
 
        get_inline_info(inode, ri);
+       if (fi->i_flags & F2FS_INLINE_TAIL)
+               set_bit(FI_INLINE_TAIL, fi->flags);
 
        fi->i_extra_isize = f2fs_has_extra_attr(inode) ?
                                        le16_to_cpu(ri->i_extra_isize) : 0;
@@ -666,6 +668,10 @@ void f2fs_update_inode(struct inode *inode, struct page 
*node_page)
                memset(&ri->i_ext, 0, sizeof(ri->i_ext));
        }
        set_raw_inline(inode, ri);
+       if (is_inode_flag_set(inode, FI_INLINE_TAIL))
+               F2FS_I(inode)->i_flags |= F2FS_INLINE_TAIL;
+       else
+               F2FS_I(inode)->i_flags &= ~F2FS_INLINE_TAIL;
 
        ri->i_atime = cpu_to_le64(inode_get_atime_sec(inode));
        ri->i_ctime = cpu_to_le64(inode_get_ctime_sec(inode));
-- 
2.35.3



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

Reply via email to