lkml.org 
[lkml]   [2020]   [Sep]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [f2fs-dev] [PATCH v2] f2fs: change i_compr_blocks of inode to atomic value
From
Date
On 2020/9/4 1:48, Jaegeuk Kim wrote:
> On 09/03, Daeho Jeong wrote:
>> From: Daeho Jeong <daehojeong@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. Plus, we don't need
>> a 64bit value for i_compr_blocks, so just we will use a atomic value,
>> not atomic64.
>>
>> Signed-off-by: Daeho Jeong <daehojeong@google.com>
>> ---
>> Changes in v2:
>> - Change atomic64 to atomic and remove unnecessary part
>> ---
>> fs/f2fs/f2fs.h | 18 ++++++++----------
>> fs/f2fs/file.c | 22 ++++++++++++----------
>> fs/f2fs/inode.c | 11 +++++++----
>> fs/f2fs/super.c | 1 +
>> 4 files changed, 28 insertions(+), 24 deletions(-)
>>
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index f60414805e05..f6b8ac10a55c 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 */
>> + atomic_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 */
>> @@ -3936,12 +3936,9 @@ static inline u64 f2fs_disable_compressed_file(struct inode *inode)
>>
>> 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;
>> - }
>> + if (S_ISREG(inode->i_mode) &&
>> + (get_dirty_pages(inode) || atomic_read(&fi->i_compr_blocks)))
>> + return 1;
>
> Please keep the original flow in this patch which says swithing to atomic.
> Instead, it'd be better to have another patch which cleans up
> f2fs_disable_compressed_file() having "bool" as a return value.

Agreed, maybe I mislead Daeho, let's keep the rule do one thing in one patch. :)

Thanks,

>
>>
>> fi->i_flags &= ~F2FS_COMPR_FL;
>> stat_dec_compr_inode(inode);
>> @@ -4057,16 +4054,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 && !atomic_read(&fi->i_compr_blocks))
>> return;
>>
>> if (add) {
>> - F2FS_I(inode)->i_compr_blocks += diff;
>> + atomic_add(diff, &fi->i_compr_blocks);
>> stat_add_compr_blocks(inode, diff);
>> } else {
>> - F2FS_I(inode)->i_compr_blocks -= diff;
>> + atomic_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..adc4acad488a 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 = !atomic_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 = atomic_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 (!atomic_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 &&
>> + atomic_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, "
>> + "iblocks=%llu, released=%u, compr_blocks=%u, "
>> "run fsck to fix.",
>> __func__, inode->i_ino, inode->i_blocks,
>> released_blocks,
>> - F2FS_I(inode)->i_compr_blocks);
>> + atomic_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 (atomic_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 &&
>> + atomic_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, "
>> + "iblocks=%llu, reserved=%u, compr_blocks=%u, "
>> "run fsck to fix.",
>> __func__, inode->i_ino, inode->i_blocks,
>> reserved_blocks,
>> - F2FS_I(inode)->i_compr_blocks);
>> + atomic_read(&F2FS_I(inode)->i_compr_blocks));
>> }
>>
>> return ret;
>> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
>> index 66969ae852b9..2ed935c13aed 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);
>> + atomic_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, atomic_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(atomic_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,
>> + atomic_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..813aa207824c 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);
>> + atomic_set(&fi->i_compr_blocks, 0);
>> init_rwsem(&fi->i_sem);
>> spin_lock_init(&fi->i_size_lock);
>> INIT_LIST_HEAD(&fi->dirty_list);
>> --
>> 2.28.0.526.ge36021eeef-goog
>>
>>
>>
>> _______________________________________________
>> Linux-f2fs-devel mailing list
>> Linux-f2fs-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
> .
>

\
 
 \ /
  Last update: 2020-09-04 03:07    [W:0.117 / U:0.056 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site