66use std:: error;
77use std:: fs:: File ;
88use std:: io;
9+ use std:: os:: fd:: AsFd ;
910#[ cfg( feature = "postcopy" ) ]
1011use std:: os:: fd:: FromRawFd ;
1112use std:: os:: unix:: io:: AsRawFd ;
1213use std:: sync:: Arc ;
1314use std:: thread;
1415
15- use crate :: bitmap:: BitmapReplace ;
16+ use crate :: bitmap:: { BitmapReplace , MemRegionBitmap , MmapLogReg } ;
1617#[ cfg( feature = "postcopy" ) ]
1718use userfaultfd:: { Uffd , UffdBuilder } ;
1819use vhost:: vhost_user:: message:: {
19- VhostTransferStateDirection , VhostTransferStatePhase , VhostUserConfigFlags ,
20+ VhostTransferStateDirection , VhostTransferStatePhase , VhostUserConfigFlags , VhostUserLog ,
2021 VhostUserMemoryRegion , VhostUserProtocolFeatures , VhostUserSingleMemoryRegion ,
2122 VhostUserVirtioFeatures , VhostUserVringAddrFlags , VhostUserVringState ,
2223} ;
@@ -26,7 +27,10 @@ use vhost::vhost_user::{
2627use virtio_bindings:: bindings:: virtio_ring:: VIRTIO_RING_F_EVENT_IDX ;
2728use virtio_queue:: { Error as VirtQueError , QueueT } ;
2829use vm_memory:: mmap:: NewBitmap ;
29- use vm_memory:: { GuestAddress , GuestAddressSpace , GuestMemoryMmap , GuestRegionMmap } ;
30+ use vm_memory:: {
31+ GuestAddress , GuestAddressSpace , GuestMemory , GuestMemoryMmap , GuestMemoryRegion ,
32+ GuestRegionMmap ,
33+ } ;
3034use vmm_sys_util:: epoll:: EventSet ;
3135
3236use super :: backend:: VhostUserBackend ;
@@ -712,6 +716,47 @@ where
712716 self . uffd = None ;
713717 Ok ( ( ) )
714718 }
719+
720+ // Sets logging (i.e., bitmap) shared memory space.
721+ //
722+ // During live migration, the front-end may need to track the modifications the back-end
723+ // makes to the memory mapped regions. The front-end should mark the dirty pages in a log.
724+ // Once it complies to this logging, it may declare the `VHOST_F_LOG_ALL` vhost feature.
725+ //
726+ // If the backend has the `VHOST_USER_PROTOCOL_F_LOG_SHMFD` protocol feature it may receive
727+ // the `VHOST_USER_SET_LOG_BASE` message. The log memory file descriptor is provided in `file`,
728+ // the size and offset of shared memory area are provided in the `VhostUserLog` message.
729+ //
730+ // See https://qemu-project.gitlab.io/qemu/interop/vhost-user.html#migration.
731+ // TODO: We ignore the `LOG_ALL` flag on `SET_FEATURES`, so we will continue marking pages as
732+ // dirty even if the migration fails. We need to disable the logging after receiving a
733+ // `SET_FEATURE` without the `LOG_ALL` flag.
734+ fn set_log_base ( & mut self , log : & VhostUserLog , file : File ) -> VhostUserResult < ( ) > {
735+ let mem = self . atomic_mem . memory ( ) ;
736+
737+ let logmem = Arc :: new (
738+ MmapLogReg :: from_file ( file. as_fd ( ) , log. mmap_offset , log. mmap_size )
739+ . map_err ( VhostUserError :: ReqHandlerError ) ?,
740+ ) ;
741+
742+ // Let's create all bitmaps first before replacing them, in case any of them fails
743+ let mut bitmaps = Vec :: new ( ) ;
744+ for region in mem. iter ( ) {
745+ let bitmap = <<T as VhostUserBackend >:: Bitmap as BitmapReplace >:: InnerBitmap :: new (
746+ region,
747+ Arc :: clone ( & logmem) ,
748+ )
749+ . map_err ( VhostUserError :: ReqHandlerError ) ?;
750+
751+ bitmaps. push ( ( region, bitmap) ) ;
752+ }
753+
754+ for ( region, bitmap) in bitmaps {
755+ region. bitmap ( ) . replace ( bitmap) ;
756+ }
757+
758+ Ok ( ( ) )
759+ }
715760}
716761
717762impl < T : VhostUserBackend > Drop for VhostUserHandler < T > {
0 commit comments