@@ -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 / \
@@ -804,6 +809,7 @@ enum {
FI_COW_FILE, /* indicate COW file */
FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */
FI_ATOMIC_REPLACE, /* indicate atomic replace */
+ FI_INLINE_TAIL, /* used for inline tail */
FI_MAX, /* max flag, never be used */
};
@@ -2997,6 +3003,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)
@@ -3264,6 +3271,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);
@@ -3300,6 +3312,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);
}
@@ -3429,6 +3444,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;
@@ -426,6 +426,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;
@@ -674,6 +676,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));
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.wu@vivo.com> --- fs/f2fs/f2fs.h | 27 ++++++++++++++++++++++++++- fs/f2fs/inode.c | 6 ++++++ 2 files changed, 32 insertions(+), 1 deletion(-)