Re: [f2fs-dev] [PATCH v3 1/2] f2fs: change i_compr_blocks of inode to atomic value

2020-09-08 Thread Chao Yu

On 2020-9-8 10:44, Daeho Jeong wrote:

From: Daeho Jeong 

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 


Reviewed-by: Chao Yu 

Thanks,


[PATCH v3 1/2] f2fs: change i_compr_blocks of inode to atomic value

2020-09-07 Thread Daeho Jeong
From: Daeho Jeong 

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 
---
Changes in v3:
 - Roll back to the original flow except changing atomic64 to atomic
Changes in v2:
 - Change atomic64 to atomic and remove unnecessary part

Signed-off-by: Daeho Jeong 
---
 fs/f2fs/f2fs.h  | 17 ++---
 fs/f2fs/file.c  | 22 --
 fs/f2fs/inode.c | 11 +++
 fs/f2fs/super.c |  1 +
 4 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index f60414805e05..c615e75c82fd 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 */
@@ -3930,17 +3930,19 @@ static inline void set_compress_context(struct inode 
*inode)
f2fs_mark_inode_dirty_sync(inode, true);
 }
 
-static inline u64 f2fs_disable_compressed_file(struct inode *inode)
+static inline u32 f2fs_disable_compressed_file(struct inode *inode)
 {
struct f2fs_inode_info *fi = F2FS_I(inode);
+   u32 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;
+   i_compr_blocks = atomic_read(>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 && !atomic_read(>i_compr_blocks))
return;
 
if (add) {
-   F2FS_I(inode)->i_compr_blocks += diff;
+   atomic_add(diff, >i_compr_blocks);
stat_add_compr_blocks(inode, diff);
} else {
-   F2FS_I(inode)->i_compr_blocks -= diff;
+   atomic_sub(diff, >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(_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(_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(_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(_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,