aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vhost
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vhost')
-rw-r--r--drivers/vhost/net.c17
-rw-r--r--drivers/vhost/vhost.c22
-rw-r--r--drivers/vhost/vhost.h10
3 files changed, 36 insertions, 13 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 72ab71fdf053..4b4da5b86ff9 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -127,7 +127,10 @@ static void handle_tx(struct vhost_net *net)
127 size_t len, total_len = 0; 127 size_t len, total_len = 0;
128 int err, wmem; 128 int err, wmem;
129 size_t hdr_size; 129 size_t hdr_size;
130 struct socket *sock = rcu_dereference(vq->private_data); 130 struct socket *sock;
131
132 sock = rcu_dereference_check(vq->private_data,
133 lockdep_is_held(&vq->mutex));
131 if (!sock) 134 if (!sock)
132 return; 135 return;
133 136
@@ -582,7 +585,10 @@ static void vhost_net_disable_vq(struct vhost_net *n,
582static void vhost_net_enable_vq(struct vhost_net *n, 585static void vhost_net_enable_vq(struct vhost_net *n,
583 struct vhost_virtqueue *vq) 586 struct vhost_virtqueue *vq)
584{ 587{
585 struct socket *sock = vq->private_data; 588 struct socket *sock;
589
590 sock = rcu_dereference_protected(vq->private_data,
591 lockdep_is_held(&vq->mutex));
586 if (!sock) 592 if (!sock)
587 return; 593 return;
588 if (vq == n->vqs + VHOST_NET_VQ_TX) { 594 if (vq == n->vqs + VHOST_NET_VQ_TX) {
@@ -598,7 +604,8 @@ static struct socket *vhost_net_stop_vq(struct vhost_net *n,
598 struct socket *sock; 604 struct socket *sock;
599 605
600 mutex_lock(&vq->mutex); 606 mutex_lock(&vq->mutex);
601 sock = vq->private_data; 607 sock = rcu_dereference_protected(vq->private_data,
608 lockdep_is_held(&vq->mutex));
602 vhost_net_disable_vq(n, vq); 609 vhost_net_disable_vq(n, vq);
603 rcu_assign_pointer(vq->private_data, NULL); 610 rcu_assign_pointer(vq->private_data, NULL);
604 mutex_unlock(&vq->mutex); 611 mutex_unlock(&vq->mutex);
@@ -736,7 +743,8 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
736 } 743 }
737 744
738 /* start polling new socket */ 745 /* start polling new socket */
739 oldsock = vq->private_data; 746 oldsock = rcu_dereference_protected(vq->private_data,
747 lockdep_is_held(&vq->mutex));
740 if (sock != oldsock) { 748 if (sock != oldsock) {
741 vhost_net_disable_vq(n, vq); 749 vhost_net_disable_vq(n, vq);
742 rcu_assign_pointer(vq->private_data, sock); 750 rcu_assign_pointer(vq->private_data, sock);
@@ -869,6 +877,7 @@ static const struct file_operations vhost_net_fops = {
869 .compat_ioctl = vhost_net_compat_ioctl, 877 .compat_ioctl = vhost_net_compat_ioctl,
870#endif 878#endif
871 .open = vhost_net_open, 879 .open = vhost_net_open,
880 .llseek = noop_llseek,
872}; 881};
873 882
874static struct miscdevice vhost_net_misc = { 883static struct miscdevice vhost_net_misc = {
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index b6f149572d1a..94701ff3a23a 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -366,7 +366,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
366 vhost_dev_cleanup(dev); 366 vhost_dev_cleanup(dev);
367 367
368 memory->nregions = 0; 368 memory->nregions = 0;
369 dev->memory = memory; 369 RCU_INIT_POINTER(dev->memory, memory);
370 return 0; 370 return 0;
371} 371}
372 372
@@ -399,8 +399,9 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
399 fput(dev->log_file); 399 fput(dev->log_file);
400 dev->log_file = NULL; 400 dev->log_file = NULL;
401 /* No one will access memory at this point */ 401 /* No one will access memory at this point */
402 kfree(dev->memory); 402 kfree(rcu_dereference_protected(dev->memory,
403 dev->memory = NULL; 403 lockdep_is_held(&dev->mutex)));
404 RCU_INIT_POINTER(dev->memory, NULL);
404 if (dev->mm) 405 if (dev->mm)
405 mmput(dev->mm); 406 mmput(dev->mm);
406 dev->mm = NULL; 407 dev->mm = NULL;
@@ -487,14 +488,22 @@ static int vq_access_ok(unsigned int num,
487/* Caller should have device mutex but not vq mutex */ 488/* Caller should have device mutex but not vq mutex */
488int vhost_log_access_ok(struct vhost_dev *dev) 489int vhost_log_access_ok(struct vhost_dev *dev)
489{ 490{
490 return memory_access_ok(dev, dev->memory, 1); 491 struct vhost_memory *mp;
492
493 mp = rcu_dereference_protected(dev->memory,
494 lockdep_is_held(&dev->mutex));
495 return memory_access_ok(dev, mp, 1);
491} 496}
492 497
493/* Verify access for write logging. */ 498/* Verify access for write logging. */
494/* Caller should have vq mutex and device mutex */ 499/* Caller should have vq mutex and device mutex */
495static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base) 500static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base)
496{ 501{
497 return vq_memory_access_ok(log_base, vq->dev->memory, 502 struct vhost_memory *mp;
503
504 mp = rcu_dereference_protected(vq->dev->memory,
505 lockdep_is_held(&vq->mutex));
506 return vq_memory_access_ok(log_base, mp,
498 vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) && 507 vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) &&
499 (!vq->log_used || log_access_ok(log_base, vq->log_addr, 508 (!vq->log_used || log_access_ok(log_base, vq->log_addr,
500 sizeof *vq->used + 509 sizeof *vq->used +
@@ -534,7 +543,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
534 kfree(newmem); 543 kfree(newmem);
535 return -EFAULT; 544 return -EFAULT;
536 } 545 }
537 oldmem = d->memory; 546 oldmem = rcu_dereference_protected(d->memory,
547 lockdep_is_held(&d->mutex));
538 rcu_assign_pointer(d->memory, newmem); 548 rcu_assign_pointer(d->memory, newmem);
539 synchronize_rcu(); 549 synchronize_rcu();
540 kfree(oldmem); 550 kfree(oldmem);
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index edc892989992..073d06ae091f 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -104,7 +104,7 @@ struct vhost_virtqueue {
104 * vhost_work execution acts instead of rcu_read_lock() and the end of 104 * vhost_work execution acts instead of rcu_read_lock() and the end of
105 * vhost_work execution acts instead of rcu_read_lock(). 105 * vhost_work execution acts instead of rcu_read_lock().
106 * Writers use virtqueue mutex. */ 106 * Writers use virtqueue mutex. */
107 void *private_data; 107 void __rcu *private_data;
108 /* Log write descriptors */ 108 /* Log write descriptors */
109 void __user *log_base; 109 void __user *log_base;
110 struct vhost_log *log; 110 struct vhost_log *log;
@@ -114,7 +114,7 @@ struct vhost_dev {
114 /* Readers use RCU to access memory table pointer 114 /* Readers use RCU to access memory table pointer
115 * log base pointer and features. 115 * log base pointer and features.
116 * Writers use mutex below.*/ 116 * Writers use mutex below.*/
117 struct vhost_memory *memory; 117 struct vhost_memory __rcu *memory;
118 struct mm_struct *mm; 118 struct mm_struct *mm;
119 struct mutex mutex; 119 struct mutex mutex;
120 unsigned acked_features; 120 unsigned acked_features;
@@ -171,7 +171,11 @@ enum {
171 171
172static inline int vhost_has_feature(struct vhost_dev *dev, int bit) 172static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
173{ 173{
174 unsigned acked_features = rcu_dereference(dev->acked_features); 174 unsigned acked_features;
175
176 acked_features =
177 rcu_dereference_index_check(dev->acked_features,
178 lockdep_is_held(&dev->mutex));
175 return acked_features & (1 << bit); 179 return acked_features & (1 << bit);
176} 180}
177 181