f2fs: spread struct f2fs_dentry_ptr for inline path
Subsystems (2)
Chao Yu
maintainerPATCH 1/6 f2fs: spread struct f2fs_dentry_ptr for inline path
From: Chao Yu <[email protected]>
Use f2fs_dentry_ptr structure to indicate inline dentry structure as much as possible, so we can wrap inline dentry with size-fixed fields to the one with size-changeable fields. With this change, we can handle size-changeable inline dentry more easily.
--- fs/f2fs/f2fs.h | 5 ++++- fs/f2fs/inline.c | 47 ++++++++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 22 deletions(-)
fs/f2fs/f2fs.h +4 -1
@@ -361,10 +361,11 @@ struct f2fs_flush_device {/* for directory operations */ struct f2fs_dentry_ptr {struct inode *inode; -const void *bitmap; +void *bitmap;struct f2fs_dir_entry *dentry;__u8 (*filename)[F2FS_SLOT_LEN ];int max; +int nr_bitmap; }; static inline void make_dentry_ptr_block(struct inode *inode,
@@ -372,6 +373,7 @@ static inline void make_dentry_ptr_block(struct inode *inode, { d->inode = inode; d->max =NR_DENTRY_IN_BLOCK ; + d->nr_bitmap =SIZE_OF_DENTRY_BITMAP ; d->bitmap = &t->dentry_bitmap; d->dentry = t->dentry; d->filename = t->filename;
@@ -382,6 +384,7 @@ static inline void make_dentry_ptr_inline(struct inode *inode, { d->inode = inode; d->max =NR_INLINE_DENTRY ; + d->nr_bitmap =INLINE_DENTRY_BITMAP_SIZE ; d->bitmap = &t->dentry_bitmap; d->dentry = t->dentry; d->filename = t->filename;
fs/f2fs/inline.c +26 -21
118 lines not on this page · raw message
Signature · 1 line
2.13.0.90.g1eb437020
Chao Yu
maintainerPATCH 2/6 f2fs: make max inline size changeable
From: Chao Yu <[email protected]>
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.
--- fs/f2fs/data.c | 6 +-- fs/f2fs/f2fs.h | 51 +++++++++++++++++++----- fs/f2fs/inline.c | 101 ++++++++++++++++++++++++------------------------ fs/f2fs/inode.c | 4 +- fs/f2fs/super.c | 3 ++ include/linux/f2fs_fs.h | 23 +---------- 6 files changed, 102 insertions(+), 86 deletions(-)
fs/f2fs/data.c +3 -3
@@ -813,7 +813,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from) F2FS_GET_BLOCK_PRE_AIO : 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);if (err)return err;
@@ -1857,8 +1857,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,set_new_dnode (&dn, inode, ipage, ipage,0 );if (f2fs_has_inline_data (inode)) { -if (pos + len <=MAX_INLINE_DATA ) { -read_inline_data (page, ipage); +if (pos + len <=MAX_INLINE_DATA (inode)) { +read_inline_data (inode, page, ipage);set_inode_flag (inode,FI_DATA_EXIST );if (inode->i_nlink)set_inline_node (ipage);
fs/f2fs/f2fs.h +42 -9
92 lines not on this page · raw message
fs/f2fs/inline.c +51 -50
304 lines not on this page · raw message
fs/f2fs/inode.c +2 -2
@@ -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) { -void *inline_data =inline_data_addr (ipage); +void *inline_data =inline_data_addr (inode, ipage);__le32 *start = inline_data; -__le32 *end = start +MAX_INLINE_DATA /sizeof (__le32); +__le32 *end = start +MAX_INLINE_DATA (inode) /sizeof (__le32);while (start < end) {if (*start++) {
fs/f2fs/super.c +3 -0
@@ -446,6 +446,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)#endif /* Will be used by directory only */ fi->i_dir_level =F2FS_SB (sb)->dir_level; + + fi->i_inline_reserved =DEF_INLINE_RESERVED_SIZE ; +return &fi->vfs_inode; }
include/linux/f2fs_fs.h +1 -22
@@ -206,9 +206,6 @@ struct f2fs_extent {#define F2FS_DATA_EXIST 0x08/* file inline data exist flag */ #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 {__le16 i_mode;/* file mode */ __u8 i_advise;/* file hints */
@@ -465,7 +462,7 @@ typedef __le32 f2fs_hash_t;#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 * bitmap 1 * 27 = 27 1 * 23 = 23 * reserved 1 * 3 = 3 1 * 7 = 7
@@ -501,24 +498,6 @@ struct f2fs_dentry_block {__u8 filename[NR_DENTRY_IN_BLOCK ][F2FS_SLOT_LEN ]; } __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 */ enum {F2FS_FT_UNKNOWN ,
Signature · 1 line
2.13.0.90.g1eb437020
Jaegeuk Kim
maintainerRe: [PATCH 2/6] f2fs: make max inline size changeable
Hi Chao,
Quoted 164 lines · Chao Yu
From: Chao Yu <[email protected]>
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_SIZEThen, 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 Chao Yu <[email protected]>--- fs/f2fs/data.c | 6 +-- fs/f2fs/f2fs.h | 51 +++++++++++++++++++----- fs/f2fs/inline.c | 101 ++++++++++++++++++++++++------------------------ fs/f2fs/inode.c | 4 +- fs/f2fs/super.c | 3 ++ include/linux/f2fs_fs.h | 23 +---------- 6 files changed, 102 insertions(+), 86 deletions(-)fs/f2fs/data.c +3
-3@@ -813,7 +813,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from) F2FS_GET_BLOCK_PRE_AIO : 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);if (err)return err;@@ -1857,8 +1857,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,set_new_dnode (&dn, inode, ipage, ipage,0 );if (f2fs_has_inline_data (inode)) { -if (pos + len <=MAX_INLINE_DATA ) { -read_inline_data (page, ipage); +if (pos + len <=MAX_INLINE_DATA (inode)) { +read_inline_data (inode, page, ipage);set_inode_flag (inode,FI_DATA_EXIST );if (inode->i_nlink)set_inline_node (ipage);fs/f2fs/f2fs.h +42
-9@@ -355,6 +355,25 @@ struct f2fs_flush_device {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 */ @@ -380,14 +399,19 @@ static inline void make_dentry_ptr_block(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->max =NR_INLINE_DENTRY ; - d->nr_bitmap =INLINE_DENTRY_BITMAP_SIZE ; - d->bitmap = &t->dentry_bitmap; - d->dentry = t->dentry; - d->filename = t->filename; + d->max = entry_cnt; + d->nr_bitmap = bitmap_size; + d->bitmap = t; + d->dentry = t + bitmap_size + reserved_size; + d->filename = t + bitmap_size + reserved_size + +SIZE_OF_DIR_ENTRY * entry_cnt; }/* @@ -540,6 +564,8 @@ struct f2fs_inode_info {struct extent_tree *extent_tree;/* cached extent_tree entry */ struct rw_semaphore dio_rwsem[2 ];/* avoid racing between dio and gc */ 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,@@ -2069,11 +2095,12 @@ static inline bool f2fs_is_drop_cache(struct inode *inode)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); +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)@@ -2184,6 +2211,11 @@ static inline void *f2fs_kvzalloc(size_t size, gfp_t flags)return ret; } +static inline int get_inline_reserved_size (struct inode *inode) +{ +return F2FS_I (inode)->i_inline_reserved; +} +#define get_inode_mode (i) \ ((is_inode_flag_set(i, FI_ACL_MODE)) ? \ (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))@@ -2681,7 +2713,8 @@ extern struct kmem_cache *inode_entry_slab;*/ bool f2fs_may_inline_data (struct inode *inode);bool f2fs_may_inline_dentry (struct inode *inode); -void read_inline_data (struct page *page,struct page *ipage); +void read_inline_data (struct inode *inode,struct page *page, +struct page *ipage);void truncate_inline_inode (struct inode *inode,struct page *ipage,u64 from);int f2fs_read_inline_data (struct inode *inode,struct page *page);int f2fs_convert_inline_page (struct dnode_of_data *dn,struct page *page);fs/f2fs/inline.c +1
-1@@ -22,7 +22,7 @@ bool f2fs_may_inline_data(struct inode *inode)if (!S_ISREG (inode->i_mode) && !S_ISLNK (inode->i_mode))return false; -if (i_size_read (inode) >MAX_INLINE_DATA ) +if (i_size_read (inode) >MAX_INLINE_DATA (inode))return false;if (f2fs_encrypted_inode (inode) &&S_ISREG (inode->i_mode))
fs/f2fs/inline.c bool f2fs_may_inline_dentry(struct inode *inode) · line 48
Quoted 8 lines
fs/f2fs/inline.c +2
-1@@ -42,7 +42,8 @@ bool f2fs_may_inline_dentry(struct inode *inode)return true; } -void read_inline_data (struct page *page,struct page *ipage) +void read_inline_data (struct inode *inode,struct page *page, +struct page *ipage) {void *src_addr, *dst_addr;
How about
struct inode *inode = page->mapping->host;
Thanks,
Quoted 392 lines
fs/f2fs/inline.c +48
-48@@ -51,12 +52,12 @@ void read_inline_data(struct page *page, struct page *ipage)f2fs_bug_on (F2FS_P_SB (page), page->index); -zero_user_segment (page,MAX_INLINE_DATA ,PAGE_SIZE ); +zero_user_segment (page,MAX_INLINE_DATA (inode),PAGE_SIZE );/* Copy the whole inline data block */ - src_addr =inline_data_addr (ipage); + src_addr =inline_data_addr (inode, ipage); dst_addr =kmap_atomic (page); -memcpy (dst_addr, src_addr,MAX_INLINE_DATA ); +memcpy (dst_addr, src_addr,MAX_INLINE_DATA (inode));flush_dcache_page (page);kunmap_atomic (dst_addr);if (!PageUptodate (page))@@ -67,13 +68,13 @@ void truncate_inline_inode(struct inode *inode, struct page *ipage, u64 from) {void *addr; -if (from >=MAX_INLINE_DATA ) +if (from >=MAX_INLINE_DATA (inode))return ; - addr =inline_data_addr (ipage); + addr =inline_data_addr (inode, ipage);f2fs_wait_on_page_writeback (ipage,NODE , true); -memset (addr + from,0 ,MAX_INLINE_DATA - from); +memset (addr + from,0 ,MAX_INLINE_DATA (inode) - from);set_page_dirty (ipage);if (from ==0 )@@ -98,7 +99,7 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)if (page->index)zero_user_segment (page,0 ,PAGE_SIZE );else -read_inline_data (page, ipage); +read_inline_data (inode, page, ipage);if (!PageUptodate (page))SetPageUptodate (page);@@ -128,7 +129,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)f2fs_bug_on (F2FS_P_SB (page),PageWriteback (page)); -read_inline_data (page, dn->inode_page); +read_inline_data (dn->inode, page, dn->inode_page);set_page_dirty (page);/* clear dirty state */ @@ -216,8 +217,8 @@ int f2fs_write_inline_data(struct inode *inode, struct page *page)f2fs_wait_on_page_writeback (dn.inode_page,NODE , true); src_addr =kmap_atomic (page); - dst_addr =inline_data_addr (dn.inode_page); -memcpy (dst_addr, src_addr,MAX_INLINE_DATA ); + dst_addr =inline_data_addr (inode, dn.inode_page); +memcpy (dst_addr, src_addr,MAX_INLINE_DATA (inode));kunmap_atomic (src_addr);set_page_dirty (dn.inode_page);@@ -255,9 +256,9 @@ bool recover_inline_data(struct inode *inode, struct page *npage)f2fs_wait_on_page_writeback (ipage,NODE , true); - src_addr =inline_data_addr (npage); - dst_addr =inline_data_addr (ipage); -memcpy (dst_addr, src_addr,MAX_INLINE_DATA ); + src_addr =inline_data_addr (inode, npage); + dst_addr =inline_data_addr (inode, ipage); +memcpy (dst_addr, src_addr,MAX_INLINE_DATA (inode));set_inode_flag (inode,FI_INLINE_DATA );set_inode_flag (inode,FI_DATA_EXIST );@@ -285,11 +286,11 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, struct fscrypt_name *fname, struct page **res_page) { struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); -struct f2fs_inline_dentry *inline_dentry;struct qstr name =FSTR_TO_QSTR (&fname->disk_name);struct f2fs_dir_entry *de;struct f2fs_dentry_ptr d;struct page *ipage; +void *inline_dentry;f2fs_hash_t namehash; ipage =get_node_page (sbi, dir->i_ino);@@ -300,9 +301,9 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, namehash =f2fs_dentry_hash (&name, fname); - inline_dentry =inline_data_addr (ipage); + inline_dentry =inline_data_addr (dir, ipage); -make_dentry_ptr_inline (NULL , &d, inline_dentry); +make_dentry_ptr_inline (dir, &d, inline_dentry); de =find_target_dentry (fname, namehash,NULL , &d);unlock_page (ipage);if (de)@@ -316,19 +317,19 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,int make_empty_inline_dir (struct inode *inode,struct inode *parent,struct page *ipage) { -struct f2fs_inline_dentry *inline_dentry;struct f2fs_dentry_ptr d; +void *inline_dentry; - inline_dentry =inline_data_addr (ipage); + inline_dentry =inline_data_addr (inode, ipage); -make_dentry_ptr_inline (NULL , &d, inline_dentry); +make_dentry_ptr_inline (inode, &d, inline_dentry);do_make_empty_dir (inode, parent, &d);set_page_dirty (ipage);/* update i_size to MAX_INLINE_DATA */ -if (i_size_read (inode) <MAX_INLINE_DATA ) -f2fs_i_size_write (inode,MAX_INLINE_DATA ); +if (i_size_read (inode) <MAX_INLINE_DATA (inode)) +f2fs_i_size_write (inode,MAX_INLINE_DATA (inode));return 0 ; }@@ -337,7 +338,7 @@ int make_empty_inline_dir(struct inode *inode, struct inode *parent,* release ipage in this function. */ static int f2fs_move_inline_dirents (struct inode *dir,struct page *ipage, -struct f2fs_inline_dentry *inline_dentry) +void *inline_dentry) {struct page *page;struct dnode_of_data dn;@@ -357,12 +358,12 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage, goto out;f2fs_wait_on_page_writeback (page,DATA , true); -zero_user_segment (page,MAX_INLINE_DATA ,PAGE_SIZE ); +zero_user_segment (page,MAX_INLINE_DATA (dir),PAGE_SIZE ); dentry_blk =kmap_atomic (page); -make_dentry_ptr_inline (NULL , &src, inline_dentry); -make_dentry_ptr_block (NULL , &dst, dentry_blk); +make_dentry_ptr_inline (dir, &src, inline_dentry); +make_dentry_ptr_block (dir, &dst, dentry_blk);/* copy data from inline dentry block to new dentry block */ memcpy (dst.bitmap, src.bitmap, src.nr_bitmap);@@ -395,14 +396,13 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,return err; } -static int f2fs_add_inline_entries (struct inode *dir, -struct f2fs_inline_dentry *inline_dentry) +static int f2fs_add_inline_entries (struct inode *dir,void *inline_dentry) {struct f2fs_dentry_ptr d;unsigned long bit_pos =0 ;int err =0 ; -make_dentry_ptr_inline (NULL , &d, inline_dentry); +make_dentry_ptr_inline (dir, &d, inline_dentry);while (bit_pos < d.max) {struct f2fs_dir_entry *de;@@ -444,19 +444,19 @@ static int f2fs_add_inline_entries(struct inode *dir, }static int f2fs_move_rehashed_dirents (struct inode *dir,struct page *ipage, -struct f2fs_inline_dentry *inline_dentry) +void *inline_dentry) { -struct f2fs_inline_dentry *backup_dentry; +void *backup_dentry;int err; backup_dentry =f2fs_kmalloc (F2FS_I_SB (dir), -sizeof (struct f2fs_inline_dentry ),GFP_F2FS_ZERO ); +MAX_INLINE_DATA (dir),GFP_F2FS_ZERO );if (!backup_dentry) {f2fs_put_page (ipage,1 );return -ENOMEM ; } -memcpy (backup_dentry, inline_dentry,MAX_INLINE_DATA ); +memcpy (backup_dentry, inline_dentry,MAX_INLINE_DATA (dir));truncate_inline_inode (dir, ipage,0 );unlock_page (ipage);@@ -473,9 +473,9 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,return 0 ; recover:lock_page (ipage); -memcpy (inline_dentry, backup_dentry,MAX_INLINE_DATA ); +memcpy (inline_dentry, backup_dentry,MAX_INLINE_DATA (dir));f2fs_i_depth_write (dir,0 ); -f2fs_i_size_write (dir,MAX_INLINE_DATA ); +f2fs_i_size_write (dir,MAX_INLINE_DATA (dir));set_page_dirty (ipage);f2fs_put_page (ipage,1 );@@ -484,7 +484,7 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage, }static int f2fs_convert_inline_dir (struct inode *dir,struct page *ipage, -struct f2fs_inline_dentry *inline_dentry) +void *inline_dentry) {if (!F2FS_I (dir)->i_dir_level)return f2fs_move_inline_dirents (dir, ipage, inline_dentry);@@ -500,7 +500,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,struct page *ipage;unsigned int bit_pos;f2fs_hash_t name_hash; -struct f2fs_inline_dentry *inline_dentry =NULL ; +void *inline_dentry =NULL ;struct f2fs_dentry_ptr d;int slots =GET_DENTRY_SLOTS (new_name->len);struct page *page =NULL ;@@ -510,8 +510,8 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,if (IS_ERR (ipage))return PTR_ERR (ipage); - inline_dentry =inline_data_addr (ipage); -make_dentry_ptr_inline (NULL , &d, inline_dentry); + inline_dentry =inline_data_addr (dir, ipage); +make_dentry_ptr_inline (dir, &d, inline_dentry); bit_pos =room_for_filename (d.bitmap, slots, d.max);if (bit_pos >= d.max) {@@ -557,8 +557,8 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,void f2fs_delete_inline_entry (struct f2fs_dir_entry *dentry,struct page *page,struct inode *dir,struct inode *inode) { -struct f2fs_inline_dentry *inline_dentry;struct f2fs_dentry_ptr d; +void *inline_dentry;int slots =GET_DENTRY_SLOTS (le16_to_cpu (dentry->name_len));unsigned int bit_pos;int i;@@ -566,8 +566,8 @@ void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page,lock_page (page);f2fs_wait_on_page_writeback (page,NODE , true); - inline_dentry =inline_data_addr (page); -make_dentry_ptr_inline (NULL , &d, inline_dentry); + inline_dentry =inline_data_addr (dir, page); +make_dentry_ptr_inline (dir, &d, inline_dentry); bit_pos = dentry - d.dentry;for (i =0 ; i < slots; i++)@@ -588,15 +588,15 @@ bool f2fs_empty_inline_dir(struct inode *dir)struct f2fs_sb_info *sbi =F2FS_I_SB (dir);struct page *ipage;unsigned int bit_pos =2 ; -struct f2fs_inline_dentry *inline_dentry; +void *inline_dentry;struct f2fs_dentry_ptr d; ipage =get_node_page (sbi, dir->i_ino);if (IS_ERR (ipage))return false; - inline_dentry =inline_data_addr (ipage); -make_dentry_ptr_inline (NULL , &d, inline_dentry); + inline_dentry =inline_data_addr (dir, ipage); +make_dentry_ptr_inline (dir, &d, inline_dentry); bit_pos =find_next_bit_le (d.bitmap, d.max, bit_pos);@@ -612,9 +612,9 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx, struct fscrypt_str *fstr) {struct inode *inode =file_inode (file); -struct f2fs_inline_dentry *inline_dentry =NULL ;struct page *ipage =NULL ;struct f2fs_dentry_ptr d; +void *inline_dentry =NULL ;int err;make_dentry_ptr_inline (inode, &d, inline_dentry);@@ -626,7 +626,7 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx,if (IS_ERR (ipage))return PTR_ERR (ipage); - inline_dentry =inline_data_addr (ipage); + inline_dentry =inline_data_addr (inode, ipage);make_dentry_ptr_inline (inode, &d, inline_dentry);@@ -657,7 +657,7 @@ int f2fs_inline_data_fiemap(struct inode *inode, goto out; } - ilen =min_t (size_t,MAX_INLINE_DATA ,i_size_read (inode)); + ilen =min_t (size_t,MAX_INLINE_DATA (inode),i_size_read (inode));if (start >= ilen) goto out;if (start + len < ilen)@@ -666,7 +666,8 @@ int f2fs_inline_data_fiemap(struct inode *inode,get_node_info (F2FS_I_SB (inode), inode->i_ino, &ni); byteaddr = (__u64 )ni.blk_addr << inode->i_sb->s_blocksize_bits; - byteaddr += (char *)inline_data_addr (ipage) - (char *)F2FS_INODE (ipage); + byteaddr += (char *)inline_data_addr (inode, ipage) - + (char *)F2FS_INODE (ipage); err =fiemap_fill_next_extent (fieinfo, start, byteaddr, ilen, flags); out:f2fs_put_page (ipage,1 );fs/f2fs/inode.c +2
-2@@ -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) { -void *inline_data =inline_data_addr (ipage); +void *inline_data =inline_data_addr (inode, ipage);__le32 *start = inline_data; -__le32 *end = start +MAX_INLINE_DATA /sizeof (__le32); +__le32 *end = start +MAX_INLINE_DATA (inode) /sizeof (__le32);while (start < end) {if (*start++) {fs/f2fs/super.c +3
-0@@ -446,6 +446,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)#endif /* Will be used by directory only */ fi->i_dir_level =F2FS_SB (sb)->dir_level; + + fi->i_inline_reserved =DEF_INLINE_RESERVED_SIZE ; +return &fi->vfs_inode; }include/linux/f2fs_fs.h +1
-22@@ -206,9 +206,6 @@ struct f2fs_extent {#define F2FS_DATA_EXIST 0x08/* file inline data exist flag */ #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 {__le16 i_mode;/* file mode */ __u8 i_advise;/* file hints */ @@ -465,7 +462,7 @@ typedef __le32 f2fs_hash_t;#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 * bitmap 1 * 27 = 27 1 * 23 = 23 * reserved 1 * 3 = 3 1 * 7 = 7 @@ -501,24 +498,6 @@ struct f2fs_dentry_block {__u8 filename[NR_DENTRY_IN_BLOCK ][F2FS_SLOT_LEN ]; } __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 */ enum {F2FS_FT_UNKNOWN ,Signature · 1 line
2.13.0.90.g1eb437020
Re: [PATCH 2/6] f2fs: make max inline size changeable
Hi Jaegeuk,
Quoted 170 lines · Jaegeuk Kim
Hi Chao,
Quoted 167 lines · Chao Yu
From: Chao Yu <[email protected]>
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_SIZEThen, 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 Chao Yu <[email protected]>--- fs/f2fs/data.c | 6 +-- fs/f2fs/f2fs.h | 51 +++++++++++++++++++----- fs/f2fs/inline.c | 101 ++++++++++++++++++++++++------------------------ fs/f2fs/inode.c | 4 +- fs/f2fs/super.c | 3 ++ include/linux/f2fs_fs.h | 23 +---------- 6 files changed, 102 insertions(+), 86 deletions(-)fs/f2fs/data.c +3
-3@@ -813,7 +813,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from) F2FS_GET_BLOCK_PRE_AIO : 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);if (err)return err;@@ -1857,8 +1857,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,set_new_dnode (&dn, inode, ipage, ipage,0 );if (f2fs_has_inline_data (inode)) { -if (pos + len <=MAX_INLINE_DATA ) { -read_inline_data (page, ipage); +if (pos + len <=MAX_INLINE_DATA (inode)) { +read_inline_data (inode, page, ipage);set_inode_flag (inode,FI_DATA_EXIST );if (inode->i_nlink)set_inline_node (ipage);fs/f2fs/f2fs.h +42
-9@@ -355,6 +355,25 @@ struct f2fs_flush_device {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 */ @@ -380,14 +399,19 @@ static inline void make_dentry_ptr_block(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->max =NR_INLINE_DENTRY ; - d->nr_bitmap =INLINE_DENTRY_BITMAP_SIZE ; - d->bitmap = &t->dentry_bitmap; - d->dentry = t->dentry; - d->filename = t->filename; + d->max = entry_cnt; + d->nr_bitmap = bitmap_size; + d->bitmap = t; + d->dentry = t + bitmap_size + reserved_size; + d->filename = t + bitmap_size + reserved_size + +SIZE_OF_DIR_ENTRY * entry_cnt; }/* @@ -540,6 +564,8 @@ struct f2fs_inode_info {struct extent_tree *extent_tree;/* cached extent_tree entry */ struct rw_semaphore dio_rwsem[2 ];/* avoid racing between dio and gc */ 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,@@ -2069,11 +2095,12 @@ static inline bool f2fs_is_drop_cache(struct inode *inode)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); +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)@@ -2184,6 +2211,11 @@ static inline void *f2fs_kvzalloc(size_t size, gfp_t flags)return ret; } +static inline int get_inline_reserved_size (struct inode *inode) +{ +return F2FS_I (inode)->i_inline_reserved; +} +#define get_inode_mode (i) \ ((is_inode_flag_set(i, FI_ACL_MODE)) ? \ (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))@@ -2681,7 +2713,8 @@ extern struct kmem_cache *inode_entry_slab;*/ bool f2fs_may_inline_data (struct inode *inode);bool f2fs_may_inline_dentry (struct inode *inode); -void read_inline_data (struct page *page,struct page *ipage); +void read_inline_data (struct inode *inode,struct page *page, +struct page *ipage);void truncate_inline_inode (struct inode *inode,struct page *ipage,u64 from);int f2fs_read_inline_data (struct inode *inode,struct page *page);int f2fs_convert_inline_page (struct dnode_of_data *dn,struct page *page);fs/f2fs/inline.c +1
-1@@ -22,7 +22,7 @@ bool f2fs_may_inline_data(struct inode *inode)if (!S_ISREG (inode->i_mode) && !S_ISLNK (inode->i_mode))return false; -if (i_size_read (inode) >MAX_INLINE_DATA ) +if (i_size_read (inode) >MAX_INLINE_DATA (inode))return false;if (f2fs_encrypted_inode (inode) &&S_ISREG (inode->i_mode))@@ -42,7 +42,8 @@ bool f2fs_may_inline_dentry(struct inode *inode)return true; }
Quoted 8 lines
fs/f2fs/inline.c bool f2fs_may_inline_dentry(struct inode *inode) · line 48
Quoted 5 lines
fs/f2fs/inline.c +2
-1-void read_inline_data (struct page *page,struct page *ipage) +void read_inline_data (struct inode *inode,struct page *page, +struct page *ipage) {void *src_addr, *dst_addr;How about
struct inode *inode = page->mapping->host;
More clean, I will update it.
Thanks,
Quoted 398 lines
Thanks,
Quoted 392 lines
fs/f2fs/inline.c +48
-48@@ -51,12 +52,12 @@ void read_inline_data(struct page *page, struct page *ipage)f2fs_bug_on (F2FS_P_SB (page), page->index); -zero_user_segment (page,MAX_INLINE_DATA ,PAGE_SIZE ); +zero_user_segment (page,MAX_INLINE_DATA (inode),PAGE_SIZE );/* Copy the whole inline data block */ - src_addr =inline_data_addr (ipage); + src_addr =inline_data_addr (inode, ipage); dst_addr =kmap_atomic (page); -memcpy (dst_addr, src_addr,MAX_INLINE_DATA ); +memcpy (dst_addr, src_addr,MAX_INLINE_DATA (inode));flush_dcache_page (page);kunmap_atomic (dst_addr);if (!PageUptodate (page))@@ -67,13 +68,13 @@ void truncate_inline_inode(struct inode *inode, struct page *ipage, u64 from) {void *addr; -if (from >=MAX_INLINE_DATA ) +if (from >=MAX_INLINE_DATA (inode))return ; - addr =inline_data_addr (ipage); + addr =inline_data_addr (inode, ipage);f2fs_wait_on_page_writeback (ipage,NODE , true); -memset (addr + from,0 ,MAX_INLINE_DATA - from); +memset (addr + from,0 ,MAX_INLINE_DATA (inode) - from);set_page_dirty (ipage);if (from ==0 )@@ -98,7 +99,7 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)if (page->index)zero_user_segment (page,0 ,PAGE_SIZE );else -read_inline_data (page, ipage); +read_inline_data (inode, page, ipage);if (!PageUptodate (page))SetPageUptodate (page);@@ -128,7 +129,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)f2fs_bug_on (F2FS_P_SB (page),PageWriteback (page)); -read_inline_data (page, dn->inode_page); +read_inline_data (dn->inode, page, dn->inode_page);set_page_dirty (page);/* clear dirty state */ @@ -216,8 +217,8 @@ int f2fs_write_inline_data(struct inode *inode, struct page *page)f2fs_wait_on_page_writeback (dn.inode_page,NODE , true); src_addr =kmap_atomic (page); - dst_addr =inline_data_addr (dn.inode_page); -memcpy (dst_addr, src_addr,MAX_INLINE_DATA ); + dst_addr =inline_data_addr (inode, dn.inode_page); +memcpy (dst_addr, src_addr,MAX_INLINE_DATA (inode));kunmap_atomic (src_addr);set_page_dirty (dn.inode_page);@@ -255,9 +256,9 @@ bool recover_inline_data(struct inode *inode, struct page *npage)f2fs_wait_on_page_writeback (ipage,NODE , true); - src_addr =inline_data_addr (npage); - dst_addr =inline_data_addr (ipage); -memcpy (dst_addr, src_addr,MAX_INLINE_DATA ); + src_addr =inline_data_addr (inode, npage); + dst_addr =inline_data_addr (inode, ipage); +memcpy (dst_addr, src_addr,MAX_INLINE_DATA (inode));set_inode_flag (inode,FI_INLINE_DATA );set_inode_flag (inode,FI_DATA_EXIST );@@ -285,11 +286,11 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, struct fscrypt_name *fname, struct page **res_page) { struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); -struct f2fs_inline_dentry *inline_dentry;struct qstr name =FSTR_TO_QSTR (&fname->disk_name);struct f2fs_dir_entry *de;struct f2fs_dentry_ptr d;struct page *ipage; +void *inline_dentry;f2fs_hash_t namehash; ipage =get_node_page (sbi, dir->i_ino);@@ -300,9 +301,9 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, namehash =f2fs_dentry_hash (&name, fname); - inline_dentry =inline_data_addr (ipage); + inline_dentry =inline_data_addr (dir, ipage); -make_dentry_ptr_inline (NULL , &d, inline_dentry); +make_dentry_ptr_inline (dir, &d, inline_dentry); de =find_target_dentry (fname, namehash,NULL , &d);unlock_page (ipage);if (de)@@ -316,19 +317,19 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,int make_empty_inline_dir (struct inode *inode,struct inode *parent,struct page *ipage) { -struct f2fs_inline_dentry *inline_dentry;struct f2fs_dentry_ptr d; +void *inline_dentry; - inline_dentry =inline_data_addr (ipage); + inline_dentry =inline_data_addr (inode, ipage); -make_dentry_ptr_inline (NULL , &d, inline_dentry); +make_dentry_ptr_inline (inode, &d, inline_dentry);do_make_empty_dir (inode, parent, &d);set_page_dirty (ipage);/* update i_size to MAX_INLINE_DATA */ -if (i_size_read (inode) <MAX_INLINE_DATA ) -f2fs_i_size_write (inode,MAX_INLINE_DATA ); +if (i_size_read (inode) <MAX_INLINE_DATA (inode)) +f2fs_i_size_write (inode,MAX_INLINE_DATA (inode));return 0 ; }@@ -337,7 +338,7 @@ int make_empty_inline_dir(struct inode *inode, struct inode *parent,* release ipage in this function. */ static int f2fs_move_inline_dirents (struct inode *dir,struct page *ipage, -struct f2fs_inline_dentry *inline_dentry) +void *inline_dentry) {struct page *page;struct dnode_of_data dn;@@ -357,12 +358,12 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage, goto out;f2fs_wait_on_page_writeback (page,DATA , true); -zero_user_segment (page,MAX_INLINE_DATA ,PAGE_SIZE ); +zero_user_segment (page,MAX_INLINE_DATA (dir),PAGE_SIZE ); dentry_blk =kmap_atomic (page); -make_dentry_ptr_inline (NULL , &src, inline_dentry); -make_dentry_ptr_block (NULL , &dst, dentry_blk); +make_dentry_ptr_inline (dir, &src, inline_dentry); +make_dentry_ptr_block (dir, &dst, dentry_blk);/* copy data from inline dentry block to new dentry block */ memcpy (dst.bitmap, src.bitmap, src.nr_bitmap);@@ -395,14 +396,13 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,return err; } -static int f2fs_add_inline_entries (struct inode *dir, -struct f2fs_inline_dentry *inline_dentry) +static int f2fs_add_inline_entries (struct inode *dir,void *inline_dentry) {struct f2fs_dentry_ptr d;unsigned long bit_pos =0 ;int err =0 ; -make_dentry_ptr_inline (NULL , &d, inline_dentry); +make_dentry_ptr_inline (dir, &d, inline_dentry);while (bit_pos < d.max) {struct f2fs_dir_entry *de;@@ -444,19 +444,19 @@ static int f2fs_add_inline_entries(struct inode *dir, }static int f2fs_move_rehashed_dirents (struct inode *dir,struct page *ipage, -struct f2fs_inline_dentry *inline_dentry) +void *inline_dentry) { -struct f2fs_inline_dentry *backup_dentry; +void *backup_dentry;int err; backup_dentry =f2fs_kmalloc (F2FS_I_SB (dir), -sizeof (struct f2fs_inline_dentry ),GFP_F2FS_ZERO ); +MAX_INLINE_DATA (dir),GFP_F2FS_ZERO );if (!backup_dentry) {f2fs_put_page (ipage,1 );return -ENOMEM ; } -memcpy (backup_dentry, inline_dentry,MAX_INLINE_DATA ); +memcpy (backup_dentry, inline_dentry,MAX_INLINE_DATA (dir));truncate_inline_inode (dir, ipage,0 );unlock_page (ipage);@@ -473,9 +473,9 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,return 0 ; recover:lock_page (ipage); -memcpy (inline_dentry, backup_dentry,MAX_INLINE_DATA ); +memcpy (inline_dentry, backup_dentry,MAX_INLINE_DATA (dir));f2fs_i_depth_write (dir,0 ); -f2fs_i_size_write (dir,MAX_INLINE_DATA ); +f2fs_i_size_write (dir,MAX_INLINE_DATA (dir));set_page_dirty (ipage);f2fs_put_page (ipage,1 );@@ -484,7 +484,7 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage, }static int f2fs_convert_inline_dir (struct inode *dir,struct page *ipage, -struct f2fs_inline_dentry *inline_dentry) +void *inline_dentry) {if (!F2FS_I (dir)->i_dir_level)return f2fs_move_inline_dirents (dir, ipage, inline_dentry);@@ -500,7 +500,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,struct page *ipage;unsigned int bit_pos;f2fs_hash_t name_hash; -struct f2fs_inline_dentry *inline_dentry =NULL ; +void *inline_dentry =NULL ;struct f2fs_dentry_ptr d;int slots =GET_DENTRY_SLOTS (new_name->len);struct page *page =NULL ;@@ -510,8 +510,8 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,if (IS_ERR (ipage))return PTR_ERR (ipage); - inline_dentry =inline_data_addr (ipage); -make_dentry_ptr_inline (NULL , &d, inline_dentry); + inline_dentry =inline_data_addr (dir, ipage); +make_dentry_ptr_inline (dir, &d, inline_dentry); bit_pos =room_for_filename (d.bitmap, slots, d.max);if (bit_pos >= d.max) {@@ -557,8 +557,8 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,void f2fs_delete_inline_entry (struct f2fs_dir_entry *dentry,struct page *page,struct inode *dir,struct inode *inode) { -struct f2fs_inline_dentry *inline_dentry;struct f2fs_dentry_ptr d; +void *inline_dentry;int slots =GET_DENTRY_SLOTS (le16_to_cpu (dentry->name_len));unsigned int bit_pos;int i;@@ -566,8 +566,8 @@ void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page,lock_page (page);f2fs_wait_on_page_writeback (page,NODE , true); - inline_dentry =inline_data_addr (page); -make_dentry_ptr_inline (NULL , &d, inline_dentry); + inline_dentry =inline_data_addr (dir, page); +make_dentry_ptr_inline (dir, &d, inline_dentry); bit_pos = dentry - d.dentry;for (i =0 ; i < slots; i++)@@ -588,15 +588,15 @@ bool f2fs_empty_inline_dir(struct inode *dir)struct f2fs_sb_info *sbi =F2FS_I_SB (dir);struct page *ipage;unsigned int bit_pos =2 ; -struct f2fs_inline_dentry *inline_dentry; +void *inline_dentry;struct f2fs_dentry_ptr d; ipage =get_node_page (sbi, dir->i_ino);if (IS_ERR (ipage))return false; - inline_dentry =inline_data_addr (ipage); -make_dentry_ptr_inline (NULL , &d, inline_dentry); + inline_dentry =inline_data_addr (dir, ipage); +make_dentry_ptr_inline (dir, &d, inline_dentry); bit_pos =find_next_bit_le (d.bitmap, d.max, bit_pos);@@ -612,9 +612,9 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx, struct fscrypt_str *fstr) {struct inode *inode =file_inode (file); -struct f2fs_inline_dentry *inline_dentry =NULL ;struct page *ipage =NULL ;struct f2fs_dentry_ptr d; +void *inline_dentry =NULL ;int err;make_dentry_ptr_inline (inode, &d, inline_dentry);@@ -626,7 +626,7 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx,if (IS_ERR (ipage))return PTR_ERR (ipage); - inline_dentry =inline_data_addr (ipage); + inline_dentry =inline_data_addr (inode, ipage);make_dentry_ptr_inline (inode, &d, inline_dentry);@@ -657,7 +657,7 @@ int f2fs_inline_data_fiemap(struct inode *inode, goto out; } - ilen =min_t (size_t,MAX_INLINE_DATA ,i_size_read (inode)); + ilen =min_t (size_t,MAX_INLINE_DATA (inode),i_size_read (inode));if (start >= ilen) goto out;if (start + len < ilen)@@ -666,7 +666,8 @@ int f2fs_inline_data_fiemap(struct inode *inode,get_node_info (F2FS_I_SB (inode), inode->i_ino, &ni); byteaddr = (__u64 )ni.blk_addr << inode->i_sb->s_blocksize_bits; - byteaddr += (char *)inline_data_addr (ipage) - (char *)F2FS_INODE (ipage); + byteaddr += (char *)inline_data_addr (inode, ipage) - + (char *)F2FS_INODE (ipage); err =fiemap_fill_next_extent (fieinfo, start, byteaddr, ilen, flags); out:f2fs_put_page (ipage,1 );fs/f2fs/inode.c +2
-2@@ -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) { -void *inline_data =inline_data_addr (ipage); +void *inline_data =inline_data_addr (inode, ipage);__le32 *start = inline_data; -__le32 *end = start +MAX_INLINE_DATA /sizeof (__le32); +__le32 *end = start +MAX_INLINE_DATA (inode) /sizeof (__le32);while (start < end) {if (*start++) {fs/f2fs/super.c +3
-0@@ -446,6 +446,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)#endif /* Will be used by directory only */ fi->i_dir_level =F2FS_SB (sb)->dir_level; + + fi->i_inline_reserved =DEF_INLINE_RESERVED_SIZE ; +return &fi->vfs_inode; }include/linux/f2fs_fs.h +1
-22@@ -206,9 +206,6 @@ struct f2fs_extent {#define F2FS_DATA_EXIST 0x08/* file inline data exist flag */ #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 {__le16 i_mode;/* file mode */ __u8 i_advise;/* file hints */ @@ -465,7 +462,7 @@ typedef __le32 f2fs_hash_t;#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 * bitmap 1 * 27 = 27 1 * 23 = 23 * reserved 1 * 3 = 3 1 * 7 = 7 @@ -501,24 +498,6 @@ struct f2fs_dentry_block {__u8 filename[NR_DENTRY_IN_BLOCK ][F2FS_SLOT_LEN ]; } __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 */ enum {F2FS_FT_UNKNOWN ,Signature · 1 line
2.13.0.90.g1eb437020.
Chao Yu
maintainerPATCH 3/6 f2fs: enhance on-disk inode structure scalability
In reply to Chao YuFrom: Chao Yu <[email protected]>
This patch add new flag F2FS_EXTRA_ATTR storing in inode.i_inline to indicate that on-disk structure of current inode is extended.
In order to extend, we changed the inode structure a bit:
Original one:
struct f2fs_inode {
...
struct f2fs_extent i_ext;
__le32 i_addr[DEF_ADDRS_PER_INODE];
__le32 i_nid[DEF_NIDS_PER_INODE];
}Extended one:
struct f2fs_inode {
...
struct f2fs_extent i_ext;
union {
struct {
__le16 i_extra_isize;
__le16 i_padding;
};
__le32 i_addr[DEF_ADDRS_PER_INODE];
};
__le32 i_nid[DEF_NIDS_PER_INODE];
}Once F2FS_EXTRA_ATTR is set, we will steal four bytes in the head of i_addr field for storing i_extra_isize and i_padding. with i_extra_isize, we can calculate actual size of reserved space in i_addr, available attribute fields included in total extra attribute fields for current inode can be described as below:
+--------------------+ | .i_mode | | ... | | .i_ext | +--------------------+ | .i_extra_isize |-----+ | .i_padding | | | .i_prjid | | | .i_atime_extra | | | .i_ctime_extra | | | .i_mtime_extra |<----+ | .i_inode_cs |<----- store blkaddr/inline from here | .i_xattr_cs | | ... | +--------------------+ | | | block address | | | +--------------------+ | .i_nid | +--------------------+ | node_footer | | (nid, ino, offset) | +--------------------+
Hence, with this patch, we would enhance scalability of f2fs inode for storing more newly added attribute.
--- fs/f2fs/data.c | 15 ++++++++----- fs/f2fs/f2fs.h | 60 +++++++++++++++++++++++++++++++++++++------------ fs/f2fs/file.c | 23 ++++++++++++------- fs/f2fs/gc.c | 2 +- fs/f2fs/inode.c | 32 +++++++++++++++++--------- fs/f2fs/namei.c | 3 +++ fs/f2fs/node.c | 7 ++++-- fs/f2fs/recovery.c | 7 +++--- fs/f2fs/super.c | 11 ++++++--- include/linux/f2fs_fs.h | 13 +++++++++-- 10 files changed, 124 insertions(+), 49 deletions(-)
fs/f2fs/data.c +10 -5
@@ -460,10 +460,14 @@ static void __set_data_blkaddr(struct dnode_of_data *dn) {struct f2fs_node *rn =F2FS_NODE (dn->node_page);__le32 *addr_array; +int base =0 ; + +if (IS_INODE (dn->node_page) &&f2fs_has_extra_attr (dn->inode)) + base =get_extra_isize (dn->inode);/* Get physical address of data block */ addr_array =blkaddr_in_node (rn); - addr_array[dn->ofs_in_node] =cpu_to_le32 (dn->data_blkaddr); + addr_array[base + dn->ofs_in_node] =cpu_to_le32 (dn->data_blkaddr); }/*
@@ -507,8 +511,8 @@ int reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count)f2fs_wait_on_page_writeback (dn->node_page,NODE , true);for (; count >0 ; dn->ofs_in_node++) { -block_t blkaddr = -datablock_addr (dn->node_page, dn->ofs_in_node); +block_t blkaddr =datablock_addr (dn->inode, + dn->node_page, dn->ofs_in_node);if (blkaddr ==NULL_ADDR ) { dn->data_blkaddr =NEW_ADDR ;__set_data_blkaddr (dn);
@@ -755,7 +759,8 @@ static int __allocate_data_block(struct dnode_of_data *dn)if (unlikely (is_inode_flag_set (dn->inode,FI_NO_ALLOC )))return -EPERM ; - dn->data_blkaddr =datablock_addr (dn->node_page, dn->ofs_in_node); + dn->data_blkaddr =datablock_addr (dn->inode, + dn->node_page, dn->ofs_in_node);if (dn->data_blkaddr ==NEW_ADDR ) goto alloc;
@@ -902,7 +907,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, end_offset =ADDRS_PER_PAGE (dn.node_page, inode); next_block: - blkaddr =datablock_addr (dn.node_page, dn.ofs_in_node); + blkaddr =datablock_addr (dn.inode, dn.node_page, dn.ofs_in_node);if (blkaddr ==NEW_ADDR || blkaddr ==NULL_ADDR ) {if (create) {
fs/f2fs/f2fs.h +46 -14
133 lines not on this page · raw message
fs/f2fs/file.c +15 -8
@@ -382,7 +382,8 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence) dn.ofs_in_node++, pgofs++, data_ofs = (loff_t)pgofs << PAGE_SHIFT) {block_t blkaddr; - blkaddr =datablock_addr (dn.node_page, dn.ofs_in_node); + blkaddr =datablock_addr (dn.inode, + dn.node_page, dn.ofs_in_node);if (__found_offset (blkaddr, dirty, pgofs, whence)) {f2fs_put_dnode (&dn);
@@ -467,9 +468,13 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count)struct f2fs_node *raw_node;int nr_free =0 , ofs = dn->ofs_in_node, len = count;__le32 *addr; +int base =0 ; + +if (IS_INODE (dn->node_page) &&f2fs_has_extra_attr (dn->inode)) + base =get_extra_isize (dn->inode); raw_node =F2FS_NODE (dn->node_page); - addr =blkaddr_in_node (raw_node) + ofs; + addr =blkaddr_in_node (raw_node) + base + ofs;for (; count >0 ; count--, addr++, dn->ofs_in_node++) {block_t blkaddr =le32_to_cpu (*addr);
@@ -927,7 +932,8 @@ static int __read_out_blkaddrs(struct inode *inode, block_t *blkaddr, done =min ((pgoff_t )ADDRS_PER_PAGE (dn.node_page, inode) - dn.ofs_in_node, len);for (i =0 ; i < done; i++, blkaddr++, do_replace++, dn.ofs_in_node++) { - *blkaddr =datablock_addr (dn.node_page, dn.ofs_in_node); + *blkaddr =datablock_addr (dn.inode, + dn.node_page, dn.ofs_in_node);if (!is_checkpointed_data (sbi, *blkaddr)) {if (test_opt (sbi,LFS )) {
@@ -1003,8 +1009,8 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,ADDRS_PER_PAGE (dn.node_page, dst_inode) - dn.ofs_in_node, len - i); do { - dn.data_blkaddr = datablock_addr(dn.node_page, - dn.ofs_in_node); + dn.data_blkaddr = datablock_addr(dn.inode, + dn.node_page, dn.ofs_in_node); truncate_data_blocks_range(&dn, 1); if (do_replace[i]) {
@@ -1173,7 +1179,8 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,int ret;for (; index < end; index++, dn->ofs_in_node++) { -if (datablock_addr (dn->node_page, dn->ofs_in_node) ==NULL_ADDR ) +if (datablock_addr (dn->inode, dn->node_page, + dn->ofs_in_node) ==NULL_ADDR ) count++; }
@@ -1184,8 +1191,8 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start, dn->ofs_in_node = ofs_in_node;for (index = start; index < end; index++, dn->ofs_in_node++) { - dn->data_blkaddr = -datablock_addr (dn->node_page, dn->ofs_in_node); + dn->data_blkaddr =datablock_addr (dn->inode, + dn->node_page, dn->ofs_in_node);/* * reserve_new_blocks will not guarantee entire block * allocation.
fs/f2fs/gc.c +1 -1
@@ -582,7 +582,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, } *nofs =ofs_of_node (node_page); - source_blkaddr =datablock_addr (node_page, ofs_in_node); + source_blkaddr =datablock_addr (NULL , node_page, ofs_in_node);f2fs_put_page (node_page,1 );if (source_blkaddr != blkaddr)
fs/f2fs/inode.c +21 -11
@@ -49,20 +49,22 @@ void f2fs_set_inode_flags(struct inode *inode)static void __get_inode_rdev (struct inode *inode,struct f2fs_inode *ri) { +int extra_size =get_extra_isize (inode); +if (S_ISCHR (inode->i_mode) ||S_ISBLK (inode->i_mode) ||S_ISFIFO (inode->i_mode) ||S_ISSOCK (inode->i_mode)) { -if (ri->i_addr[0 ]) - inode->i_rdev = -old_decode_dev (le32_to_cpu (ri->i_addr[0 ])); +if (ri->i_addr[extra_size]) + inode->i_rdev =old_decode_dev ( +le32_to_cpu (ri->i_addr[extra_size]));else - inode->i_rdev = -new_decode_dev (le32_to_cpu (ri->i_addr[1 ])); + inode->i_rdev =new_decode_dev ( +le32_to_cpu (ri->i_addr[extra_size +1 ])); } }static bool __written_first_block (struct f2fs_inode *ri) { -block_t addr =le32_to_cpu (ri->i_addr[0 ]); +block_t addr =le32_to_cpu (ri->i_addr[offset_in_addr (ri)]);if (addr !=NEW_ADDR && addr !=NULL_ADDR )return true;
@@ -71,16 +73,18 @@ static bool __written_first_block(struct f2fs_inode *ri)static void __set_inode_rdev (struct inode *inode,struct f2fs_inode *ri) { +int extra_size =get_extra_isize (inode); +if (S_ISCHR (inode->i_mode) ||S_ISBLK (inode->i_mode)) {if (old_valid_dev (inode->i_rdev)) { - ri->i_addr[0 ] = + ri->i_addr[extra_size] =cpu_to_le32 (old_encode_dev (inode->i_rdev)); - ri->i_addr[1 ] =0 ; + ri->i_addr[extra_size +1 ] =0 ; }else { - ri->i_addr[0 ] =0 ; - ri->i_addr[1 ] = + ri->i_addr[extra_size] =0 ; + ri->i_addr[extra_size +1 ] =cpu_to_le32 (new_encode_dev (inode->i_rdev)); - ri->i_addr[2 ] =0 ; + ri->i_addr[extra_size +2 ] =0 ; } } }
@@ -153,6 +157,9 @@ static int do_read_inode(struct inode *inode)get_inline_info (inode, ri); + fi->i_extra_isize =f2fs_has_extra_attr (inode) ? +le16_to_cpu (ri->i_extra_isize) :0 ; +/* check data exist */ if (f2fs_has_inline_data (inode) && !f2fs_exist_data (inode))__recover_inline_status (inode, node_page);
@@ -292,6 +299,9 @@ int update_inode(struct inode *inode, struct page *node_page) ri->i_generation =cpu_to_le32 (inode->i_generation); ri->i_dir_level =F2FS_I (inode)->i_dir_level; +if (f2fs_has_extra_attr (inode)) + ri->i_extra_isize =cpu_to_le16 (F2FS_I (inode)->i_extra_isize); +__set_inode_rdev (inode, ri);set_cold_node (inode, node_page);
fs/f2fs/namei.c +3 -0
@@ -85,6 +85,9 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)stat_inc_inline_inode (inode);stat_inc_inline_dir (inode); +F2FS_I (inode)->i_extra_isize =f2fs_has_extra_attr (inode) ? +F2FS_TOTAL_EXTRA_ATTR_SIZE :0 ; +trace_f2fs_new_inode (inode,0 );return inode;
fs/f2fs/node.c +5 -2
@@ -654,7 +654,8 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) dn->nid = nids[level]; dn->ofs_in_node = offset[level]; dn->node_page = npage[level]; - dn->data_blkaddr =datablock_addr (dn->node_page, dn->ofs_in_node); + dn->data_blkaddr =datablock_addr (dn->inode, + dn->node_page, dn->ofs_in_node);return 0 ; release_pages:
@@ -2262,7 +2263,9 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) dst->i_blocks =cpu_to_le64 (1 ); dst->i_links =cpu_to_le32 (1 ); dst->i_xattr_nid =0 ; - dst->i_inline = src->i_inline &F2FS_INLINE_XATTR ; + dst->i_inline = src->i_inline & (F2FS_INLINE_XATTR |F2FS_EXTRA_ATTR ); +if (dst->i_inline &F2FS_EXTRA_ATTR ) + dst->i_extra_isize = src->i_extra_isize; new_ni = old_ni; new_ni.ino = ino;
fs/f2fs/recovery.c +4 -3
@@ -361,7 +361,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,return 0 ; truncate_out: -if (datablock_addr (tdn.node_page, tdn.ofs_in_node) == blkaddr) +if (datablock_addr (tdn.inode, tdn.node_page, + tdn.ofs_in_node) == blkaddr)truncate_data_blocks_range (&tdn,1 );if (dn->inode->i_ino == nid && !dn->inode_page_locked)unlock_page (dn->inode_page);
@@ -414,8 +415,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,for (; start < end; start++, dn.ofs_in_node++) {block_t src, dest; - src =datablock_addr (dn.node_page, dn.ofs_in_node); - dest =datablock_addr (page, dn.ofs_in_node); + src =datablock_addr (dn.inode, dn.node_page, dn.ofs_in_node); + dest =datablock_addr (dn.inode, page, dn.ofs_in_node);/* skip recovering if dest is the same as src */ if (src == dest)
fs/f2fs/super.c +8 -3
@@ -447,8 +447,6 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)/* Will be used by directory only */ fi->i_dir_level =F2FS_SB (sb)->dir_level; - fi->i_inline_reserved =DEF_INLINE_RESERVED_SIZE ; -return &fi->vfs_inode; }
@@ -1306,9 +1304,16 @@ static const struct export_operations f2fs_export_ops = {static loff_t max_file_blocks (void ) { -loff_t result = (DEF_ADDRS_PER_INODE -F2FS_INLINE_XATTR_ADDRS ); +loff_t result =0 ;loff_t leaf_count =ADDRS_PER_BLOCK ; +/* +* note: previously, result is equal to (DEF_ADDRS_PER_INODE - +* F2FS_INLINE_XATTR_ADDRS), but now f2fs try to reserve more +* space in inode.i_addr, it will be more safe to reassign +* result as zero. +*/ +/* two direct node blocks */ result += (leaf_count *2 );
include/linux/f2fs_fs.h +11 -2
@@ -186,6 +186,8 @@ struct f2fs_extent {#define F2FS_NAME_LEN 255#define F2FS_INLINE_XATTR_ADDRS 50/* 200 bytes for inline xattrs */ #define DEF_ADDRS_PER_INODE 923/* Address Pointers in an Inode */ +#define CUR_ADDRS_PER_INODE (inode) (DEF_ADDRS_PER_INODE - \ + get_extra_isize(inode))#define DEF_NIDS_PER_INODE 5/* Node IDs in an Inode */ #define ADDRS_PER_INODE (inode) addrs_per_inode(inode)#define ADDRS_PER_BLOCK 1018/* Address Pointers in a Direct Block */
@@ -205,6 +207,7 @@ struct f2fs_extent {#define F2FS_INLINE_DENTRY 0x04/* file inline dentry flag */ #define F2FS_DATA_EXIST 0x08/* file inline data exist flag */ #define F2FS_INLINE_DOTS 0x10/* file having implicit dot dentries */ +#define F2FS_EXTRA_ATTR 0x20/* file having extra attribute */ struct f2fs_inode {__le16 i_mode;/* file mode */
@@ -232,8 +235,14 @@ struct f2fs_inode {struct f2fs_extent i_ext;/* caching a largest extent */ -__le32 i_addr[DEF_ADDRS_PER_INODE ];/* Pointers to data blocks */ - +union { +struct { +__le16 i_extra_isize;/* extra inode attribute size */ +__le16 i_padding;/* padding */ +__le32 i_extra_end[0 ];/* for attribute size calculation */ + }; +__le32 i_addr[DEF_ADDRS_PER_INODE ];/* Pointers to data blocks */ + };__le32 i_nid[DEF_NIDS_PER_INODE ];/* direct(2), indirect(2), double_indirect(1) node id */ } __packed;
Signature · 1 line
2.13.0.90.g1eb437020
Chao Yu
maintainerPATCH 4/6 f2fs: support project quota
In reply to Chao YuFrom: Chao Yu <[email protected]>
This patch adds to support plain project quota.
--- Documentation/filesystems/f2fs.txt | 1 + fs/f2fs/f2fs.h | 29 +++++++++++++++++++++++++++++ fs/f2fs/file.c | 13 ------------- fs/f2fs/inode.c | 23 ++++++++++++++++++++++- fs/f2fs/namei.c | 32 ++++++++++++++++++++++++++++++++ fs/f2fs/node.c | 6 +++++- fs/f2fs/super.c | 17 ++++++++++++++++- include/linux/f2fs_fs.h | 3 +++ 8 files changed, 108 insertions(+), 16 deletions(-)
Documentation/filesystems/f2fs.txt +1 -0
@@ -164,6 +164,7 @@ io_bits=%u Set the bit size of write IO requests. It should be set with "mode=lfs". usrquota Enable plain user disk quota accounting. grpquota Enable plain group disk quota accounting. +prjquota Enable plain project quota accounting. ================================================================================ DEBUGFS ENTRIES
fs/f2fs/f2fs.h +29 -0
@@ -91,6 +91,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_LFS 0x00040000#define F2FS_MOUNT_USRQUOTA 0x00080000#define F2FS_MOUNT_GRPQUOTA 0x00100000 +#define F2FS_MOUNT_PRJQUOTA 0x00200000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -112,6 +113,7 @@ struct f2fs_mount_info {#define F2FS_FEATURE_ENCRYPT 0x0001#define F2FS_FEATURE_BLKZONED 0x0002 +#define F2FS_FEATURE_PRJQUOTA 0x0004#define F2FS_HAS_FEATURE (sb, mask) \ ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -566,6 +568,7 @@ struct f2fs_inode_info {struct rw_semaphore i_mmap_sem;int i_extra_isize;/* size of extra space located in i_addr */ +kprojid_t i_projid;/* id for project quota */ }; static inline void get_extent_info(struct extent_info *ext,
@@ -1880,6 +1883,20 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) *addr ^= mask; } +#define F2FS_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL)) +#define F2FS_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL) +#define F2FS_FL_INHERITED (FS_PROJINHERIT_FL) + +static inline __u32 f2fs_mask_flags (umode_t mode,__u32 flags) +{ +if (S_ISDIR (mode)) +return flags; +else if (S_ISREG (mode)) +return flags &F2FS_REG_FLMASK ; +else +return flags &F2FS_OTHER_FLMASK ; +} +/* used for f2fs_inode_info->flags */ enum {FI_NEW_INODE ,/* indicate newly allocated inode */
@@ -1909,6 +1926,7 @@ enum {FI_NO_PREALLOC ,/* indicate skipped preallocated blocks */ FI_HOT_DATA ,/* indicate file is hot */ FI_EXTRA_ATTR ,/* indicate file has extra attribute */ + FI_PROJ_INHERIT, /* indicate file inherits projectid */ }; static inline void __mark_inode_dirty_flag(struct inode *inode,
@@ -2252,6 +2270,12 @@ static inline int get_extra_isize(struct inode *inode) (offsetof(struct f2fs_inode , i_extra_end) - \ offsetof(struct f2fs_inode, i_extra_isize)) \ +#define F2FS_OLD_ATTRIBUTE_SIZE (offsetof(struct f2fs_inode, i_addr)) +#define F2FS_FITS_IN_INODE (f2fs_inode, extra_isize, field) \ + ((offsetof(typeof(*f2fs_inode), field) + \ + sizeof((f2fs_inode)->field)) \ + <= (F2FS_OLD_ATTRIBUTE_SIZE + extra_isize)) \ +/* * file.c */
@@ -2846,6 +2870,11 @@ static inline int f2fs_sb_mounted_blkzoned(struct super_block *sb)return F2FS_HAS_FEATURE (sb,F2FS_FEATURE_BLKZONED ); } +static inline int f2fs_sb_has_project_quota (struct super_block *sb) +{ +return F2FS_HAS_FEATURE (sb,F2FS_FEATURE_PRJQUOTA ); +} +#ifdef CONFIG_BLK_DEV_ZONED static inline int get_blkz_type (struct f2fs_sb_info *sbi,struct block_device *bdev,block_t blkaddr)
fs/f2fs/file.c +0 -13
@@ -1502,19 +1502,6 @@ static int f2fs_release_file(struct inode *inode, struct file *filp)return 0 ; } -#define F2FS_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL)) -#define F2FS_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL) - -static inline __u32 f2fs_mask_flags (umode_t mode,__u32 flags) -{ -if (S_ISDIR (mode)) -return flags; -else if (S_ISREG (mode)) -return flags &F2FS_REG_FLMASK ; -else -return flags &F2FS_OTHER_FLMASK ; -} -static int f2fs_ioc_getflags (struct file *filp,unsigned long arg) {struct inode *inode =file_inode (filp);
fs/f2fs/inode.c +22 -1
@@ -114,6 +114,7 @@ static int do_read_inode(struct inode *inode)struct f2fs_inode_info *fi =F2FS_I (inode);struct page *node_page;struct f2fs_inode *ri; +projid_t i_projid;/* Check if ino is within scope */ if (check_nid_range (sbi, inode->i_ino)) {
@@ -173,6 +174,16 @@ static int do_read_inode(struct inode *inode)if (!need_inode_block_update (sbi, inode->i_ino)) fi->last_disk_size = inode->i_size; +if (fi->i_flags &FS_PROJINHERIT_FL ) +set_inode_flag (inode,FI_PROJ_INHERIT ); + +if (f2fs_has_extra_attr (inode) && +F2FS_FITS_IN_INODE (ri, fi->i_extra_isize, i_projid)) + i_projid = (projid_t )le32_to_cpu (ri->i_projid); +else + i_projid =F2FS_DEF_PROJID ; + fi->i_projid =make_kprojid (&init_user_ns, i_projid); +f2fs_put_page (node_page,1 );stat_inc_inline_xattr (inode);
@@ -299,9 +310,19 @@ int update_inode(struct inode *inode, struct page *node_page) ri->i_generation =cpu_to_le32 (inode->i_generation); ri->i_dir_level =F2FS_I (inode)->i_dir_level; -if (f2fs_has_extra_attr (inode)) +if (f2fs_has_extra_attr (inode)) { ri->i_extra_isize =cpu_to_le16 (F2FS_I (inode)->i_extra_isize); +if (F2FS_FITS_IN_INODE (ri,F2FS_I (inode)->i_extra_isize, + i_projid)) { +projid_t i_projid; + + i_projid =from_kprojid (&init_user_ns, +F2FS_I (inode)->i_projid); + ri->i_projid =cpu_to_le32 (i_projid); + } + } +__set_inode_rdev (inode, ri);set_cold_node (inode, node_page);
fs/f2fs/namei.c +32 -0
@@ -58,6 +58,13 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) goto fail; } +if (f2fs_sb_has_project_quota (sbi->sb) && + (F2FS_I (dir)->i_flags &FS_PROJINHERIT_FL )) +F2FS_I (inode)->i_projid =F2FS_I (dir)->i_projid; +else +F2FS_I (inode)->i_projid =make_kprojid (&init_user_ns, +F2FS_DEF_PROJID ); + err =dquot_initialize (inode);if (err) goto fail_drop;
@@ -71,6 +78,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)f2fs_set_encrypted_inode (inode);set_inode_flag (inode,FI_NEW_INODE ); +set_inode_flag (inode,FI_EXTRA_ATTR );if (test_opt (sbi,INLINE_XATTR ))set_inode_flag (inode,FI_INLINE_XATTR );
@@ -88,6 +96,12 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)F2FS_I (inode)->i_extra_isize =f2fs_has_extra_attr (inode) ?F2FS_TOTAL_EXTRA_ATTR_SIZE :0 ; +F2FS_I (inode)->i_flags = +f2fs_mask_flags (mode,F2FS_I (dir)->i_flags &F2FS_FL_INHERITED ); + +if (F2FS_I (inode)->i_flags &FS_PROJINHERIT_FL ) +set_inode_flag (inode,FI_PROJ_INHERIT ); +trace_f2fs_new_inode (inode,0 );return inode;
@@ -207,6 +221,11 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, !fscrypt_has_permitted_context(dir, inode))return -EPERM ; +if (is_inode_flag_set (dir,FI_PROJ_INHERIT ) && + (!projid_eq (F2FS_I (dir)->i_projid, +F2FS_I (old_dentry->d_inode)->i_projid))) +return -EXDEV ; + err =dquot_initialize (dir);if (err)return err;
@@ -727,6 +746,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, goto out; } +if (is_inode_flag_set (new_dir,FI_PROJ_INHERIT ) && + (!projid_eq (F2FS_I (new_dir)->i_projid, +F2FS_I (old_dentry->d_inode)->i_projid))) +return -EXDEV ; + err =dquot_initialize (old_dir);if (err) goto out;
@@ -915,6 +939,14 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, !fscrypt_has_permitted_context(old_dir, new_inode)))return -EPERM ; +if ((is_inode_flag_set (new_dir,FI_PROJ_INHERIT ) && + !projid_eq (F2FS_I (new_dir)->i_projid, +F2FS_I (old_dentry->d_inode)->i_projid)) || + (is_inode_flag_set (new_dir,FI_PROJ_INHERIT ) && + !projid_eq (F2FS_I (old_dir)->i_projid, +F2FS_I (new_dentry->d_inode)->i_projid))) +return -EXDEV ; + err =dquot_initialize (old_dir);if (err) goto out;
fs/f2fs/node.c +5 -1
@@ -2264,8 +2264,12 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) dst->i_links =cpu_to_le32 (1 ); dst->i_xattr_nid =0 ; dst->i_inline = src->i_inline & (F2FS_INLINE_XATTR |F2FS_EXTRA_ATTR ); -if (dst->i_inline &F2FS_EXTRA_ATTR ) +if (dst->i_inline &F2FS_EXTRA_ATTR ) { dst->i_extra_isize = src->i_extra_isize; +if (F2FS_FITS_IN_INODE (src,le16_to_cpu (src->i_extra_isize), + i_projid)) + dst->i_projid = src->i_projid; + } new_ni = old_ni; new_ni.ino = ino;
fs/f2fs/super.c +16 -1
@@ -109,6 +109,7 @@ enum { Opt_nolazytime, Opt_usrquota, Opt_grpquota, + Opt_prjquota, Opt_err, };
@@ -146,6 +147,7 @@ static match_table_t f2fs_tokens = { {Opt_nolazytime, "nolazytime"}, {Opt_usrquota, "usrquota"}, {Opt_grpquota, "grpquota"}, + {Opt_prjquota, "prjquota"}, {Opt_err, NULL}, };
@@ -392,9 +394,13 @@ static int parse_options(struct super_block *sb, char *options)case Opt_grpquota:set_opt (sbi,GRPQUOTA );break ; +case Opt_prjquota: +set_opt (sbi,PRJQUOTA ); +break ;#else case Opt_usrquota:case Opt_grpquota: +case Opt_prjquota:f2fs_msg (sb,KERN_INFO ,"quota operations not supported" );break ;
@@ -814,6 +820,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)seq_puts (seq,",usrquota" );if (test_opt (sbi,GRPQUOTA ))seq_puts (seq,",grpquota" ); +if (test_opt (sbi,PRJQUOTA )) +seq_puts (seq,",prjquota" );#endif return 0 ;
@@ -1172,6 +1180,12 @@ static void f2fs_quota_off_umount(struct super_block *sb)f2fs_quota_off (sb, type); } +int f2fs_get_projid (struct inode *inode,kprojid_t *projid) +{ + *projid =F2FS_I (inode)->i_projid; +return 0 ; +} +static const struct dquot_operations f2fs_quota_operations = { .get_reserved_space = f2fs_get_reserved_space, .write_dquot = dquot_commit,
@@ -1181,6 +1195,7 @@ static const struct dquot_operations f2fs_quota_operations = { .write_info = dquot_commit_info, .alloc_dquot = dquot_alloc, .destroy_dquot = dquot_destroy, + .get_projid = f2fs_get_projid, .get_next_id = dquot_get_next_id, };
@@ -1964,7 +1979,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)#ifdef CONFIG_QUOTA sb->dq_op = &f2fs_quota_operations; sb->s_qcop = &f2fs_quotactl_ops; - sb->s_quota_types =QTYPE_MASK_USR |QTYPE_MASK_GRP ; + sb->s_quota_types =QTYPE_MASK_USR |QTYPE_MASK_GRP |QTYPE_MASK_PRJ ;#endif sb->s_op = &f2fs_sops;
include/linux/f2fs_fs.h +3 -0
@@ -239,6 +239,7 @@ struct f2fs_inode {struct {__le16 i_extra_isize;/* extra inode attribute size */ __le16 i_padding;/* padding */ +__le32 i_projid;/* project id */ __le32 i_extra_end[0 ];/* for attribute size calculation */ };__le32 i_addr[DEF_ADDRS_PER_INODE ];/* Pointers to data blocks */
@@ -522,4 +523,6 @@ enum {#define S_SHIFT 12 +#define F2FS_DEF_PROJID 0/* default project ID */ +#endif /* _LINUX_F2FS_FS_H */
Signature · 6 lines
2.13.0.90.g1eb437020 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Chao Yu
maintainerPATCH 5/6 f2fs: support F2FS_IOC_FS{GET,SET}XATTR
In reply to Chao YuFrom: Chao Yu <[email protected]>
This patch adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR ioctl interface support for f2fs. The interface is kept consistent with the one of ext4/xfs.
--- fs/f2fs/f2fs.h | 3 + fs/f2fs/file.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 238 insertions(+), 28 deletions(-)
fs/f2fs/f2fs.h +3 -0
@@ -334,6 +334,9 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,#define F2FS_IOC32_GETVERSION FS_IOC32_GETVERSION#endif +#define F2FS_IOC_FSGETXATTR FS_IOC_FSGETXATTR +#define F2FS_IOC_FSSETXATTR FS_IOC_FSSETXATTR +struct f2fs_gc_range {u32 sync;u64 start;
fs/f2fs/file.c +235 -28
307 lines not on this page · raw message
Signature · 1 line
2.13.0.90.g1eb437020
Chao Yu
maintainerPATCH 6/6 f2fs: introduce f2fs_statfs_project
In reply to Chao YuFrom: Chao Yu <[email protected]>
This patch introduces f2fs_statfs_project, it enables to show usage status of directory tree which is limited with project quota.
--- fs/f2fs/super.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
fs/f2fs/super.c +48 -0
@@ -705,6 +705,48 @@ static int f2fs_unfreeze(struct super_block *sb)return 0 ; } +#ifdef CONFIG_QUOTA +static int f2fs_statfs_project (struct super_block *sb, +kprojid_t projid,struct kstatfs *buf) +{ +struct kqid qid; +struct dquot *dquot; +u64 limit; +u64 curblock; + + qid =make_kqid_projid (projid); + dquot =dqget (sb, qid); +if (IS_ERR (dquot)) +return PTR_ERR (dquot); +spin_lock (&dq_data_lock); + + limit = (dquot->dq_dqb.dqb_bsoftlimit ? + dquot->dq_dqb.dqb_bsoftlimit : + dquot->dq_dqb.dqb_bhardlimit) >> sb->s_blocksize_bits; +if (limit && buf->f_blocks > limit) { + curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits; + buf->f_blocks = limit; + buf->f_bfree = buf->f_bavail = + (buf->f_blocks > curblock) ? + (buf->f_blocks - curblock) :0 ; + } + + limit = dquot->dq_dqb.dqb_isoftlimit ? + dquot->dq_dqb.dqb_isoftlimit : + dquot->dq_dqb.dqb_ihardlimit; +if (limit && buf->f_files > limit) { + buf->f_files = limit; + buf->f_ffree = + (buf->f_files > dquot->dq_dqb.dqb_curinodes) ? + (buf->f_files - dquot->dq_dqb.dqb_curinodes) :0 ; + } + +spin_unlock (&dq_data_lock); +dqput (dquot); +return 0 ; +} +#endif +static int f2fs_statfs (struct dentry *dentry,struct kstatfs *buf) {struct super_block *sb = dentry->d_sb;
@@ -740,6 +782,12 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_fsid.val[0 ] = (u32 )id; buf->f_fsid.val[1 ] = (u32)(id >>32 ); +#ifdef CONFIG_QUOTA +if (is_inode_flag_set (dentry->d_inode,FI_PROJ_INHERIT ) && +sb_has_quota_limits_enabled (sb,PRJQUOTA )) { +f2fs_statfs_project (sb,F2FS_I (dentry->d_inode)->i_projid, buf); + } +#endif return 0 ; }
Signature · 1 line
2.13.0.90.g1eb437020