linux-f2fs-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
* [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly
@ 2024-05-06 10:41 Chao Yu
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 2/5] f2fs: compress: fix error path of inc_valid_block_count() Chao Yu
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Chao Yu @ 2024-05-06 10:41 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-kernel, linux-f2fs-devel

Previously, we account reserved blocks and compressed blocks into
@compr_blocks, then, f2fs_i_compr_blocks_update(,compr_blocks) will
update i_compr_blocks incorrectly, fix it.

Meanwhile, for the case all blocks in cluster were reserved, fix to
update dn->ofs_in_node correctly.

Fixes: eb8fbaa53374 ("f2fs: compress: fix to check unreleased compressed cluster")
Signed-off-by: Chao Yu <chao@kernel.org>
---
 fs/f2fs/file.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 1761ad125f97..6c84485687d3 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3641,7 +3641,8 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
 
 	while (count) {
 		int compr_blocks = 0;
-		blkcnt_t reserved;
+		blkcnt_t reserved = 0;
+		blkcnt_t to_reserved;
 		int ret;
 
 		for (i = 0; i < cluster_size; i++) {
@@ -3661,20 +3662,26 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
 			 * fails in release_compress_blocks(), so NEW_ADDR
 			 * is a possible case.
 			 */
-			if (blkaddr == NEW_ADDR ||
-				__is_valid_data_blkaddr(blkaddr)) {
+			if (blkaddr == NEW_ADDR) {
+				reserved++;
+				continue;
+			}
+			if (__is_valid_data_blkaddr(blkaddr)) {
 				compr_blocks++;
 				continue;
 			}
 		}
 
-		reserved = cluster_size - compr_blocks;
+		to_reserved = cluster_size - compr_blocks - reserved;
 
 		/* for the case all blocks in cluster were reserved */
-		if (reserved == 1)
+		if (to_reserved == 1) {
+			dn->ofs_in_node += cluster_size;
 			goto next;
+		}
 
-		ret = inc_valid_block_count(sbi, dn->inode, &reserved, false);
+		ret = inc_valid_block_count(sbi, dn->inode,
+						&to_reserved, false);
 		if (unlikely(ret))
 			return ret;
 
@@ -3685,7 +3692,7 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
 
 		f2fs_i_compr_blocks_update(dn->inode, compr_blocks, true);
 
-		*reserved_blocks += reserved;
+		*reserved_blocks += to_reserved;
 next:
 		count -= cluster_size;
 	}
-- 
2.40.1



_______________________________________________
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] 6+ messages in thread

* [f2fs-dev] [PATCH 2/5] f2fs: compress: fix error path of inc_valid_block_count()
  2024-05-06 10:41 [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly Chao Yu
@ 2024-05-06 10:41 ` Chao Yu
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 3/5] f2fs: compress: fix typo in f2fs_reserve_compress_blocks() Chao Yu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Chao Yu @ 2024-05-06 10:41 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-kernel, linux-f2fs-devel

If inc_valid_block_count() can not allocate all requested blocks,
it needs to release block count in .total_valid_block_count and
resevation blocks in inode.

Fixes: 54607494875e ("f2fs: compress: fix to avoid inconsistence bewteen i_blocks and dnode")
Signed-off-by: Chao Yu <chao@kernel.org>
---
 fs/f2fs/f2fs.h | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c876813b5532..95a40d4f778f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2309,7 +2309,7 @@ static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool);
 static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
 				 struct inode *inode, blkcnt_t *count, bool partial)
 {
-	blkcnt_t diff = 0, release = 0;
+	long long diff = 0, release = 0;
 	block_t avail_user_block_count;
 	int ret;
 
@@ -2329,26 +2329,27 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
 	percpu_counter_add(&sbi->alloc_valid_block_count, (*count));
 
 	spin_lock(&sbi->stat_lock);
-	sbi->total_valid_block_count += (block_t)(*count);
-	avail_user_block_count = get_available_block_count(sbi, inode, true);
 
-	if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
+	avail_user_block_count = get_available_block_count(sbi, inode, true);
+	diff = (long long)sbi->total_valid_block_count + *count -
+						avail_user_block_count;
+	if (unlikely(diff > 0)) {
 		if (!partial) {
 			spin_unlock(&sbi->stat_lock);
+			release = *count;
 			goto enospc;
 		}
-
-		diff = sbi->total_valid_block_count - avail_user_block_count;
 		if (diff > *count)
 			diff = *count;
 		*count -= diff;
 		release = diff;
-		sbi->total_valid_block_count -= diff;
 		if (!*count) {
 			spin_unlock(&sbi->stat_lock);
 			goto enospc;
 		}
 	}
+	sbi->total_valid_block_count += (block_t)(*count);
+
 	spin_unlock(&sbi->stat_lock);
 
 	if (unlikely(release)) {
-- 
2.40.1



_______________________________________________
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] 6+ messages in thread

* [f2fs-dev] [PATCH 3/5] f2fs: compress: fix typo in f2fs_reserve_compress_blocks()
  2024-05-06 10:41 [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly Chao Yu
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 2/5] f2fs: compress: fix error path of inc_valid_block_count() Chao Yu
@ 2024-05-06 10:41 ` Chao Yu
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 4/5] f2fs: compress: fix to cover {reserve, release}_compress_blocks() w/ cp_rwsem lock Chao Yu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Chao Yu @ 2024-05-06 10:41 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-kernel, linux-f2fs-devel

s/released/reserved.

Signed-off-by: Chao Yu <chao@kernel.org>
---
 fs/f2fs/file.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 6c84485687d3..e77e958a9f92 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3785,7 +3785,7 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
 	} 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 "
+		f2fs_warn(sbi, "%s: partial blocks were reserved i_ino=%lx "
 			"iblocks=%llu, reserved=%u, compr_blocks=%u, "
 			"run fsck to fix.",
 			__func__, inode->i_ino, inode->i_blocks,
-- 
2.40.1



_______________________________________________
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] 6+ messages in thread

* [f2fs-dev] [PATCH 4/5] f2fs: compress: fix to cover {reserve, release}_compress_blocks() w/ cp_rwsem lock
  2024-05-06 10:41 [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly Chao Yu
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 2/5] f2fs: compress: fix error path of inc_valid_block_count() Chao Yu
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 3/5] f2fs: compress: fix typo in f2fs_reserve_compress_blocks() Chao Yu
@ 2024-05-06 10:41 ` Chao Yu
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 5/5] f2fs: compress: don't allow unaligned truncation on released compress inode Chao Yu
  2024-05-11  0:50 ` [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly patchwork-bot+f2fs
  4 siblings, 0 replies; 6+ messages in thread
From: Chao Yu @ 2024-05-06 10:41 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-kernel, linux-f2fs-devel

It needs to cover {reserve,release}_compress_blocks() w/ cp_rwsem lock
to avoid racing with checkpoint, otherwise, filesystem metadata including
blkaddr in dnode, inode fields and .total_valid_block_count may be
corrupted after SPO case.

Fixes: ef8d563f184e ("f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS")
Fixes: c75488fb4d82 ("f2fs: introduce F2FS_IOC_RESERVE_COMPRESS_BLOCKS")
Signed-off-by: Chao Yu <chao@kernel.org>
---
 fs/f2fs/file.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index e77e958a9f92..3f0db351e976 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3570,9 +3570,12 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
 		struct dnode_of_data dn;
 		pgoff_t end_offset, count;
 
+		f2fs_lock_op(sbi);
+
 		set_new_dnode(&dn, inode, NULL, NULL, 0);
 		ret = f2fs_get_dnode_of_data(&dn, page_idx, LOOKUP_NODE);
 		if (ret) {
+			f2fs_unlock_op(sbi);
 			if (ret == -ENOENT) {
 				page_idx = f2fs_get_next_page_offset(&dn,
 								page_idx);
@@ -3590,6 +3593,8 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
 
 		f2fs_put_dnode(&dn);
 
+		f2fs_unlock_op(sbi);
+
 		if (ret < 0)
 			break;
 
@@ -3742,9 +3747,12 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
 		struct dnode_of_data dn;
 		pgoff_t end_offset, count;
 
+		f2fs_lock_op(sbi);
+
 		set_new_dnode(&dn, inode, NULL, NULL, 0);
 		ret = f2fs_get_dnode_of_data(&dn, page_idx, LOOKUP_NODE);
 		if (ret) {
+			f2fs_unlock_op(sbi);
 			if (ret == -ENOENT) {
 				page_idx = f2fs_get_next_page_offset(&dn,
 								page_idx);
@@ -3762,6 +3770,8 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
 
 		f2fs_put_dnode(&dn);
 
+		f2fs_unlock_op(sbi);
+
 		if (ret < 0)
 			break;
 
-- 
2.40.1



_______________________________________________
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] 6+ messages in thread

* [f2fs-dev] [PATCH 5/5] f2fs: compress: don't allow unaligned truncation on released compress inode
  2024-05-06 10:41 [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly Chao Yu
                   ` (2 preceding siblings ...)
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 4/5] f2fs: compress: fix to cover {reserve, release}_compress_blocks() w/ cp_rwsem lock Chao Yu
@ 2024-05-06 10:41 ` Chao Yu
  2024-05-11  0:50 ` [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly patchwork-bot+f2fs
  4 siblings, 0 replies; 6+ messages in thread
From: Chao Yu @ 2024-05-06 10:41 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-kernel, linux-f2fs-devel

f2fs image may be corrupted after below testcase:
- mkfs.f2fs -O extra_attr,compression -f /dev/vdb
- mount /dev/vdb /mnt/f2fs
- touch /mnt/f2fs/file
- f2fs_io setflags compression /mnt/f2fs/file
- dd if=/dev/zero of=/mnt/f2fs/file bs=4k count=4
- f2fs_io release_cblocks /mnt/f2fs/file
- truncate -s 8192 /mnt/f2fs/file
- umount /mnt/f2fs
- fsck.f2fs /dev/vdb

[ASSERT] (fsck_chk_inode_blk:1256)  --> ino: 0x5 has i_blocks: 0x00000002, but has 0x3 blocks
[FSCK] valid_block_count matching with CP             [Fail] [0x4, 0x5]
[FSCK] other corrupted bugs                           [Fail]

The reason is: partial truncation assume compressed inode has reserved
blocks, after partial truncation, valid block count may change w/
.i_blocks and .total_valid_block_count update, result in corruption.

This patch only allow cluster size aligned truncation on released
compress inode for fixing.

Fixes: c61404153eb6 ("f2fs: introduce FI_COMPRESS_RELEASED instead of using IMMUTABLE bit")
Signed-off-by: Chao Yu <chao@kernel.org>
---
 fs/f2fs/file.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 3f0db351e976..ac9d6380e433 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -952,9 +952,14 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
 				  ATTR_GID | ATTR_TIMES_SET))))
 		return -EPERM;
 
-	if ((attr->ia_valid & ATTR_SIZE) &&
-		!f2fs_is_compress_backend_ready(inode))
-		return -EOPNOTSUPP;
+	if ((attr->ia_valid & ATTR_SIZE)) {
+		if (!f2fs_is_compress_backend_ready(inode))
+			return -EOPNOTSUPP;
+		if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) &&
+			(attr->ia_size %
+			F2FS_BLK_TO_BYTES(F2FS_I(inode)->i_cluster_size)))
+			return -EINVAL;
+	}
 
 	err = setattr_prepare(idmap, dentry, attr);
 	if (err)
-- 
2.40.1



_______________________________________________
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] 6+ messages in thread

* Re: [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly
  2024-05-06 10:41 [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly Chao Yu
                   ` (3 preceding siblings ...)
  2024-05-06 10:41 ` [f2fs-dev] [PATCH 5/5] f2fs: compress: don't allow unaligned truncation on released compress inode Chao Yu
@ 2024-05-11  0:50 ` patchwork-bot+f2fs
  4 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+f2fs @ 2024-05-11  0:50 UTC (permalink / raw)
  To: Chao Yu; +Cc: jaegeuk, linux-kernel, linux-f2fs-devel

Hello:

This series was applied to jaegeuk/f2fs.git (dev)
by Jaegeuk Kim <jaegeuk@kernel.org>:

On Mon,  6 May 2024 18:41:36 +0800 you wrote:
> Previously, we account reserved blocks and compressed blocks into
> @compr_blocks, then, f2fs_i_compr_blocks_update(,compr_blocks) will
> update i_compr_blocks incorrectly, fix it.
> 
> Meanwhile, for the case all blocks in cluster were reserved, fix to
> update dn->ofs_in_node correctly.
> 
> [...]

Here is the summary with links:
  - [f2fs-dev,1/5] f2fs: compress: fix to update i_compr_blocks correctly
    https://git.kernel.org/jaegeuk/f2fs/c/186e7d71534d
  - [f2fs-dev,2/5] f2fs: compress: fix error path of inc_valid_block_count()
    https://git.kernel.org/jaegeuk/f2fs/c/043c832371cd
  - [f2fs-dev,3/5] f2fs: compress: fix typo in f2fs_reserve_compress_blocks()
    https://git.kernel.org/jaegeuk/f2fs/c/a3a0bc6c2239
  - [f2fs-dev,4/5] f2fs: compress: fix to cover {reserve, release}_compress_blocks() w/ cp_rwsem lock
    https://git.kernel.org/jaegeuk/f2fs/c/0a4ed2d97cb6
  - [f2fs-dev,5/5] f2fs: compress: don't allow unaligned truncation on released compress inode
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




_______________________________________________
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] 6+ messages in thread

end of thread, other threads:[~2024-05-11  0:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-06 10:41 [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly Chao Yu
2024-05-06 10:41 ` [f2fs-dev] [PATCH 2/5] f2fs: compress: fix error path of inc_valid_block_count() Chao Yu
2024-05-06 10:41 ` [f2fs-dev] [PATCH 3/5] f2fs: compress: fix typo in f2fs_reserve_compress_blocks() Chao Yu
2024-05-06 10:41 ` [f2fs-dev] [PATCH 4/5] f2fs: compress: fix to cover {reserve, release}_compress_blocks() w/ cp_rwsem lock Chao Yu
2024-05-06 10:41 ` [f2fs-dev] [PATCH 5/5] f2fs: compress: don't allow unaligned truncation on released compress inode Chao Yu
2024-05-11  0:50 ` [f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly patchwork-bot+f2fs

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).