• Jan Kara's avatar
    ext4: fix deadlock with fs freezing and EA inodes · 46e294ef
    Jan Kara authored
    Xattr code using inodes with large xattr data can end up dropping last
    inode reference (and thus deleting the inode) from places like
    ext4_xattr_set_entry(). That function is called with transaction started
    and so ext4_evict_inode() can deadlock against fs freezing like:
    
    CPU1					CPU2
    
    removexattr()				freeze_super()
      vfs_removexattr()
        ext4_xattr_set()
          handle = ext4_journal_start()
          ...
          ext4_xattr_set_entry()
            iput(old_ea_inode)
              ext4_evict_inode(old_ea_inode)
    					  sb->s_writers.frozen = SB_FREEZE_FS;
    					  sb_wait_write(sb, SB_FREEZE_FS);
    					  ext4_freeze()
    					    jbd2_journal_lock_updates()
    					      -> blocks waiting for all
    					         handles to stop
                sb_start_intwrite()
    	      -> blocks as sb is already in SB_FREEZE_FS state
    
    Generally it is advisable to delete inodes from a separate transaction
    as it can consume quite some credits however in this case it would be
    quite clumsy and furthermore the credits for inode deletion are quite
    limited and already accounted for. So just tweak ext4_evict_inode() to
    avoid freeze protection if we have transaction already started and thus
    it is not really needed anyway.
    
    Cc: stable@vger.kernel.org
    Fixes: dec214d0 ("ext4: xattr inode deduplication")
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Reviewed-by: default avatarAndreas Dilger <adilger@dilger.ca>
    Link: https://lore.kernel.org/r/20201127110649.24730-1-jack@suse.czSigned-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
    46e294ef
inode.c 178 KB