• Niklas Schnelle's avatar
    s390/ism: Fix and simplify add()/remove() callback handling · 76631ffa
    Niklas Schnelle authored
    Previously the clients_lock was protecting the clients array against
    concurrent addition/removal of clients but was also accessed from IRQ
    context. This meant that it had to be a spinlock and that the add() and
    remove() callbacks in which clients need to do allocation and take
    mutexes can't be called under the clients_lock. To work around this these
    callbacks were moved to workqueues. This not only introduced significant
    complexity but is also subtly broken in at least one way.
    
    In ism_dev_init() and ism_dev_exit() clients[i]->tgt_ism is used to
    communicate the added/removed ISM device to the work function. While
    write access to client[i]->tgt_ism is protected by the clients_lock and
    the code waits that there is no pending add/remove work before and after
    setting clients[i]->tgt_ism this is not enough. The problem is that the
    wait happens based on per ISM device counters. Thus a concurrent
    ism_dev_init()/ism_dev_exit() for a different ISM device may overwrite
    a clients[i]->tgt_ism between unlocking the clients_lock and the
    subsequent wait for the work to finnish.
    
    Thankfully with the clients_lock no longer held in IRQ context it can be
    turned into a mutex which can be held during the calls to add()/remove()
    completely removing the need for the workqueues and the associated
    broken housekeeping including the per ISM device counters and the
    clients[i]->tgt_ism.
    
    Fixes: 89e7d2ba ("net/ism: Add new API for client registration")
    Signed-off-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    76631ffa
ism_drv.c 18.8 KB