• Jan Kara's avatar
    jbd2: Fix return value of jbd2_journal_start_commit() · c88ccea3
    Jan Kara authored
    The function jbd2_journal_start_commit() returns 1 if either a
    transaction is committing or the function has queued a transaction
    commit. But it returns 0 if we raced with somebody queueing the
    transaction commit as well. This resulted in ext4_sync_fs() not
    functioning correctly (description from Arthur Jones): 
    
       In the case of a data=ordered umount with pending long symlinks
       which are delayed due to a long list of other I/O on the backing
       block device, this causes the buffer associated with the long
       symlinks to not be moved to the inode dirty list in the second
       phase of fsync_super.  Then, before they can be dirtied again,
       kjournald exits, seeing the UMOUNT flag and the dirty pages are
       never written to the backing block device, causing long symlink
       corruption and exposing new or previously freed block data to
       userspace.
    
    This can be reproduced with a script created by Eric Sandeen
    <sandeen@redhat.com>:
    
            #!/bin/bash
    
            umount /mnt/test2
            mount /dev/sdb4 /mnt/test2
            rm -f /mnt/test2/*
            dd if=/dev/zero of=/mnt/test2/bigfile bs=1M count=512
            touch /mnt/test2/thisisveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfilename
            ln -s /mnt/test2/thisisveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfilename
            /mnt/test2/link
            umount /mnt/test2
            mount /dev/sdb4 /mnt/test2
            ls /mnt/test2/
    
    This patch fixes jbd2_journal_start_commit() to always return 1 when
    there's a transaction committing or queued for commit.
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
    CC: Eric Sandeen <sandeen@redhat.com>
    CC: linux-ext4@vger.kernel.org
    c88ccea3
journal.c 64.7 KB