• Petr Mladek's avatar
    IB/rdmavt: Avoid queuing work into a destroyed cq kthread worker · 6efaf10f
    Petr Mladek authored
    The memory barrier is not enough to protect queuing works into
    a destroyed cq kthread. Just imagine the following situation:
    
    CPU1				CPU2
    
    rvt_cq_enter()
      worker =  cq->rdi->worker;
    
    				rvt_cq_exit()
    				  rdi->worker = NULL;
    				  smp_wmb();
    				  kthread_flush_worker(worker);
    				  kthread_stop(worker->task);
    				  kfree(worker);
    
    				  // nothing queued yet =>
    				  // nothing flushed and
    				  // happily stopped and freed
    
      if (likely(worker)) {
         // true => read before CPU2 acted
         cq->notify = RVT_CQ_NONE;
         cq->triggered++;
         kthread_queue_work(worker, &cq->comptask);
    
      BANG: worker has been flushed/stopped/freed in the meantime.
    
    This patch solves this by protecting the critical sections by
    rdi->n_cqs_lock. It seems that this lock is not much contended
    and looks reasonable for this purpose.
    
    One catch is that rvt_cq_enter() might be called from IRQ context.
    Therefore we must always take the lock with IRQs disabled to avoid
    a possible deadlock.
    Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
    Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
    6efaf10f
cq.c 13.9 KB