@ -24,33 +24,41 @@
void virtio_9p_push_and_notify ( V9fsPDU * pdu )
{
V9fsState * s = pdu - > s ;
V9fsVirtioState * v = container_of ( s , V9fsVirtioState , state ) ;
VirtQueueElement * elem = & v - > elems [ pdu - > idx ] ;
/* push onto queue and notify */
virtqueue_push ( s - > vq , & pdu - > elem , pdu - > size ) ;
virtqueue_push ( v - > vq , elem , pdu - > size ) ;
/* FIXME: we should batch these completions */
virtio_notify ( VIRTIO_DEVICE ( s ) , s - > vq ) ;
virtio_notify ( VIRTIO_DEVICE ( v ) , v - > vq ) ;
}
static void handle_9p_output ( VirtIODevice * vdev , VirtQueue * vq )
{
V9fsState * s = ( V9fsState * ) vdev ;
V9fsVirtioState * v = ( V9fsVirtioState * ) vdev ;
V9fsState * s = & v - > state ;
V9fsPDU * pdu ;
ssize_t len ;
while ( ( pdu = pdu_alloc ( s ) ) & &
( len = virtqueue_pop ( vq , & pdu - > elem ) ) ! = 0 ) {
while ( ( pdu = pdu_alloc ( s ) ) ) {
struct {
uint32_t size_le ;
uint8_t id ;
uint16_t tag_le ;
} QEMU_PACKED out ;
int len ;
VirtQueueElement * elem = & v - > elems [ pdu - > idx ] ;
BUG_ON ( pdu - > elem . out_num = = 0 | | pdu - > elem . in_num = = 0 ) ;
len = virtqueue_pop ( vq , elem ) ;
if ( ! len ) {
pdu_free ( pdu ) ;
break ;
}
BUG_ON ( elem - > out_num = = 0 | | elem - > in_num = = 0 ) ;
QEMU_BUILD_BUG_ON ( sizeof out ! = 7 ) ;
len = iov_to_buf ( pdu - > elem . out_sg , pdu - > elem . out_num , 0 ,
len = iov_to_buf ( elem - > out_sg , elem - > out_num , 0 ,
& out , sizeof out ) ;
BUG_ON ( len ! = sizeof out ) ;
@ -62,7 +70,6 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
qemu_co_queue_init ( & pdu - > complete ) ;
pdu_submit ( pdu ) ;
}
pdu_free ( pdu ) ;
}
static uint64_t virtio_9p_get_features ( VirtIODevice * vdev , uint64_t features ,
@ -76,14 +83,15 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
{
int len ;
struct virtio_9p_config * cfg ;
V9fsState * s = VIRTIO_9P ( vdev ) ;
V9fsVirtioState * v = VIRTIO_9P ( vdev ) ;
V9fsState * s = & v - > state ;
len = strlen ( s - > tag ) ;
cfg = g_malloc0 ( sizeof ( struct virtio_9p_config ) + len ) ;
virtio_stw_p ( vdev , & cfg - > tag_len , len ) ;
/* We don't copy the terminating null to config space */
memcpy ( cfg - > tag , s - > tag , len ) ;
memcpy ( config , cfg , s - > config_size ) ;
memcpy ( config , cfg , v - > config_size ) ;
g_free ( cfg ) ;
}
@ -100,16 +108,17 @@ static int virtio_9p_load(QEMUFile *f, void *opaque, int version_id)
static void virtio_9p_device_realize ( DeviceState * dev , Error * * errp )
{
VirtIODevice * vdev = VIRTIO_DEVICE ( dev ) ;
V9fsState * s = VIRTIO_9P ( dev ) ;
V9fsVirtioState * v = VIRTIO_9P ( dev ) ;
V9fsState * s = & v - > state ;
if ( v9fs_device_realize_common ( s , errp ) ) {
goto out ;
}
s - > config_size = sizeof ( struct virtio_9p_config ) + strlen ( s - > fsconf . tag ) ;
virtio_init ( vdev , " virtio-9p " , VIRTIO_ID_9P , s - > config_size ) ;
s - > vq = virtio_add_queue ( vdev , MAX_REQ , handle_9p_output ) ;
register_savevm ( dev , " virtio-9p " , - 1 , 1 , virtio_9p_save , virtio_9p_load , s ) ;
v - > config_size = sizeof ( struct virtio_9p_config ) + strlen ( s - > fsconf . tag ) ;
virtio_init ( vdev , " virtio-9p " , VIRTIO_ID_9P , v - > config_size ) ;
v - > vq = virtio_add_queue ( vdev , MAX_REQ , handle_9p_output ) ;
register_savevm ( dev , " virtio-9p " , - 1 , 1 , virtio_9p_save , virtio_9p_load , v ) ;
out :
return ;
@ -118,44 +127,55 @@ out:
static void virtio_9p_device_unrealize ( DeviceState * dev , Error * * errp )
{
VirtIODevice * vdev = VIRTIO_DEVICE ( dev ) ;
V9fsState * s = VIRTIO_9P ( dev ) ;
V9fsVirtioState * v = VIRTIO_9P ( dev ) ;
V9fsState * s = & v - > state ;
virtio_cleanup ( vdev ) ;
unregister_savevm ( dev , " virtio-9p " , s ) ;
unregister_savevm ( dev , " virtio-9p " , v ) ;
v9fs_device_unrealize_common ( s , errp ) ;
}
ssize_t virtio_pdu_vmarshal ( V9fsPDU * pdu , size_t offset ,
const char * fmt , va_list ap )
{
return v9fs_iov_vmarshal ( pdu - > elem . in_sg , pdu - > elem . in_num ,
offset , 1 , fmt , ap ) ;
V9fsState * s = pdu - > s ;
V9fsVirtioState * v = container_of ( s , V9fsVirtioState , state ) ;
VirtQueueElement * elem = & v - > elems [ pdu - > idx ] ;
return v9fs_iov_vmarshal ( elem - > in_sg , elem - > in_num , offset , 1 , fmt , ap ) ;
}
ssize_t virtio_pdu_vunmarshal ( V9fsPDU * pdu , size_t offset ,
const char * fmt , va_list ap )
{
return v9fs_iov_vunmarshal ( pdu - > elem . out_sg , pdu - > elem . out_num ,
offset , 1 , fmt , ap ) ;
V9fsState * s = pdu - > s ;
V9fsVirtioState * v = container_of ( s , V9fsVirtioState , state ) ;
VirtQueueElement * elem = & v - > elems [ pdu - > idx ] ;
return v9fs_iov_vunmarshal ( elem - > out_sg , elem - > out_num , offset , 1 , fmt , ap ) ;
}
void virtio_init_iov_from_pdu ( V9fsPDU * pdu , struct iovec * * piov ,
unsigned int * pniov , bool is_write )
{
V9fsState * s = pdu - > s ;
V9fsVirtioState * v = container_of ( s , V9fsVirtioState , state ) ;
VirtQueueElement * elem = & v - > elems [ pdu - > idx ] ;
if ( is_write ) {
* piov = pdu - > elem . out_sg ;
* pniov = pdu - > elem . out_num ;
* piov = elem - > out_sg ;
* pniov = elem - > out_num ;
} else {
* piov = pdu - > elem . in_sg ;
* pniov = pdu - > elem . in_num ;
* piov = elem - > in_sg ;
* pniov = elem - > in_num ;
}
}
/* virtio-9p device */
static Property virtio_9p_properties [ ] = {
DEFINE_PROP_STRING ( " mount_tag " , V9fsState , fsconf . tag ) ,
DEFINE_PROP_STRING ( " fsdev " , V9fsState , fsconf . fsdev_id ) ,
DEFINE_PROP_STRING ( " mount_tag " , V9fsVirtio State , state . fsconf . tag ) ,
DEFINE_PROP_STRING ( " fsdev " , V9fsVirtio State , state . fsconf . fsdev_id ) ,
DEFINE_PROP_END_OF_LIST ( ) ,
} ;
@ -175,7 +195,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data)
static const TypeInfo virtio_device_info = {
. name = TYPE_VIRTIO_9P ,
. parent = TYPE_VIRTIO_DEVICE ,
. instance_size = sizeof ( V9fsState ) ,
. instance_size = sizeof ( V9fsVirtio State ) ,
. class_init = virtio_9p_class_init ,
} ;