Commit 0a4ed2d9 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: compress: fix to cover {reserve,release}_compress_blocks() w/ cp_rwsem lock



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: ef8d563f ("f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS")
Fixes: c75488fb ("f2fs: introduce F2FS_IOC_RESERVE_COMPRESS_BLOCKS")
Signed-off-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 043c8323
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -3593,9 +3593,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);
@@ -3613,6 +3616,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;

@@ -3765,9 +3770,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);
@@ -3785,6 +3793,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;