f2fs: support plain user/group quota
Subsystems (2)
Chao Yu
maintainerPATCH v2 1/1 f2fs: support plain user/group quota
From: Chao Yu <[email protected]>
This patch adds to support plain user/group quota.
Change Note by Jaegeuk Kim.
- Use f2fs page cache for quota files in order to consider garbage collection. so, quota files are not tolerable for sudden power-cuts, so user needs to do quotacheck.
- setattr() calls dquot_transfer which will transfer inode->i_blocks. We can't reclaim that during f2fs_evict_inode(). So, we need to count node blocks as well in order to match i_blocks with dquot's space.
Note that, Chao wrote a patch to count inode->i_blocks without inode block. (f2fs: don't count inode block in in-memory inode.i_blocks)
- in f2fs_remount, we need to make RW in prior to dquot_resume.
- handle fault_injection case during f2fs_quota_off_umount
- TODO: Project quota
---
v2:
- update doc for quota support.
Documentation/filesystems/f2fs.txt | 2 + fs/f2fs/data.c | 10 +- fs/f2fs/f2fs.h | 88 +++++++++--- fs/f2fs/file.c | 34 ++++- fs/f2fs/inode.c | 5 + fs/f2fs/namei.c | 66 ++++++++- fs/f2fs/node.c | 9 +- fs/f2fs/super.c | 280 +++++++++++++++++++++++++++++++++++++ 8 files changed, 454 insertions(+), 40 deletions(-)
Documentation/filesystems/f2fs.txt +2 -0
@@ -162,6 +162,8 @@ mode=%s Control block allocation mode which supports "adaptive" writes towards main area. 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. ================================================================================ DEBUGFS ENTRIES
fs/f2fs/data.c +6 -4
@@ -491,14 +491,15 @@ void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr)int reserve_new_blocks (struct dnode_of_data *dn,blkcnt_t count) {struct f2fs_sb_info *sbi =F2FS_I_SB (dn->inode); +int err;if (!count)return 0 ;if (unlikely (is_inode_flag_set (dn->inode,FI_NO_ALLOC )))return -EPERM ; -if (unlikely (!inc_valid_block_count (sbi, dn->inode, &count))) -return -ENOSPC ; +if (unlikely ((err =inc_valid_block_count (sbi, dn->inode, &count)))) +return err;trace_f2fs_reserve_new_blocks (dn->inode, dn->nid, dn->ofs_in_node, count);
@@ -749,6 +750,7 @@ static int __allocate_data_block(struct dnode_of_data *dn)struct node_info ni;pgoff_t fofs;blkcnt_t count =1 ; +int err;if (unlikely (is_inode_flag_set (dn->inode,FI_NO_ALLOC )))return -EPERM ;
@@ -757,8 +759,8 @@ static int __allocate_data_block(struct dnode_of_data *dn)if (dn->data_blkaddr ==NEW_ADDR ) goto alloc; -if (unlikely (!inc_valid_block_count (sbi, dn->inode, &count))) -return -ENOSPC ; +if (unlikely ((err =inc_valid_block_count (sbi, dn->inode, &count)))) +return err; alloc:get_node_info (sbi, dn->nid, &ni);
fs/f2fs/f2fs.h +65 -23
189 lines not on this page · raw message
fs/f2fs/file.c +27 -7
@@ -442,11 +442,10 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)static int f2fs_file_open (struct inode *inode,struct file *filp) { -int ret =generic_file_open (inode, filp);struct dentry *dir; -if (!ret &&f2fs_encrypted_inode (inode)) { - ret =fscrypt_get_encryption_info (inode); +if (f2fs_encrypted_inode (inode)) { +int ret =fscrypt_get_encryption_info (inode);if (ret)return -EACCES ;if (!fscrypt_has_encryption_key (inode))
@@ -459,7 +458,7 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)return -EPERM ; }dput (dir); -return ret; +return dquot_file_open (inode, filp); }int truncate_data_blocks_range (struct dnode_of_data *dn,int count)
@@ -710,6 +709,20 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)if (err)return err; +if (is_quota_modification (inode, attr)) { + err =dquot_initialize (inode); +if (err) +return err; + } +if ((attr->ia_valid &ATTR_UID && + !uid_eq (attr->ia_uid, inode->i_uid)) || + (attr->ia_valid &ATTR_GID && + !gid_eq (attr->ia_gid, inode->i_gid))) { + err =dquot_transfer (inode, attr); +if (err) +return err; + } +if (attr->ia_valid &ATTR_SIZE ) {if (f2fs_encrypted_inode (inode)) { err =fscrypt_get_encryption_info (inode);
@@ -996,9 +1009,9 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,if (do_replace[i]) {f2fs_i_blocks_write (src_inode, -1 , false); +1 , false, false);f2fs_i_blocks_write (dst_inode, -1 , true); +1 , true, false);f2fs_replace_block (sbi, &dn, dn.data_blkaddr, blkaddr[i], ni.version, true, false);
@@ -1523,6 +1536,13 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)inode_lock (inode); +/* Is it quota file? Do not allow user to mess with it */ +if (IS_NOQUOTA (inode)) { +inode_unlock (inode); + ret = -EPERM ; + goto unlock_out; + } + flags =f2fs_mask_flags (inode->i_mode, flags); oldflags = fi->i_flags;
@@ -1542,7 +1562,7 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg) inode->i_ctime =current_time (inode);f2fs_set_inode_flags (inode);f2fs_mark_inode_dirty_sync (inode, false); - +unlock_out:inode_unlock (inode); out:mnt_drop_write_file (filp);
fs/f2fs/inode.c +5 -0
@@ -373,6 +373,8 @@ void f2fs_evict_inode(struct inode *inode)if (inode->i_nlink ||is_bad_inode (inode)) goto no_delete; +dquot_initialize (inode); +remove_ino_entry (sbi, inode->i_ino,APPEND_INO );remove_ino_entry (sbi, inode->i_ino,UPDATE_INO );
@@ -405,8 +407,11 @@ void f2fs_evict_inode(struct inode *inode)if (err)update_inode_page (inode); +dquot_free_inode (inode);sb_end_intwrite (inode->i_sb); no_delete: +dquot_drop (inode); +stat_dec_inline_xattr (inode);stat_dec_inline_dir (inode);stat_dec_inline_inode (inode);
fs/f2fs/namei.c +65 -1
147 lines not on this page · raw message
fs/f2fs/node.c +4 -5
@@ -1040,10 +1040,9 @@ struct page *new_node_page(struct dnode_of_data *dn,if (!page)return ERR_PTR (-ENOMEM ); -if (unlikely (!inc_valid_node_count (sbi, dn->inode, !ofs))) { - err = -ENOSPC ; +if (unlikely ((err =inc_valid_node_count (sbi, dn->inode, !ofs)))) goto fail; - } +#ifdef CONFIG_F2FS_CHECK_FS get_node_info (sbi, dn->nid, &new_ni);f2fs_bug_on (sbi, new_ni.blk_addr !=NULL_ADDR );
@@ -2210,7 +2209,7 @@ int recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)/* 2: update xattr nid in inode */ remove_free_nid (sbi, new_xnid);f2fs_i_xnid_write (inode, new_xnid); -if (unlikely (!inc_valid_node_count (sbi, inode, false))) +if (unlikely (inc_valid_node_count (sbi, inode, false)))f2fs_bug_on (sbi,1 );update_inode_page (inode);
@@ -2268,7 +2267,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) new_ni = old_ni; new_ni.ino = ino; -if (unlikely (!inc_valid_node_count (sbi,NULL , true))) +if (unlikely (inc_valid_node_count (sbi,NULL , true)))WARN_ON (1 );set_node_addr (sbi, &new_ni,NEW_ADDR , false);inc_valid_inode_count (sbi);
fs/f2fs/super.c +280 -0
369 lines not on this page · raw message
Signature · 1 line
2.13.0.90.g1eb437020