Skip to content
Snippets Groups Projects
Forked from drm / msm
Source project has a limited visibility.
  • Igor Pylypiv's avatar
    67d6212a
    Revert "module, async: async_synchronize_full() on module init iff async is used" · 67d6212a
    Igor Pylypiv authored
    
    This reverts commit 774a1221.
    
    We need to finish all async code before the module init sequence is
    done.  In the reverted commit the PF_USED_ASYNC flag was added to mark a
    thread that called async_schedule().  Then the PF_USED_ASYNC flag was
    used to determine whether or not async_synchronize_full() needs to be
    invoked.  This works when modprobe thread is calling async_schedule(),
    but it does not work if module dispatches init code to a worker thread
    which then calls async_schedule().
    
    For example, PCI driver probing is invoked from a worker thread based on
    a node where device is attached:
    
    	if (cpu < nr_cpu_ids)
    		error = work_on_cpu(cpu, local_pci_probe, &ddi);
    	else
    		error = local_pci_probe(&ddi);
    
    We end up in a situation where a worker thread gets the PF_USED_ASYNC
    flag set instead of the modprobe thread.  As a result,
    async_synchronize_full() is not invoked and modprobe completes without
    waiting for the async code to finish.
    
    The issue was discovered while loading the pm80xx driver:
    (scsi_mod.scan=async)
    
    modprobe pm80xx                      worker
    ...
      do_init_module()
      ...
        pci_call_probe()
          work_on_cpu(local_pci_probe)
                                         local_pci_probe()
                                           pm8001_pci_probe()
                                             scsi_scan_host()
                                               async_schedule()
                                               worker->flags |= PF_USED_ASYNC;
                                         ...
          < return from worker >
      ...
      if (current->flags & PF_USED_ASYNC) <--- false
      	async_synchronize_full();
    
    Commit 21c3c5d2 ("block: don't request module during elevator init")
    fixed the deadlock issue which the reverted commit 774a1221
    ("module, async: async_synchronize_full() on module init iff async is
    used") tried to fix.
    
    Since commit 0fdff3ec ("async, kmod: warn on synchronous
    request_module() from async workers") synchronous module loading from
    async is not allowed.
    
    Given that the original deadlock issue is fixed and it is no longer
    allowed to call synchronous request_module() from async we can remove
    PF_USED_ASYNC flag to make module init consistently invoke
    async_synchronize_full() unless async module probe is requested.
    
    Signed-off-by: default avatarIgor Pylypiv <ipylypiv@google.com>
    Reviewed-by: default avatarChangyuan Lyu <changyuanl@google.com>
    Reviewed-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
    Acked-by: default avatarTejun Heo <tj@kernel.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    67d6212a
    History
    Revert "module, async: async_synchronize_full() on module init iff async is used"
    Igor Pylypiv authored
    
    This reverts commit 774a1221.
    
    We need to finish all async code before the module init sequence is
    done.  In the reverted commit the PF_USED_ASYNC flag was added to mark a
    thread that called async_schedule().  Then the PF_USED_ASYNC flag was
    used to determine whether or not async_synchronize_full() needs to be
    invoked.  This works when modprobe thread is calling async_schedule(),
    but it does not work if module dispatches init code to a worker thread
    which then calls async_schedule().
    
    For example, PCI driver probing is invoked from a worker thread based on
    a node where device is attached:
    
    	if (cpu < nr_cpu_ids)
    		error = work_on_cpu(cpu, local_pci_probe, &ddi);
    	else
    		error = local_pci_probe(&ddi);
    
    We end up in a situation where a worker thread gets the PF_USED_ASYNC
    flag set instead of the modprobe thread.  As a result,
    async_synchronize_full() is not invoked and modprobe completes without
    waiting for the async code to finish.
    
    The issue was discovered while loading the pm80xx driver:
    (scsi_mod.scan=async)
    
    modprobe pm80xx                      worker
    ...
      do_init_module()
      ...
        pci_call_probe()
          work_on_cpu(local_pci_probe)
                                         local_pci_probe()
                                           pm8001_pci_probe()
                                             scsi_scan_host()
                                               async_schedule()
                                               worker->flags |= PF_USED_ASYNC;
                                         ...
          < return from worker >
      ...
      if (current->flags & PF_USED_ASYNC) <--- false
      	async_synchronize_full();
    
    Commit 21c3c5d2 ("block: don't request module during elevator init")
    fixed the deadlock issue which the reverted commit 774a1221
    ("module, async: async_synchronize_full() on module init iff async is
    used") tried to fix.
    
    Since commit 0fdff3ec ("async, kmod: warn on synchronous
    request_module() from async workers") synchronous module loading from
    async is not allowed.
    
    Given that the original deadlock issue is fixed and it is no longer
    allowed to call synchronous request_module() from async we can remove
    PF_USED_ASYNC flag to make module init consistently invoke
    async_synchronize_full() unless async module probe is requested.
    
    Signed-off-by: default avatarIgor Pylypiv <ipylypiv@google.com>
    Reviewed-by: default avatarChangyuan Lyu <changyuanl@google.com>
    Reviewed-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
    Acked-by: default avatarTejun Heo <tj@kernel.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>