Commit f2470371 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim

f2fs: make max inline size changeable

This patch tries to make below macros calculating max inline size,
inline dentry field size considerring reserving size-changeable
space:
- MAX_INLINE_DATA
- NR_INLINE_DENTRY
- INLINE_DENTRY_BITMAP_SIZE
- INLINE_RESERVED_SIZE

Then, when inline_{data,dentry} options is enabled, it allows us to
reserve inline space with different size flexibly for adding newly
introduced inode attribute.
Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent e65ef207
...@@ -813,7 +813,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from) ...@@ -813,7 +813,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
F2FS_GET_BLOCK_PRE_AIO : F2FS_GET_BLOCK_PRE_AIO :
F2FS_GET_BLOCK_PRE_DIO); F2FS_GET_BLOCK_PRE_DIO);
} }
if (iocb->ki_pos + iov_iter_count(from) > MAX_INLINE_DATA) { if (iocb->ki_pos + iov_iter_count(from) > MAX_INLINE_DATA(inode)) {
err = f2fs_convert_inline_inode(inode); err = f2fs_convert_inline_inode(inode);
if (err) if (err)
return err; return err;
...@@ -1857,7 +1857,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, ...@@ -1857,7 +1857,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
set_new_dnode(&dn, inode, ipage, ipage, 0); set_new_dnode(&dn, inode, ipage, ipage, 0);
if (f2fs_has_inline_data(inode)) { if (f2fs_has_inline_data(inode)) {
if (pos + len <= MAX_INLINE_DATA) { if (pos + len <= MAX_INLINE_DATA(inode)) {
read_inline_data(page, ipage); read_inline_data(page, ipage);
set_inode_flag(inode, FI_DATA_EXIST); set_inode_flag(inode, FI_DATA_EXIST);
if (inode->i_nlink) if (inode->i_nlink)
......
...@@ -357,6 +357,25 @@ struct f2fs_flush_device { ...@@ -357,6 +357,25 @@ struct f2fs_flush_device {
u32 segments; /* # of segments to flush */ u32 segments; /* # of segments to flush */
}; };
/* for inline stuff */
#define DEF_INLINE_RESERVED_SIZE 1
static inline int get_inline_reserved_size(struct inode *inode);
#define MAX_INLINE_DATA(inode) (sizeof(__le32) * (DEF_ADDRS_PER_INODE -\
get_inline_reserved_size(inode) -\
F2FS_INLINE_XATTR_ADDRS))
/* for inline dir */
#define NR_INLINE_DENTRY(inode) (MAX_INLINE_DATA(inode) * BITS_PER_BYTE / \
((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
BITS_PER_BYTE + 1))
#define INLINE_DENTRY_BITMAP_SIZE(inode) ((NR_INLINE_DENTRY(inode) + \
BITS_PER_BYTE - 1) / BITS_PER_BYTE)
#define INLINE_RESERVED_SIZE(inode) (MAX_INLINE_DATA(inode) - \
((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
NR_INLINE_DENTRY(inode) + \
INLINE_DENTRY_BITMAP_SIZE(inode)))
/* /*
* For INODE and NODE manager * For INODE and NODE manager
*/ */
...@@ -382,14 +401,19 @@ static inline void make_dentry_ptr_block(struct inode *inode, ...@@ -382,14 +401,19 @@ static inline void make_dentry_ptr_block(struct inode *inode,
} }
static inline void make_dentry_ptr_inline(struct inode *inode, static inline void make_dentry_ptr_inline(struct inode *inode,
struct f2fs_dentry_ptr *d, struct f2fs_inline_dentry *t) struct f2fs_dentry_ptr *d, void *t)
{ {
int entry_cnt = NR_INLINE_DENTRY(inode);
int bitmap_size = INLINE_DENTRY_BITMAP_SIZE(inode);
int reserved_size = INLINE_RESERVED_SIZE(inode);
d->inode = inode; d->inode = inode;
d->max = NR_INLINE_DENTRY; d->max = entry_cnt;
d->nr_bitmap = INLINE_DENTRY_BITMAP_SIZE; d->nr_bitmap = bitmap_size;
d->bitmap = &t->dentry_bitmap; d->bitmap = t;
d->dentry = t->dentry; d->dentry = t + bitmap_size + reserved_size;
d->filename = t->filename; d->filename = t + bitmap_size + reserved_size +
SIZE_OF_DIR_ENTRY * entry_cnt;
} }
/* /*
...@@ -543,6 +567,8 @@ struct f2fs_inode_info { ...@@ -543,6 +567,8 @@ struct f2fs_inode_info {
struct extent_tree *extent_tree; /* cached extent_tree entry */ struct extent_tree *extent_tree; /* cached extent_tree entry */
struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */ struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
struct rw_semaphore i_mmap_sem; struct rw_semaphore i_mmap_sem;
int i_inline_reserved; /* reserved size in inline data */
}; };
static inline void get_extent_info(struct extent_info *ext, static inline void get_extent_info(struct extent_info *ext,
...@@ -2075,11 +2101,12 @@ static inline bool f2fs_is_drop_cache(struct inode *inode) ...@@ -2075,11 +2101,12 @@ static inline bool f2fs_is_drop_cache(struct inode *inode)
return is_inode_flag_set(inode, FI_DROP_CACHE); return is_inode_flag_set(inode, FI_DROP_CACHE);
} }
static inline void *inline_data_addr(struct page *page) static inline void *inline_data_addr(struct inode *inode, struct page *page)
{ {
struct f2fs_inode *ri = F2FS_INODE(page); struct f2fs_inode *ri = F2FS_INODE(page);
int reserved_size = get_inline_reserved_size(inode);
return (void *)&(ri->i_addr[1]); return (void *)&(ri->i_addr[reserved_size]);
} }
static inline int f2fs_has_inline_dentry(struct inode *inode) static inline int f2fs_has_inline_dentry(struct inode *inode)
...@@ -2170,6 +2197,11 @@ static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi, ...@@ -2170,6 +2197,11 @@ static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi,
return kmalloc(size, flags); return kmalloc(size, flags);
} }
static inline int get_inline_reserved_size(struct inode *inode)
{
return F2FS_I(inode)->i_inline_reserved;
}
#define get_inode_mode(i) \ #define get_inode_mode(i) \
((is_inode_flag_set(i, FI_ACL_MODE)) ? \ ((is_inode_flag_set(i, FI_ACL_MODE)) ? \
(F2FS_I(i)->i_acl_mode) : ((i)->i_mode)) (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
......
This diff is collapsed.
...@@ -87,9 +87,9 @@ static void __set_inode_rdev(struct inode *inode, struct f2fs_inode *ri) ...@@ -87,9 +87,9 @@ static void __set_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
static void __recover_inline_status(struct inode *inode, struct page *ipage) static void __recover_inline_status(struct inode *inode, struct page *ipage)
{ {
void *inline_data = inline_data_addr(ipage); void *inline_data = inline_data_addr(inode, ipage);
__le32 *start = inline_data; __le32 *start = inline_data;
__le32 *end = start + MAX_INLINE_DATA / sizeof(__le32); __le32 *end = start + MAX_INLINE_DATA(inode) / sizeof(__le32);
while (start < end) { while (start < end) {
if (*start++) { if (*start++) {
......
...@@ -446,6 +446,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) ...@@ -446,6 +446,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
#endif #endif
/* Will be used by directory only */ /* Will be used by directory only */
fi->i_dir_level = F2FS_SB(sb)->dir_level; fi->i_dir_level = F2FS_SB(sb)->dir_level;
fi->i_inline_reserved = DEF_INLINE_RESERVED_SIZE;
return &fi->vfs_inode; return &fi->vfs_inode;
} }
......
...@@ -206,9 +206,6 @@ struct f2fs_extent { ...@@ -206,9 +206,6 @@ struct f2fs_extent {
#define F2FS_DATA_EXIST 0x08 /* file inline data exist flag */ #define F2FS_DATA_EXIST 0x08 /* file inline data exist flag */
#define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries */ #define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries */
#define MAX_INLINE_DATA (sizeof(__le32) * (DEF_ADDRS_PER_INODE - \
F2FS_INLINE_XATTR_ADDRS - 1))
struct f2fs_inode { struct f2fs_inode {
__le16 i_mode; /* file mode */ __le16 i_mode; /* file mode */
__u8 i_advise; /* file hints */ __u8 i_advise; /* file hints */
...@@ -465,7 +462,7 @@ typedef __le32 f2fs_hash_t; ...@@ -465,7 +462,7 @@ typedef __le32 f2fs_hash_t;
#define MAX_DIR_BUCKETS (1 << ((MAX_DIR_HASH_DEPTH / 2) - 1)) #define MAX_DIR_BUCKETS (1 << ((MAX_DIR_HASH_DEPTH / 2) - 1))
/* /*
* space utilization of regular dentry and inline dentry * space utilization of regular dentry and inline dentry (w/o extra reservation)
* regular dentry inline dentry * regular dentry inline dentry
* bitmap 1 * 27 = 27 1 * 23 = 23 * bitmap 1 * 27 = 27 1 * 23 = 23
* reserved 1 * 3 = 3 1 * 7 = 7 * reserved 1 * 3 = 3 1 * 7 = 7
...@@ -501,24 +498,6 @@ struct f2fs_dentry_block { ...@@ -501,24 +498,6 @@ struct f2fs_dentry_block {
__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
} __packed; } __packed;
/* for inline dir */
#define NR_INLINE_DENTRY (MAX_INLINE_DATA * BITS_PER_BYTE / \
((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
BITS_PER_BYTE + 1))
#define INLINE_DENTRY_BITMAP_SIZE ((NR_INLINE_DENTRY + \
BITS_PER_BYTE - 1) / BITS_PER_BYTE)
#define INLINE_RESERVED_SIZE (MAX_INLINE_DATA - \
((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
NR_INLINE_DENTRY + INLINE_DENTRY_BITMAP_SIZE))
/* inline directory entry structure */
struct f2fs_inline_dentry {
__u8 dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE];
__u8 reserved[INLINE_RESERVED_SIZE];
struct f2fs_dir_entry dentry[NR_INLINE_DENTRY];
__u8 filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN];
} __packed;
/* file types used in inode_info->flags */ /* file types used in inode_info->flags */
enum { enum {
F2FS_FT_UNKNOWN, F2FS_FT_UNKNOWN,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment