• Jan Kara's avatar
    jbd2: fix hung processes in jbd2_journal_lock_updates() · 9837d8e9
    Jan Kara authored
    Toshiyuki Okajima found out that when running
    
    for ((i=0; i < 100000; i++)); do
            if ((i%2 == 0)); then
                    chattr +j /mnt/file
            else
                    chattr -j /mnt/file
            fi
            echo "0" >> /mnt/file
    done
    
    process sometimes hangs indefinitely in jbd2_journal_lock_updates().
    
    Toshiyuki identified that the following race happens:
    
    jbd2_journal_lock_updates()            |jbd2_journal_stop()
    ---------------------------------------+---------------------------------------
     write_lock(&journal->j_state_lock)    |    .
     ++journal->j_barrier_count            |    .
     spin_lock(&tran->t_handle_lock)       |    .
     atomic_read(&tran->t_updates) //not 0 |
                                           | atomic_dec_and_test(&tran->t_updates)
                                           |    // t_updates = 0
                                           | wake_up(&journal->j_wait_updates)
     prepare_to_wait()                     |    // no process is woken up.
     spin_unlock(&tran->t_handle_lock)     |
     write_unlock(&journal->j_state_lock)  |
     schedule() // never return            |
    
    We fix the problem by first calling prepare_to_wait() and only after that
    checking t_updates in jbd2_journal_lock_updates().
    Reported-and-analyzed-by: default avatarToshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
    9837d8e9
transaction.c 68.1 KB