• Zachary Hays's avatar
    mmc: block: handle complete_work on separate workqueue · dcf6e2e3
    Zachary Hays authored
    The kblockd workqueue is created with the WQ_MEM_RECLAIM flag set.
    This generates a rescuer thread for that queue that will trigger when
    the CPU is under heavy load and collect the uncompleted work.
    
    In the case of mmc, this creates the possibility of a deadlock when
    there are multiple partitions on the device as other blk-mq work is
    also run on the same queue. For example:
    
    - worker 0 claims the mmc host to work on partition 1
    - worker 1 attempts to claim the host for partition 2 but has to wait
      for worker 0 to finish
    - worker 0 schedules complete_work to release the host
    - rescuer thread is triggered after time-out and collects the dangling
      work
    - rescuer thread attempts to complete the work in order starting with
      claim host
    - the task to release host is now blocked by a task to claim it and
      will never be called
    
    The above results in multiple hung tasks that lead to failures to
    mount partitions.
    
    Handling complete_work on a separate workqueue avoids this by keeping
    the work completion tasks separate from the other blk-mq work. This
    allows the host to be released without getting blocked by other tasks
    attempting to claim the host.
    Signed-off-by: default avatarZachary Hays <zhays@lexmark.com>
    Fixes: 81196976 ("mmc: block: Add blk-mq support")
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
    dcf6e2e3
block.c 75.7 KB