@@ -40,9 +40,9 @@ use util::loop_context::{
4040 gen_delete_notifiers, read_fd, EventNotifier , EventNotifierHelper , NotifierCallback ,
4141 NotifierOperation ,
4242} ;
43- use virtio:: vhost:: user:: RegionMemInfo ;
4443use virtio:: {
45- Queue , QueueConfig , QUEUE_TYPE_SPLIT_VRING , VIRTIO_F_RING_EVENT_IDX ,
44+ vhost:: user:: RegionMemInfo , virtio_has_feature, Queue , QueueConfig ,
45+ VhostUser :: VHOST_USER_F_PROTOCOL_FEATURES , QUEUE_TYPE_SPLIT_VRING , VIRTIO_F_RING_EVENT_IDX ,
4646 VIRTIO_F_RING_INDIRECT_DESC , VIRTIO_F_VERSION_1 ,
4747} ;
4848
@@ -246,6 +246,51 @@ impl VirtioFs {
246246
247247 bail ! ( "Failed to find the guest address for addr: 0x{:X}" , addr) ;
248248 }
249+
250+ fn register_fs_handler ( & mut self , queue_index : usize ) -> Result < ( ) > {
251+ // Before setting up new notifiers, we should remove old ones.
252+ self . unregister_fs_handler ( queue_index) ?;
253+
254+ let driver_features = self . config . driver_features ;
255+ let mut queue_info = self . config . get_mut_queue_config ( queue_index) ?;
256+ if queue_info. kick_evt . is_none ( ) || queue_info. call_evt . is_none ( ) {
257+ bail ! (
258+ "The event for kicking {} or calling {} is none" ,
259+ queue_info. kick_evt. is_none( ) ,
260+ queue_info. call_evt. is_none( ) ,
261+ ) ;
262+ }
263+ queue_info. config . ready = true ;
264+
265+ let fs_handler = Arc :: new ( Mutex :: new (
266+ FsIoHandler :: new (
267+ queue_info. config ,
268+ queue_info. kick_evt . as_ref ( ) . unwrap ( ) . clone ( ) ,
269+ queue_info. call_evt . as_ref ( ) . unwrap ( ) . clone ( ) ,
270+ & self . sys_mem ,
271+ driver_features,
272+ self . fs . clone ( ) ,
273+ )
274+ . with_context ( || "Failed to create fs handler" ) ?,
275+ ) ) ;
276+
277+ self . fs_handlers [ queue_index] = Some ( fs_handler. clone ( ) ) ;
278+ EventLoop :: update_event ( EventNotifierHelper :: internal_notifiers ( fs_handler) , None )
279+ . with_context ( || "Failed to update event for queue status which is ready" ) ?;
280+
281+ Ok ( ( ) )
282+ }
283+
284+ fn unregister_fs_handler ( & mut self , queue_index : usize ) -> Result < ( ) > {
285+ if let Some ( fs_handler) = self . fs_handlers . get_mut ( queue_index) . unwrap ( ) . take ( ) {
286+ EventLoop :: update_event ( fs_handler. lock ( ) . unwrap ( ) . delete_notifiers ( ) , None )
287+ . with_context ( || "Failed to update event for queue status which is not ready" ) ?;
288+ } ;
289+ let mut queue_info = self . config . get_mut_queue_config ( queue_index) ?;
290+ queue_info. config . ready = false ;
291+
292+ Ok ( ( ) )
293+ }
249294}
250295
251296impl VhostUserReqHandler for VirtioFs {
@@ -398,6 +443,11 @@ impl VhostUserReqHandler for VirtioFs {
398443 queue_info. call_evt = Some ( Arc :: new ( call_evt) ) ;
399444 } )
400445 . with_context ( || format ! ( "Failed to set vring call, index: {}" , index) ) ?;
446+
447+ if !virtio_has_feature ( self . config . driver_features , VHOST_USER_F_PROTOCOL_FEATURES ) {
448+ self . register_fs_handler ( queue_index) ?;
449+ }
450+
401451 Ok ( ( ) )
402452 }
403453
@@ -417,43 +467,11 @@ impl VhostUserReqHandler for VirtioFs {
417467 }
418468
419469 fn set_vring_enable ( & mut self , queue_index : usize , status : u32 ) -> Result < ( ) > {
420- let driver_features = self . config . driver_features ;
421-
422- let mut queue_info = self . config . get_mut_queue_config ( queue_index) ?;
423- queue_info. config . ready = status == 1 ;
424-
425- // Before setting up new notifiers, we should remove old ones.
426- if let Some ( fs_handler) = self . fs_handlers . get_mut ( queue_index) . unwrap ( ) . take ( ) {
427- EventLoop :: update_event ( fs_handler. lock ( ) . unwrap ( ) . delete_notifiers ( ) , None )
428- . with_context ( || "Failed to update event for queue status which is not ready" ) ?;
429- } ;
430-
431470 if status == 1 {
432- if queue_info. kick_evt . is_none ( ) || queue_info. call_evt . is_none ( ) {
433- bail ! (
434- "The event for kicking {} or calling {} is none" ,
435- queue_info. kick_evt. is_none( ) ,
436- queue_info. call_evt. is_none( ) ,
437- ) ;
438- }
439-
440- let fs_handler = Arc :: new ( Mutex :: new (
441- FsIoHandler :: new (
442- queue_info. config ,
443- queue_info. kick_evt . as_ref ( ) . unwrap ( ) . clone ( ) ,
444- queue_info. call_evt . as_ref ( ) . unwrap ( ) . clone ( ) ,
445- & self . sys_mem ,
446- driver_features,
447- self . fs . clone ( ) ,
448- )
449- . with_context ( || "Failed to create fs handler" ) ?,
450- ) ) ;
451-
452- self . fs_handlers [ queue_index] = Some ( fs_handler. clone ( ) ) ;
453- EventLoop :: update_event ( EventNotifierHelper :: internal_notifiers ( fs_handler) , None )
454- . with_context ( || "Failed to update event for queue status which is ready" ) ?;
471+ self . register_fs_handler ( queue_index) ?;
472+ } else {
473+ self . unregister_fs_handler ( queue_index) ?;
455474 }
456-
457475 Ok ( ( ) )
458476 }
459477}
0 commit comments