f2fs: make max inline size changeable
Subsystems (2)
Chao Yu
maintainerPATCH v2 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.
---
v2: remove unneeded parameter in read_inline_data.
fs/f2fs/data.c | 4 +-- fs/f2fs/f2fs.h | 48 ++++++++++++++++++++----- fs/f2fs/inline.c | 95 +++++++++++++++++++++++++------------------------ fs/f2fs/inode.c | 4 +-- fs/f2fs/super.c | 3 ++ include/linux/f2fs_fs.h | 23 +----------- 6 files changed, 96 insertions(+), 81 deletions(-)
fs/f2fs/data.c +2 -2
@@ -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,7 +1857,7 @@ 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 ) { +if (pos + len <=MAX_INLINE_DATA (inode)) {read_inline_data (page, ipage);set_inode_flag (inode,FI_DATA_EXIST );if (inode->i_nlink)
fs/f2fs/f2fs.h +40 -8
83 lines not on this page · raw message
fs/f2fs/inline.c +48 -47
286 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
Chao Yu
maintainerPATCH v2 3/6 f2fs: enhance on-disk inode structure scalability
From: 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_extra_end[0];
};
__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.
---
v2:
- update comments.
- set EXTRA_ATTR flag in new inode when extra_attr feature is set.
fs/f2fs/data.c | 15 +++++++---- fs/f2fs/f2fs.h | 66 ++++++++++++++++++++++++++++++++++++++----------- fs/f2fs/file.c | 23 +++++++++++------ fs/f2fs/gc.c | 2 +- fs/f2fs/inode.c | 32 +++++++++++++++--------- fs/f2fs/namei.c | 5 ++++ fs/f2fs/node.c | 7 ++++-- fs/f2fs/recovery.c | 7 +++--- fs/f2fs/super.c | 11 ++++++--- include/linux/f2fs_fs.h | 13 ++++++++-- 10 files changed, 132 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 +52 -14
151 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 +5 -0
@@ -72,6 +72,11 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)set_inode_flag (inode,FI_NEW_INODE ); +if (f2fs_sb_has_extra_attr (sbi->sb)) { +set_inode_flag (inode,FI_EXTRA_ATTR ); +F2FS_I (inode)->i_extra_isize =F2FS_TOTAL_EXTRA_ATTR_SIZE ; + } +if (test_opt (sbi,INLINE_XATTR ))set_inode_flag (inode,FI_INLINE_XATTR );if (test_opt (sbi,INLINE_DATA ) &&f2fs_may_inline_data (inode))
fs/f2fs/node.c +5 -2
@@ -655,7 +655,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:
@@ -2263,7 +2264,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 v2 4/6 f2fs: support project quota
In reply to Chao YuFrom: Chao Yu <[email protected]>
This patch adds to support plain project quota.
---
v2: rebase codes.
Documentation/filesystems/f2fs.txt | 1 + fs/f2fs/f2fs.h | 29 +++++++++++++++++++++++++++++ fs/f2fs/file.c | 13 ------------- fs/f2fs/inode.c | 23 ++++++++++++++++++++++- fs/f2fs/namei.c | 31 +++++++++++++++++++++++++++++++ fs/f2fs/node.c | 6 +++++- fs/f2fs/super.c | 17 ++++++++++++++++- include/linux/f2fs_fs.h | 3 +++ 8 files changed, 107 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)
@@ -113,6 +114,7 @@ struct f2fs_mount_info {#define F2FS_FEATURE_ENCRYPT 0x0001#define F2FS_FEATURE_BLKZONED 0x0002#define F2FS_FEATURE_EXTRA_ATTR 0x0004 +#define F2FS_FEATURE_PRJQUOTA 0x0008#define F2FS_HAS_FEATURE (sb, mask) \ ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -567,6 +569,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,
@@ -1884,6 +1887,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 */
@@ -1913,6 +1930,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,
@@ -2236,6 +2254,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 */
@@ -2833,6 +2857,11 @@ static inline int f2fs_sb_has_extra_attr(struct super_block *sb)return F2FS_HAS_FEATURE (sb,F2FS_FEATURE_EXTRA_ATTR ); } +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 +31 -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;
@@ -90,6 +97,12 @@ 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_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;
@@ -209,6 +222,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;
@@ -729,6 +747,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;
@@ -917,6 +940,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
@@ -2265,8 +2265,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 · 1 line
2.13.0.90.g1eb437020