@ -284,7 +284,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
vhost_dev_cleanup ( dev ) ;
memory - > nregions = 0 ;
dev - > memory = memory ;
RCU_INIT_POINTER ( dev - > memory , memory ) ;
return 0 ;
}
@ -316,8 +316,9 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
fput ( dev - > log_file ) ;
dev - > log_file = NULL ;
/* No one will access memory at this point */
kfree ( dev - > memory ) ;
dev - > memory = NULL ;
kfree ( rcu_dereference_protected ( dev - > memory ,
lockdep_is_held ( & dev - > mutex ) ) ) ;
RCU_INIT_POINTER ( dev - > memory , NULL ) ;
if ( dev - > mm )
mmput ( dev - > mm ) ;
dev - > mm = NULL ;
@ -401,14 +402,22 @@ static int vq_access_ok(unsigned int num,
/* Caller should have device mutex but not vq mutex */
int vhost_log_access_ok ( struct vhost_dev * dev )
{
return memory_access_ok ( dev , dev - > memory , 1 ) ;
struct vhost_memory * mp ;
mp = rcu_dereference_protected ( dev - > memory ,
lockdep_is_held ( & dev - > mutex ) ) ;
return memory_access_ok ( dev , mp , 1 ) ;
}
/* Verify access for write logging. */
/* Caller should have vq mutex and device mutex */
static int vq_log_access_ok ( struct vhost_virtqueue * vq , void __user * log_base )
{
return vq_memory_access_ok ( log_base , vq - > dev - > memory ,
struct vhost_memory * mp ;
mp = rcu_dereference_protected ( vq - > dev - > memory ,
lockdep_is_held ( & vq - > mutex ) ) ;
return vq_memory_access_ok ( log_base , mp ,
vhost_has_feature ( vq - > dev , VHOST_F_LOG_ALL ) ) & &
( ! vq - > log_used | | log_access_ok ( log_base , vq - > log_addr ,
sizeof * vq - > used +
@ -448,7 +457,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
kfree ( newmem ) ;
return - EFAULT ;
}
oldmem = d - > memory ;
oldmem = rcu_dereference_protected ( d - > memory ,
lockdep_is_held ( & d - > mutex ) ) ;
rcu_assign_pointer ( d - > memory , newmem ) ;
synchronize_rcu ( ) ;
kfree ( oldmem ) ;