• yangwenfang's avatar
    ocfs2: call ocfs2_journal_access_di() before ocfs2_journal_dirty() in ocfs2_write_end_nolock() · 7f27ec97
    yangwenfang authored
    1: After we call ocfs2_journal_access_di() in ocfs2_write_begin(),
       jbd2_journal_restart() may also be called, in this function transaction
       A's t_updates-- and obtains a new transaction B.  If
       jbd2_journal_commit_transaction() is happened to commit transaction A,
       when t_updates==0, it will continue to complete commit and unfile
       buffer.
    
       So when jbd2_journal_dirty_metadata(), the handle is pointed a new
       transaction B, and the buffer head's journal head is already freed,
       jh->b_transaction == NULL, jh->b_next_transaction == NULL, it returns
       EINVAL, So it triggers the BUG_ON(status).
    
    thread 1                                          jbd2
    ocfs2_write_begin                     jbd2_journal_commit_transaction
    ocfs2_write_begin_nolock
      ocfs2_start_trans
        jbd2__journal_start(t_updates+1,
                           transaction A)
        ocfs2_journal_access_di
        ocfs2_write_cluster_by_desc
          ocfs2_mark_extent_written
            ocfs2_change_extent_flag
              ocfs2_split_extent
                ocfs2_extend_rotate_transaction
                  jbd2_journal_restart
                  (t_updates-1,transaction B) t_updates==0
                                            __jbd2_journal_refile_buffer
                                            (jh->b_transaction = NULL)
    ocfs2_write_end
    ocfs2_write_end_nolock
        ocfs2_journal_dirty
            jbd2_journal_dirty_metadata(bug)
       ocfs2_commit_trans
    
    2.  In ext4, I found that: jbd2_journal_get_write_access() called by
       ext4_write_end.
    
    ext4_write_begin
        ext4_journal_start
            __ext4_journal_start_sb
                ext4_journal_check_start
                jbd2__journal_start
    
    ext4_write_end
        ext4_mark_inode_dirty
            ext4_reserve_inode_write
                ext4_journal_get_write_access
                    jbd2_journal_get_write_access
            ext4_mark_iloc_dirty
                ext4_do_update_inode
                    ext4_handle_dirty_metadata
                        jbd2_journal_dirty_metadata
    
    3. So I think we should put ocfs2_journal_access_di before
       ocfs2_journal_dirty in the ocfs2_write_end.  and it works well after my
       modification.
    Signed-off-by: default avatarvicky <vicky.yangwenfang@huawei.com>
    Reviewed-by: default avatarMark Fasheh <mfasheh@suse.de>
    Cc: Joel Becker <jlbec@evilplan.org>
    Cc: Zhangguanghui <zhang.guanghui@h3c.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    7f27ec97
aops.c 62.3 KB