linux-f2fs-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
* [f2fs-dev] [PATCH] f2fs: change i_compr_blocks of inode to atomic value
@ 2020-09-02  6:29 Daeho Jeong
  2020-09-03  1:08 ` Chao Yu
  0 siblings, 1 reply; 4+ messages in thread
From: Daeho Jeong @ 2020-09-02  6:29 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel, kernel-team; +Cc: Daeho Jeong

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.

Signed-off-by: Daeho Jeong <daehojeong@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;
+		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);
-- 
2.28.0.402.g5ffc5be6b7-goog



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [f2fs-dev] [PATCH] f2fs: change i_compr_blocks of inode to atomic value
  2020-09-02  6:29 [f2fs-dev] [PATCH] f2fs: change i_compr_blocks of inode to atomic value Daeho Jeong
@ 2020-09-03  1:08 ` Chao Yu
  2020-09-03  1:43   ` Daeho Jeong
  0 siblings, 1 reply; 4+ messages in thread
From: Chao Yu @ 2020-09-03  1:08 UTC (permalink / raw)
  To: Daeho Jeong, linux-kernel, linux-f2fs-devel, kernel-team; +Cc: Daeho Jeong

On 2020/9/2 14:29, 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.
> 
> Signed-off-by: Daeho Jeong <daehojeong@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);
> 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [f2fs-dev] [PATCH] f2fs: change i_compr_blocks of inode to atomic value
  2020-09-03  1:08 ` Chao Yu
@ 2020-09-03  1:43   ` Daeho Jeong
  2020-09-03  2:05     ` Chao Yu
  0 siblings, 1 reply; 4+ messages in thread
From: Daeho Jeong @ 2020-09-03  1:43 UTC (permalink / raw)
  To: Chao Yu; +Cc: Daeho Jeong, kernel-team, linux-kernel, linux-f2fs-devel

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 <yuchao0@huawei.com>님이 작성:
>
> On 2020/9/2 14:29, 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.
> >
> > Signed-off-by: Daeho Jeong <daehojeong@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);
> >


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [f2fs-dev] [PATCH] f2fs: change i_compr_blocks of inode to atomic value
  2020-09-03  1:43   ` Daeho Jeong
@ 2020-09-03  2:05     ` Chao Yu
  0 siblings, 0 replies; 4+ messages in thread
From: Chao Yu @ 2020-09-03  2:05 UTC (permalink / raw)
  To: Daeho Jeong; +Cc: Daeho Jeong, kernel-team, linux-kernel, linux-f2fs-devel

On 2020/9/3 9:43, Daeho Jeong wrote:
> 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.

Yup, I think atomic type is enough for both f2fs_inode_info.i_compr_blocks and
f2fs_sb_info.compr_blocks.

Thanks,

> 
> 2020년 9월 3일 (목) 오전 10:08, Chao Yu <yuchao0@huawei.com>님이 작성:
>>
>> On 2020/9/2 14:29, 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.
>>>
>>> Signed-off-by: Daeho Jeong <daehojeong@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);
>>>
> .
> 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-09-03  2:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-02  6:29 [f2fs-dev] [PATCH] f2fs: change i_compr_blocks of inode to atomic value Daeho Jeong
2020-09-03  1:08 ` Chao Yu
2020-09-03  1:43   ` Daeho Jeong
2020-09-03  2:05     ` Chao Yu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).