Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vhost: Use virtqueue mutex for swapping worker

__vhost_vq_attach_worker uses the vhost_dev mutex to serialize the
swapping of a virtqueue's worker. This was done for simplicity because
we are already holding that mutex.

In the next patches where the worker can be killed while in use, we need
finer grained locking because some drivers will hold the vhost_dev mutex
while flushing. However in the SIGKILL handler in the next patches, we
will need to be able to swap workers (set current one to NULL), kill
queued works and stop new flushes while flushes are in progress.

To prepare us, this has us use the virtqueue mutex for swapping workers
instead of the vhost_dev one.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Message-Id: <20240316004707.45557-7-michael.christie@oracle.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

authored by

Mike Christie and committed by
Michael S. Tsirkin
34cf9ba5 0352c961

+13 -7
+13 -7
drivers/vhost/vhost.c
··· 652 652 { 653 653 struct vhost_worker *old_worker; 654 654 655 - old_worker = rcu_dereference_check(vq->worker, 656 - lockdep_is_held(&vq->dev->mutex)); 657 - 658 655 mutex_lock(&worker->mutex); 659 - worker->attachment_cnt++; 660 - mutex_unlock(&worker->mutex); 661 - rcu_assign_pointer(vq->worker, worker); 656 + mutex_lock(&vq->mutex); 662 657 663 - if (!old_worker) 658 + old_worker = rcu_dereference_check(vq->worker, 659 + lockdep_is_held(&vq->mutex)); 660 + rcu_assign_pointer(vq->worker, worker); 661 + worker->attachment_cnt++; 662 + 663 + if (!old_worker) { 664 + mutex_unlock(&vq->mutex); 665 + mutex_unlock(&worker->mutex); 664 666 return; 667 + } 668 + mutex_unlock(&vq->mutex); 669 + mutex_unlock(&worker->mutex); 670 + 665 671 /* 666 672 * Take the worker mutex to make sure we see the work queued from 667 673 * device wide flushes which doesn't use RCU for execution.