[Devel] [RH7 PATCH] ext4: move ext4_truncate_data_csum out of transaction

Dmitry Monakhov dmonakhov at openvz.org
Mon Jul 20 09:00:39 PDT 2015


ext4_truncate_data_csum implicitly require journal transatcion so it can not be
called inside opened transaction.

BAD_CHAIN-#1:
 ->generic_file_buffered_write_iter
   ->ext4_da_write_begin
     ->ext4_journal_start( ,,1) : reserve 1 journal block
       ->ext4_write_end
     ->ext4_update_data_csum
       ->ext4_truncate_data_csum
         ->ext4_xattr_set
           ->ext4_journal_start(,,20): require 20 blocks,
                       but since journal already started
                       it use existing handle
            ->jbd2_journal_dirty_metadata
               J_ASSERT_JH(jh, handle->h_buffer_credits > 0) -> ASSERT
BAD_CHAIN-#2
ext4_evict_inode
 ->ext4_journal_start_sb
 ->ext4_truncate
   ->ext4_truncate_data_csum
     ->ext4_close_pfcache
       ->close_mapping_peer
         ->touch_atime
           ->update_time
             ->ext4_dirty_inode
               ->ext4_journal_start_sb -> start journal on another FS ->BUGON

Signed-off-by: Dmitry Monakhov <dmonakhov at openvz.org>
---
 fs/ext4/inode.c   |    2 ++
 fs/ext4/pfcache.c |    3 +++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 2b05910..30ae6b4 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -237,6 +237,8 @@ void ext4_evict_inode(struct inode *inode)
 	 * protection against it
 	 */
 	sb_start_intwrite(inode->i_sb);
+	if (inode->i_blocks && ext4_test_inode_state(inode, EXT4_STATE_PFCACHE_CSUM))
+		ext4_truncate_data_csum(inode, inode->i_size);
 	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE,
 				    ext4_blocks_for_truncate(inode)+3);
 	if (IS_ERR(handle)) {
diff --git a/fs/ext4/pfcache.c b/fs/ext4/pfcache.c
index bf45504..902bc0d 100644
--- a/fs/ext4/pfcache.c
+++ b/fs/ext4/pfcache.c
@@ -446,6 +446,8 @@ static int ext4_save_data_csum(struct inode *inode, u8 *csum)
 {
 	int ret;
 
+	WARN_ON(journal_current_handle());
+
 	if (ext4_test_inode_state(inode, EXT4_STATE_PFCACHE_CSUM) &&
 	    EXT4_I(inode)->i_data_csum_end < 0 &&
 	    memcmp(EXT4_I(inode)->i_data_csum, csum, EXT4_DATA_CSUM_SIZE))
@@ -501,6 +503,7 @@ int ext4_truncate_data_csum(struct inode *inode, loff_t pos)
 		return 0;
 
 	if (EXT4_I(inode)->i_data_csum_end < 0) {
+		WARN_ON(journal_current_handle());
 		ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED,
 				EXT4_DATA_CSUM_NAME, NULL, 0, 0);
 		ext4_close_pfcache(inode);
-- 
1.7.1




More information about the Devel mailing list