And how about this atomic64 to just atomic? As you mentioned before, we don't need a 64bit value for i_compr_blocks of inode.
2020년 9월 3일 (목) 오전 10:08, Chao Yu <yuch...@huawei.com>님이 작성: > > On 2020/9/2 14:29, Daeho Jeong wrote: > > From: Daeho Jeong <daehoje...@google.com> > > > > writepages() can be concurrently invoked for the same file by different > > threads such as a thread fsyncing the file and a kworker kernel thread. > > So, changing i_compr_blocks without protection is racy and we need to > > protect it by changing it with atomic type value. > > > > Signed-off-by: Daeho Jeong <daehoje...@google.com> > > --- > > fs/f2fs/f2fs.h | 15 +++++++++------ > > fs/f2fs/file.c | 18 ++++++++++-------- > > fs/f2fs/inode.c | 11 +++++++---- > > fs/f2fs/super.c | 1 + > > 4 files changed, 27 insertions(+), 18 deletions(-) > > > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > > index f60414805e05..633957e14944 100644 > > --- a/fs/f2fs/f2fs.h > > +++ b/fs/f2fs/f2fs.h > > @@ -801,7 +801,7 @@ struct f2fs_inode_info { > > struct timespec64 i_disk_time[4];/* inode disk times */ > > > > /* for file compress */ > > - u64 i_compr_blocks; /* # of compressed blocks */ > > + atomic64_t i_compr_blocks; /* # of compressed blocks */ > > unsigned char i_compress_algorithm; /* algorithm type */ > > unsigned char i_log_cluster_size; /* log of cluster size */ > > unsigned int i_cluster_size; /* cluster size */ > > @@ -3933,14 +3933,16 @@ static inline void set_compress_context(struct > > inode *inode) > > static inline u64 f2fs_disable_compressed_file(struct inode *inode) > > { > > struct f2fs_inode_info *fi = F2FS_I(inode); > > + u64 i_compr_blocks; > > > > if (!f2fs_compressed_file(inode)) > > return 0; > > if (S_ISREG(inode->i_mode)) { > > if (get_dirty_pages(inode)) > > return 1; > > - if (fi->i_compr_blocks) > > - return fi->i_compr_blocks; > Caller doesn't care how many compr_blocks this inode has saved, so we can just > return 1 here. > > > + i_compr_blocks = atomic64_read(&fi->i_compr_blocks); > > + if (i_compr_blocks) > > + return i_compr_blocks; > > } > > > > fi->i_flags &= ~F2FS_COMPR_FL; > > @@ -4057,16 +4059,17 @@ static inline void > > f2fs_i_compr_blocks_update(struct inode *inode, > > u64 blocks, bool add) > > { > > int diff = F2FS_I(inode)->i_cluster_size - blocks; > > + struct f2fs_inode_info *fi = F2FS_I(inode); > > > > /* don't update i_compr_blocks if saved blocks were released */ > > - if (!add && !F2FS_I(inode)->i_compr_blocks) > > + if (!add && !atomic64_read(&fi->i_compr_blocks)) > > return; > > > > if (add) { > > - F2FS_I(inode)->i_compr_blocks += diff; > > + atomic64_add(diff, &fi->i_compr_blocks); > > stat_add_compr_blocks(inode, diff); > > } else { > > - F2FS_I(inode)->i_compr_blocks -= diff; > > + atomic64_sub(diff, &fi->i_compr_blocks); > > stat_sub_compr_blocks(inode, diff); > > } > > f2fs_mark_inode_dirty_sync(inode, true); > > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > > index cc7f5670390f..4e4e369b97e5 100644 > > --- a/fs/f2fs/file.c > > +++ b/fs/f2fs/file.c > > @@ -564,7 +564,7 @@ void f2fs_truncate_data_blocks_range(struct > > dnode_of_data *dn, int count) > > bool compressed_cluster = false; > > int cluster_index = 0, valid_blocks = 0; > > int cluster_size = F2FS_I(dn->inode)->i_cluster_size; > > - bool released = !F2FS_I(dn->inode)->i_compr_blocks; > > + bool released = !atomic64_read(&F2FS_I(dn->inode)->i_compr_blocks); > > > > if (IS_INODE(dn->node_page) && f2fs_has_extra_attr(dn->inode)) > > base = get_extra_isize(dn->inode); > > @@ -3436,7 +3436,7 @@ static int f2fs_get_compress_blocks(struct file > > *filp, unsigned long arg) > > if (!f2fs_compressed_file(inode)) > > return -EINVAL; > > > > - blocks = F2FS_I(inode)->i_compr_blocks; > > + blocks = atomic64_read(&F2FS_I(inode)->i_compr_blocks); > > return put_user(blocks, (u64 __user *)arg); > > } > > > > @@ -3535,7 +3535,7 @@ static int f2fs_release_compress_blocks(struct file > > *filp, unsigned long arg) > > if (ret) > > goto out; > > > > - if (!F2FS_I(inode)->i_compr_blocks) > > + if (!atomic64_read(&F2FS_I(inode)->i_compr_blocks)) > > goto out; > > > > F2FS_I(inode)->i_flags |= F2FS_IMMUTABLE_FL; > > @@ -3588,14 +3588,15 @@ static int f2fs_release_compress_blocks(struct file > > *filp, unsigned long arg) > > > > if (ret >= 0) { > > ret = put_user(released_blocks, (u64 __user *)arg); > > - } else if (released_blocks && F2FS_I(inode)->i_compr_blocks) { > > + } else if (released_blocks && > > + atomic64_read(&F2FS_I(inode)->i_compr_blocks)) { > > set_sbi_flag(sbi, SBI_NEED_FSCK); > > f2fs_warn(sbi, "%s: partial blocks were released i_ino=%lx " > > "iblocks=%llu, released=%u, compr_blocks=%llu, " > > "run fsck to fix.", > > __func__, inode->i_ino, inode->i_blocks, > > released_blocks, > > - F2FS_I(inode)->i_compr_blocks); > > + atomic64_read(&F2FS_I(inode)->i_compr_blocks)); > > } > > > > return ret; > > @@ -3683,7 +3684,7 @@ static int f2fs_reserve_compress_blocks(struct file > > *filp, unsigned long arg) > > if (ret) > > return ret; > > > > - if (F2FS_I(inode)->i_compr_blocks) > > + if (atomic64_read(&F2FS_I(inode)->i_compr_blocks)) > > goto out; > > > > f2fs_balance_fs(F2FS_I_SB(inode), true); > > @@ -3747,14 +3748,15 @@ static int f2fs_reserve_compress_blocks(struct file > > *filp, unsigned long arg) > > > > if (ret >= 0) { > > ret = put_user(reserved_blocks, (u64 __user *)arg); > > - } else if (reserved_blocks && F2FS_I(inode)->i_compr_blocks) { > > + } else if (reserved_blocks && > > + atomic64_read(&F2FS_I(inode)->i_compr_blocks)) { > > set_sbi_flag(sbi, SBI_NEED_FSCK); > > f2fs_warn(sbi, "%s: partial blocks were released i_ino=%lx " > > "iblocks=%llu, reserved=%u, compr_blocks=%llu, " > > "run fsck to fix.", > > __func__, inode->i_ino, inode->i_blocks, > > reserved_blocks, > > - F2FS_I(inode)->i_compr_blocks); > > + atomic64_read(&F2FS_I(inode)->i_compr_blocks)); > > } > > > > return ret; > > diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c > > index 66969ae852b9..e86857af9699 100644 > > --- a/fs/f2fs/inode.c > > +++ b/fs/f2fs/inode.c > > @@ -442,7 +442,8 @@ static int do_read_inode(struct inode *inode) > > (fi->i_flags & F2FS_COMPR_FL)) { > > if (F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, > > i_log_cluster_size)) { > > - fi->i_compr_blocks = le64_to_cpu(ri->i_compr_blocks); > > + atomic64_set(&fi->i_compr_blocks, > > + le64_to_cpu(ri->i_compr_blocks)); > > fi->i_compress_algorithm = ri->i_compress_algorithm; > > fi->i_log_cluster_size = ri->i_log_cluster_size; > > fi->i_cluster_size = 1 << fi->i_log_cluster_size; > > @@ -460,7 +461,7 @@ static int do_read_inode(struct inode *inode) > > stat_inc_inline_inode(inode); > > stat_inc_inline_dir(inode); > > stat_inc_compr_inode(inode); > > - stat_add_compr_blocks(inode, F2FS_I(inode)->i_compr_blocks); > > + stat_add_compr_blocks(inode, atomic64_read(&fi->i_compr_blocks)); > > > > return 0; > > } > > @@ -619,7 +620,8 @@ void f2fs_update_inode(struct inode *inode, struct page > > *node_page) > > F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize, > > i_log_cluster_size)) { > > ri->i_compr_blocks = > > - cpu_to_le64(F2FS_I(inode)->i_compr_blocks); > > + cpu_to_le64(atomic64_read( > > + &F2FS_I(inode)->i_compr_blocks)); > > ri->i_compress_algorithm = > > F2FS_I(inode)->i_compress_algorithm; > > ri->i_log_cluster_size = > > @@ -768,7 +770,8 @@ void f2fs_evict_inode(struct inode *inode) > > stat_dec_inline_dir(inode); > > stat_dec_inline_inode(inode); > > stat_dec_compr_inode(inode); > > - stat_sub_compr_blocks(inode, F2FS_I(inode)->i_compr_blocks); > > + stat_sub_compr_blocks(inode, > > + atomic64_read(&F2FS_I(inode)->i_compr_blocks)); > > > > if (likely(!f2fs_cp_error(sbi) && > > !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > > index 83bf9a02f83f..65613500e1ab 100644 > > --- a/fs/f2fs/super.c > > +++ b/fs/f2fs/super.c > > @@ -1011,6 +1011,7 @@ static struct inode *f2fs_alloc_inode(struct > > super_block *sb) > > > > /* Initialize f2fs-specific inode info */ > > atomic_set(&fi->dirty_pages, 0); > > + atomic64_set(&fi->i_compr_blocks, 0); > > init_rwsem(&fi->i_sem); > > spin_lock_init(&fi->i_size_lock); > > INIT_LIST_HEAD(&fi->dirty_list); > >