• T
    libata: implement cross-port EH exclusion · c0c362b6
    Tejun Heo 提交于
    In libata, the non-EH code paths should always take and release
    ap->lock explicitly when accessing hardware or shared data structures.
    However, once EH is active, it's assumed that the port is owned by EH
    and EH methods don't explicitly take ap->lock unless race from irq
    handler or other code paths are expected.  However, libata EH didn't
    guarantee exclusion among EHs for ports of the same host.  IOW,
    multiple EHs may execute in parallel on multiple ports of the same
    controller.
    
    In many cases, especially in SATA, the ports are completely
    independent of each other and this doesn't cause problems; however,
    there are cases where different ports share the same resource, which
    lead to obscure timing related bugs such as the one fixed by commit
    213373cf (ata_piix: fix locking around SIDPR access).
    
    This patch implements exclusion among EHs of the same host.  When EH
    begins, it acquires per-host EH ownership by calling ata_eh_acquire().
    When EH finishes, the ownership is released by calling
    ata_eh_release().  EH ownership is also released whenever the EH
    thread goes to sleep from ata_msleep() or explicitly and reacquired
    after waking up.
    
    This ensures that while EH is actively accessing the hardware, it has
    exclusive access to it while allowing EHs to interleave and progress
    in parallel as they hit waiting stages, which dominate the time spent
    in EH.  This achieves cross-port EH exclusion without pervasive and
    fragile changes while still allowing parallel EH for the most part.
    
    This was first reported by yuanding02@gmail.com more than three years
    ago in the following bugzilla.  :-)
    
      https://bugzilla.kernel.org/show_bug.cgi?id=8223Signed-off-by: NTejun Heo <tj@kernel.org>
    Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
    Reported-by: yuanding02@gmail.com
    Signed-off-by: NJeff Garzik <jgarzik@redhat.com>
    c0c362b6
libata.h 56.3 KB