@@ -102,55 +102,50 @@ static void virtio_scsi_free_req(VirtIOSCSIReq *req)
102
102
g_free (req );
103
103
}
104
104
105
- static void virtio_scsi_complete_req (VirtIOSCSIReq * req )
105
+ static void virtio_scsi_complete_req (VirtIOSCSIReq * req , QemuMutex * vq_lock )
106
106
{
107
107
VirtIOSCSI * s = req -> dev ;
108
108
VirtQueue * vq = req -> vq ;
109
109
VirtIODevice * vdev = VIRTIO_DEVICE (s );
110
110
111
111
qemu_iovec_from_buf (& req -> resp_iov , 0 , & req -> resp , req -> resp_size );
112
+
113
+ if (vq_lock ) {
114
+ qemu_mutex_lock (vq_lock );
115
+ }
116
+
112
117
virtqueue_push (vq , & req -> elem , req -> qsgl .size + req -> resp_iov .size );
113
118
if (s -> dataplane_started && !s -> dataplane_fenced ) {
114
119
virtio_notify_irqfd (vdev , vq );
115
120
} else {
116
121
virtio_notify (vdev , vq );
117
122
}
118
123
124
+ if (vq_lock ) {
125
+ qemu_mutex_unlock (vq_lock );
126
+ }
127
+
119
128
if (req -> sreq ) {
120
129
req -> sreq -> hba_private = NULL ;
121
130
scsi_req_unref (req -> sreq );
122
131
}
123
132
virtio_scsi_free_req (req );
124
133
}
125
134
126
- static void virtio_scsi_complete_req_bh ( void * opaque )
135
+ static void virtio_scsi_bad_req ( VirtIOSCSIReq * req , QemuMutex * vq_lock )
127
136
{
128
- VirtIOSCSIReq * req = opaque ;
137
+ virtio_error ( VIRTIO_DEVICE ( req -> dev ), "wrong size for virtio-scsi headers" ) ;
129
138
130
- virtio_scsi_complete_req (req );
131
- }
139
+ if (vq_lock ) {
140
+ qemu_mutex_lock (vq_lock );
141
+ }
132
142
133
- /*
134
- * Called from virtio_scsi_do_one_tmf_bh() in main loop thread. The main loop
135
- * thread cannot touch the virtqueue since that could race with an IOThread.
136
- */
137
- static void virtio_scsi_complete_req_from_main_loop (VirtIOSCSIReq * req )
138
- {
139
- VirtIOSCSI * s = req -> dev ;
143
+ virtqueue_detach_element (req -> vq , & req -> elem , 0 );
140
144
141
- if (!s -> ctx || s -> ctx == qemu_get_aio_context ()) {
142
- /* No need to schedule a BH when there is no IOThread */
143
- virtio_scsi_complete_req (req );
144
- } else {
145
- /* Run request completion in the IOThread */
146
- aio_wait_bh_oneshot (s -> ctx , virtio_scsi_complete_req_bh , req );
145
+ if (vq_lock ) {
146
+ qemu_mutex_unlock (vq_lock );
147
147
}
148
- }
149
148
150
- static void virtio_scsi_bad_req (VirtIOSCSIReq * req )
151
- {
152
- virtio_error (VIRTIO_DEVICE (req -> dev ), "wrong size for virtio-scsi headers" );
153
- virtqueue_detach_element (req -> vq , & req -> elem , 0 );
154
149
virtio_scsi_free_req (req );
155
150
}
156
151
@@ -235,12 +230,21 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
235
230
return 0 ;
236
231
}
237
232
238
- static VirtIOSCSIReq * virtio_scsi_pop_req (VirtIOSCSI * s , VirtQueue * vq )
233
+ static VirtIOSCSIReq * virtio_scsi_pop_req (VirtIOSCSI * s , VirtQueue * vq , QemuMutex * vq_lock )
239
234
{
240
235
VirtIOSCSICommon * vs = (VirtIOSCSICommon * )s ;
241
236
VirtIOSCSIReq * req ;
242
237
238
+ if (vq_lock ) {
239
+ qemu_mutex_lock (vq_lock );
240
+ }
241
+
243
242
req = virtqueue_pop (vq , sizeof (VirtIOSCSIReq ) + vs -> cdb_size );
243
+
244
+ if (vq_lock ) {
245
+ qemu_mutex_unlock (vq_lock );
246
+ }
247
+
244
248
if (!req ) {
245
249
return NULL ;
246
250
}
@@ -305,7 +309,7 @@ static void virtio_scsi_cancel_notify(Notifier *notifier, void *data)
305
309
306
310
trace_virtio_scsi_tmf_resp (virtio_scsi_get_lun (req -> req .tmf .lun ),
307
311
req -> req .tmf .tag , req -> resp .tmf .response );
308
- virtio_scsi_complete_req (req );
312
+ virtio_scsi_complete_req (req , & req -> dev -> ctrl_lock );
309
313
}
310
314
g_free (n );
311
315
}
@@ -361,7 +365,7 @@ static void virtio_scsi_do_one_tmf_bh(VirtIOSCSIReq *req)
361
365
362
366
out :
363
367
object_unref (OBJECT (d ));
364
- virtio_scsi_complete_req_from_main_loop (req );
368
+ virtio_scsi_complete_req (req , & s -> ctrl_lock );
365
369
}
366
370
367
371
/* Some TMFs must be processed from the main loop thread */
@@ -408,7 +412,7 @@ static void virtio_scsi_reset_tmf_bh(VirtIOSCSI *s)
408
412
409
413
/* SAM-6 6.3.2 Hard reset */
410
414
req -> resp .tmf .response = VIRTIO_SCSI_S_TARGET_FAILURE ;
411
- virtio_scsi_complete_req (req );
415
+ virtio_scsi_complete_req (req , & req -> dev -> ctrl_lock );
412
416
}
413
417
}
414
418
@@ -562,15 +566,15 @@ static void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
562
566
563
567
if (iov_to_buf (req -> elem .out_sg , req -> elem .out_num , 0 ,
564
568
& type , sizeof (type )) < sizeof (type )) {
565
- virtio_scsi_bad_req (req );
569
+ virtio_scsi_bad_req (req , & s -> ctrl_lock );
566
570
return ;
567
571
}
568
572
569
573
virtio_tswap32s (vdev , & type );
570
574
if (type == VIRTIO_SCSI_T_TMF ) {
571
575
if (virtio_scsi_parse_req (req , sizeof (VirtIOSCSICtrlTMFReq ),
572
576
sizeof (VirtIOSCSICtrlTMFResp )) < 0 ) {
573
- virtio_scsi_bad_req (req );
577
+ virtio_scsi_bad_req (req , & s -> ctrl_lock );
574
578
return ;
575
579
} else {
576
580
r = virtio_scsi_do_tmf (s , req );
@@ -580,7 +584,7 @@ static void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
580
584
type == VIRTIO_SCSI_T_AN_SUBSCRIBE ) {
581
585
if (virtio_scsi_parse_req (req , sizeof (VirtIOSCSICtrlANReq ),
582
586
sizeof (VirtIOSCSICtrlANResp )) < 0 ) {
583
- virtio_scsi_bad_req (req );
587
+ virtio_scsi_bad_req (req , & s -> ctrl_lock );
584
588
return ;
585
589
} else {
586
590
req -> req .an .event_requested =
@@ -600,7 +604,7 @@ static void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
600
604
type == VIRTIO_SCSI_T_AN_SUBSCRIBE )
601
605
trace_virtio_scsi_an_resp (virtio_scsi_get_lun (req -> req .an .lun ),
602
606
req -> resp .an .response );
603
- virtio_scsi_complete_req (req );
607
+ virtio_scsi_complete_req (req , & s -> ctrl_lock );
604
608
} else {
605
609
assert (r == - EINPROGRESS );
606
610
}
@@ -610,7 +614,7 @@ static void virtio_scsi_handle_ctrl_vq(VirtIOSCSI *s, VirtQueue *vq)
610
614
{
611
615
VirtIOSCSIReq * req ;
612
616
613
- while ((req = virtio_scsi_pop_req (s , vq ))) {
617
+ while ((req = virtio_scsi_pop_req (s , vq , & s -> ctrl_lock ))) {
614
618
virtio_scsi_handle_ctrl_req (s , req );
615
619
}
616
620
}
@@ -654,7 +658,7 @@ static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req)
654
658
* in virtio_scsi_command_complete.
655
659
*/
656
660
req -> resp_size = sizeof (VirtIOSCSICmdResp );
657
- virtio_scsi_complete_req (req );
661
+ virtio_scsi_complete_req (req , NULL );
658
662
}
659
663
660
664
static void virtio_scsi_command_failed (SCSIRequest * r )
@@ -788,7 +792,7 @@ static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
788
792
virtio_scsi_fail_cmd_req (req );
789
793
return - ENOTSUP ;
790
794
} else {
791
- virtio_scsi_bad_req (req );
795
+ virtio_scsi_bad_req (req , NULL );
792
796
return - EINVAL ;
793
797
}
794
798
}
@@ -843,7 +847,7 @@ static void virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
843
847
virtio_queue_set_notification (vq , 0 );
844
848
}
845
849
846
- while ((req = virtio_scsi_pop_req (s , vq ))) {
850
+ while ((req = virtio_scsi_pop_req (s , vq , NULL ))) {
847
851
ret = virtio_scsi_handle_cmd_req_prepare (s , req );
848
852
if (!ret ) {
849
853
QTAILQ_INSERT_TAIL (& reqs , req , next );
@@ -973,7 +977,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s,
973
977
return ;
974
978
}
975
979
976
- req = virtio_scsi_pop_req (s , vs -> event_vq );
980
+ req = virtio_scsi_pop_req (s , vs -> event_vq , & s -> event_lock );
977
981
if (!req ) {
978
982
s -> events_dropped = true;
979
983
return ;
@@ -985,7 +989,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s,
985
989
}
986
990
987
991
if (virtio_scsi_parse_req (req , 0 , sizeof (VirtIOSCSIEvent ))) {
988
- virtio_scsi_bad_req (req );
992
+ virtio_scsi_bad_req (req , & s -> event_lock );
989
993
return ;
990
994
}
991
995
@@ -1005,7 +1009,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s,
1005
1009
}
1006
1010
trace_virtio_scsi_event (virtio_scsi_get_lun (evt -> lun ), event , reason );
1007
1011
1008
- virtio_scsi_complete_req (req );
1012
+ virtio_scsi_complete_req (req , & s -> event_lock );
1009
1013
}
1010
1014
1011
1015
static void virtio_scsi_handle_event_vq (VirtIOSCSI * s , VirtQueue * vq )
@@ -1236,6 +1240,8 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
1236
1240
Error * err = NULL ;
1237
1241
1238
1242
QTAILQ_INIT (& s -> tmf_bh_list );
1243
+ qemu_mutex_init (& s -> ctrl_lock );
1244
+ qemu_mutex_init (& s -> event_lock );
1239
1245
qemu_mutex_init (& s -> tmf_bh_lock );
1240
1246
1241
1247
virtio_scsi_common_realize (dev ,
@@ -1280,6 +1286,8 @@ static void virtio_scsi_device_unrealize(DeviceState *dev)
1280
1286
qbus_set_hotplug_handler (BUS (& s -> bus ), NULL );
1281
1287
virtio_scsi_common_unrealize (dev );
1282
1288
qemu_mutex_destroy (& s -> tmf_bh_lock );
1289
+ qemu_mutex_destroy (& s -> event_lock );
1290
+ qemu_mutex_destroy (& s -> ctrl_lock );
1283
1291
}
1284
1292
1285
1293
static const Property virtio_scsi_properties [] = {
0 commit comments