• Joonas Lahtinen's avatar
    drm/i915: Don't call synchronize_rcu_expedited under struct_mutex · c053b5a5
    Joonas Lahtinen authored
    Only call synchronize_rcu_expedited after unlocking struct_mutex to
    avoid deadlock because the workqueues depend on struct_mutex.
    
    >From original patch by Andrea:
    
    synchronize_rcu/synchronize_sched/synchronize_rcu_expedited() will
    hang until its own workqueues are run. The i915 gem workqueues will
    wait on the struct_mutex to be released. So we cannot wait for a
    quiescent state using those rcu primitives while holding the
    struct_mutex or it creates a circular lock dependency resulting in
    kernel hangs (which is reproducible but goes undetected by lockdep).
    
    kswapd0         D    0   700      2 0x00000000
    Call Trace:
    ? __schedule+0x1a5/0x660
    ? schedule+0x36/0x80
    ? _synchronize_rcu_expedited.constprop.65+0x2ef/0x300
    ? wake_up_bit+0x20/0x20
    ? rcu_stall_kick_kthreads.part.54+0xc0/0xc0
    ? rcu_exp_wait_wake+0x530/0x530
    ? i915_gem_shrink+0x34b/0x4b0
    ? i915_gem_shrinker_scan+0x7c/0x90
    ? i915_gem_shrinker_scan+0x7c/0x90
    ? shrink_slab.part.61.constprop.72+0x1c1/0x3a0
    ? shrink_zone+0x154/0x160
    ? kswapd+0x40a/0x720
    ? kthread+0xf4/0x130
    ? try_to_free_pages+0x450/0x450
    ? kthread_create_on_node+0x40/0x40
    ? ret_from_fork+0x23/0x30
    plasmashell     D    0  4657   4614 0x00000000
    Call Trace:
    ? __schedule+0x1a5/0x660
    ? schedule+0x36/0x80
    ? schedule_preempt_disabled+0xe/0x10
    ? __mutex_lock.isra.4+0x1c9/0x790
    ? i915_gem_close_object+0x26/0xc0
    ? i915_gem_close_object+0x26/0xc0
    ? drm_gem_object_release_handle+0x48/0x90
    ? drm_gem_handle_delete+0x50/0x80
    ? drm_ioctl+0x1fa/0x420
    ? drm_gem_handle_create+0x40/0x40
    ? pipe_write+0x391/0x410
    ? __vfs_write+0xc6/0x120
    ? do_vfs_ioctl+0x8b/0x5d0
    ? SyS_ioctl+0x3b/0x70
    ? entry_SYSCALL_64_fastpath+0x13/0x94
    kworker/0:0     D    0 29186      2 0x00000000
    Workqueue: events __i915_gem_free_work
    Call Trace:
    ? __schedule+0x1a5/0x660
    ? schedule+0x36/0x80
    ? schedule_preempt_disabled+0xe/0x10
    ? __mutex_lock.isra.4+0x1c9/0x790
    ? del_timer_sync+0x44/0x50
    ? update_curr+0x57/0x110
    ? __i915_gem_free_objects+0x31/0x300
    ? __i915_gem_free_objects+0x31/0x300
    ? __i915_gem_free_work+0x2d/0x40
    ? process_one_work+0x13a/0x3b0
    ? worker_thread+0x4a/0x460
    ? kthread+0xf4/0x130
    ? process_one_work+0x3b0/0x3b0
    ? kthread_create_on_node+0x40/0x40
    ? ret_from_fork+0x23/0x30
    
    Fixes: 3d3d18f0 ("drm/i915: Avoid rcu_barrier() from reclaim paths (shrinker)")
    Reported-by: default avatarAndrea Arcangeli <aarcange@redhat.com>
    Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
    Cc: Andrea Arcangeli <aarcange@redhat.com>
    Cc: Chris Wilson <chris@chris-wilson.co.uk>
    Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
    Cc: Jani Nikula <jani.nikula@intel.com>
    Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
    (cherry picked from commit 8f612d05)
    Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
    c053b5a5
i915_gem_shrinker.c 14.7 KB