aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vhost
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@relay.de.ibm.com>2010-03-09 13:24:45 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-08-21 19:27:36 -0400
commit28457ee69c473a903e51e26c7bcd6f1e9eceb93e (patch)
tree7f872922577ec45ce655d68770c95082ad858a45 /drivers/vhost
parent65e6bf484c497f02d47a0faae69ee398cd59cfda (diff)
vhost: add __rcu annotations
Also add rcu_dereference_protected() for code paths where locks are held. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: "Michael S. Tsirkin" <mst@redhat.com>
Diffstat (limited to 'drivers/vhost')
-rw-r--r--drivers/vhost/net.c16
-rw-r--r--drivers/vhost/vhost.c22
-rw-r--r--drivers/vhost/vhost.h10
3 files changed, 35 insertions, 13 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 29e850a7a2f..1318ee00834 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);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index e05557d5299..b5c49478d20 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -284,7 +284,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
284 vhost_dev_cleanup(dev); 284 vhost_dev_cleanup(dev);
285 285
286 memory->nregions = 0; 286 memory->nregions = 0;
287 dev->memory = memory; 287 RCU_INIT_POINTER(dev->memory, memory);
288 return 0; 288 return 0;
289} 289}
290 290
@@ -316,8 +316,9 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
316 fput(dev->log_file); 316 fput(dev->log_file);
317 dev->log_file = NULL; 317 dev->log_file = NULL;
318 /* No one will access memory at this point */ 318 /* No one will access memory at this point */
319 kfree(dev->memory); 319 kfree(rcu_dereference_protected(dev->memory,
320 dev->memory = NULL; 320 lockdep_is_held(&dev->mutex)));
321 RCU_INIT_POINTER(dev->memory, NULL);
321 if (dev->mm) 322 if (dev->mm)
322 mmput(dev->mm); 323 mmput(dev->mm);
323 dev->mm = NULL; 324 dev->mm = NULL;
@@ -401,14 +402,22 @@ static int vq_access_ok(unsigned int num,
401/* Caller should have device mutex but not vq mutex */ 402/* Caller should have device mutex but not vq mutex */
402int vhost_log_access_ok(struct vhost_dev *dev) 403int vhost_log_access_ok(struct vhost_dev *dev)
403{ 404{
404 return memory_access_ok(dev, dev->memory, 1); 405 struct vhost_memory *mp;
406
407 mp = rcu_dereference_protected(dev->memory,
408 lockdep_is_held(&dev->mutex));
409 return memory_access_ok(dev, mp, 1);
405} 410}
406 411
407/* Verify access for write logging. */ 412/* Verify access for write logging. */
408/* Caller should have vq mutex and device mutex */ 413/* Caller should have vq mutex and device mutex */
409static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base) 414static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base)
410{ 415{
411 return vq_memory_access_ok(log_base, vq->dev->memory, 416 struct vhost_memory *mp;
417
418 mp = rcu_dereference_protected(vq->dev->memory,
419 lockdep_is_held(&vq->mutex));
420 return vq_memory_access_ok(log_base, mp,
412 vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) && 421 vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) &&
413 (!vq->log_used || log_access_ok(log_base, vq->log_addr, 422 (!vq->log_used || log_access_ok(log_base, vq->log_addr,
414 sizeof *vq->used + 423 sizeof *vq->used +
@@ -448,7 +457,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
448 kfree(newmem); 457 kfree(newmem);
449 return -EFAULT; 458 return -EFAULT;
450 } 459 }
451 oldmem = d->memory; 460 oldmem = rcu_dereference_protected(d->memory,
461 lockdep_is_held(&d->mutex));
452 rcu_assign_pointer(d->memory, newmem); 462 rcu_assign_pointer(d->memory, newmem);
453 synchronize_rcu(); 463 synchronize_rcu();
454 kfree(oldmem); 464 kfree(oldmem);
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index afd77295971..af3c11ded5f 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -106,7 +106,7 @@ struct vhost_virtqueue {
106 * vhost_work execution acts instead of rcu_read_lock() and the end of 106 * vhost_work execution acts instead of rcu_read_lock() and the end of
107 * vhost_work execution acts instead of rcu_read_lock(). 107 * vhost_work execution acts instead of rcu_read_lock().
108 * Writers use virtqueue mutex. */ 108 * Writers use virtqueue mutex. */
109 void *private_data; 109 void __rcu *private_data;
110 /* Log write descriptors */ 110 /* Log write descriptors */
111 void __user *log_base; 111 void __user *log_base;
112 struct vhost_log log[VHOST_NET_MAX_SG]; 112 struct vhost_log log[VHOST_NET_MAX_SG];
@@ -116,7 +116,7 @@ struct vhost_dev {
116 /* Readers use RCU to access memory table pointer 116 /* Readers use RCU to access memory table pointer
117 * log base pointer and features. 117 * log base pointer and features.
118 * Writers use mutex below.*/ 118 * Writers use mutex below.*/
119 struct vhost_memory *memory; 119 struct vhost_memory __rcu *memory;
120 struct mm_struct *mm; 120 struct mm_struct *mm;
121 struct mutex mutex; 121 struct mutex mutex;
122 unsigned acked_features; 122 unsigned acked_features;
@@ -173,7 +173,11 @@ enum {
173 173
174static inline int vhost_has_feature(struct vhost_dev *dev, int bit) 174static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
175{ 175{
176 unsigned acked_features = rcu_dereference(dev->acked_features); 176 unsigned acked_features;
177
178 acked_features =
179 rcu_dereference_index_check(dev->acked_features,
180 lockdep_is_held(&dev->mutex));
177 return acked_features & (1 << bit); 181 return acked_features & (1 << bit);
178} 182}
179 183