Patch "f2fs: fix to update user block counts in block_operations()" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    f2fs: fix to update user block counts in block_operations()

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     f2fs-fix-to-update-user-block-counts-in-block_operat.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 82c7530fea3dc6f4899b42f2e83b87e412baa5f6
Author: Chao Yu <chao@xxxxxxxxxx>
Date:   Tue Jun 25 10:32:39 2024 +0800

    f2fs: fix to update user block counts in block_operations()
    
    [ Upstream commit f06c0f82e38bbda7264d6ef3c90045ad2810e0f3 ]
    
    Commit 59c9081bc86e ("f2fs: allow write page cache when writting cp")
    allows write() to write data to page cache during checkpoint, so block
    count fields like .total_valid_block_count, .alloc_valid_block_count
    and .rf_node_block_count may encounter race condition as below:
    
    CP                              Thread A
    - write_checkpoint
     - block_operations
      - f2fs_down_write(&sbi->node_change)
      - __prepare_cp_block
      : ckpt->valid_block_count = .total_valid_block_count
      - f2fs_up_write(&sbi->node_change)
                                    - write
                                     - f2fs_preallocate_blocks
                                      - f2fs_map_blocks(,F2FS_GET_BLOCK_PRE_AIO)
                                       - f2fs_map_lock
                                        - f2fs_down_read(&sbi->node_change)
                                       - f2fs_reserve_new_blocks
                                        - inc_valid_block_count
                                        : percpu_counter_add(&sbi->alloc_valid_block_count, count)
                                        : sbi->total_valid_block_count += count
                                        - f2fs_up_read(&sbi->node_change)
     - do_checkpoint
     : sbi->last_valid_block_count = sbi->total_valid_block_count
     : percpu_counter_set(&sbi->alloc_valid_block_count, 0)
     : percpu_counter_set(&sbi->rf_node_block_count, 0)
                                    - fsync
                                     - need_do_checkpoint
                                      - f2fs_space_for_roll_forward
                                      : alloc_valid_block_count was reset to zero,
                                        so, it may missed last data during checkpoint
    
    Let's change to update .total_valid_block_count, .alloc_valid_block_count
    and .rf_node_block_count in block_operations(), then their access can be
    protected by .node_change and .cp_rwsem lock, so that it can avoid above
    race condition.
    
    Fixes: 59c9081bc86e ("f2fs: allow write page cache when writting cp")
    Cc: Yunlei He <heyunlei@xxxxxxxx>
    Signed-off-by: Chao Yu <chao@xxxxxxxxxx>
    Signed-off-by: Jaegeuk Kim <jaegeuk@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 13d8774706758..ad4073cde397b 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -1178,6 +1178,11 @@ static void __prepare_cp_block(struct f2fs_sb_info *sbi)
 	ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
 	ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
 	ckpt->next_free_nid = cpu_to_le32(last_nid);
+
+	/* update user_block_counts */
+	sbi->last_valid_block_count = sbi->total_valid_block_count;
+	percpu_counter_set(&sbi->alloc_valid_block_count, 0);
+	percpu_counter_set(&sbi->rf_node_block_count, 0);
 }
 
 static bool __need_flush_quota(struct f2fs_sb_info *sbi)
@@ -1569,11 +1574,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 		start_blk += NR_CURSEG_NODE_TYPE;
 	}
 
-	/* update user_block_counts */
-	sbi->last_valid_block_count = sbi->total_valid_block_count;
-	percpu_counter_set(&sbi->alloc_valid_block_count, 0);
-	percpu_counter_set(&sbi->rf_node_block_count, 0);
-
 	/* Here, we have one bio having CP pack except cp pack 2 page */
 	f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
 	/* Wait for all dirty meta pages to be submitted for IO */




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux