Skip to content
  • Kay Sievers's avatar
    loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other · 05eb0f25
    Kay Sievers authored
    
    
    LOOP_CLR_FD takes lo->lo_ctl_mutex and tries to remove the loop sysfs
    files. Sysfs calls show() and waits for lo->lo_ctl_mutex. LOOP_CLR_FD
    waits for show() to finish to remove the sysfs file.
    
      cat /sys/class/block/loop0/loop/backing_file
        mutex_lock_nested+0x176/0x350
        ? loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
        ? loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
        loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
        dev_attr_show+0x1b/0x60
        ? sysfs_read_file+0x86/0x1a0
        ? __get_free_pages+0x12/0x50
        sysfs_read_file+0xaf/0x1a0
    
      ioctl(LOOP_CLR_FD):
        wait_for_common+0x12c/0x180
        ? try_to_wake_up+0x2a0/0x2a0
        wait_for_completion+0x18/0x20
        sysfs_deactivate+0x178/0x180
        ? sysfs_addrm_finish+0x43/0x70
        ? sysfs_addrm_start+0x1d/0x20
        sysfs_addrm_finish+0x43/0x70
        sysfs_hash_and_remove+0x85/0xa0
        sysfs_remove_group+0x59/0x100
        loop_clr_fd+0x1dc/0x3f0 [loop]
        lo_ioctl+0x223/0x7a0 [loop]
    
    Instead of taking the lo_ctl_mutex from sysfs code, take the inner
    lo->lo_lock, to protect the access to the backing_file data.
    
    Thanks to Tejun for help debugging and finding a solution.
    
    Cc: Milan Broz <mbroz@redhat.com>
    Cc: Tejun Heo <tj@kernel.org>
    Signed-off-by: default avatarKay Sievers <kay.sievers@vrfy.org>
    Cc: stable@kernel.org
    Signed-off-by: default avatarJens Axboe <jaxboe@fusionio.com>
    05eb0f25