@ -86,6 +86,7 @@ static uint32_t known_capabilities = RDMA_CAPABILITY_PIN_ALL;
" to abort! " ) ; \
rdma - > error_reported = 1 ; \
} \
rcu_read_unlock ( ) ; \
return rdma - > error_state ; \
} \
} while ( 0 )
@ -387,6 +388,10 @@ typedef struct RDMAContext {
uint64_t unregistrations [ RDMA_SIGNALED_SEND_MAX ] ;
GHashTable * blockmap ;
/* the RDMAContext for return path */
struct RDMAContext * return_path ;
bool is_return_path ;
} RDMAContext ;
# define TYPE_QIO_CHANNEL_RDMA "qio-channel-rdma"
@ -398,7 +403,8 @@ typedef struct QIOChannelRDMA QIOChannelRDMA;
struct QIOChannelRDMA {
QIOChannel parent ;
RDMAContext * rdma ;
RDMAContext * rdmain ;
RDMAContext * rdmaout ;
QEMUFile * file ;
bool blocking ; /* XXX we don't actually honour this yet */
} ;
@ -1483,27 +1489,56 @@ static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out,
*/
static int qemu_rdma_wait_comp_channel ( RDMAContext * rdma )
{
struct rdma_cm_event * cm_event ;
int ret = - 1 ;
/*
* Coroutine doesn ' t start until migration_fd_process_incoming ( )
* so don ' t yield unless we know we ' re running inside of a coroutine .
*/
if ( rdma - > migration_started_on_destination ) {
if ( rdma - > migration_started_on_destination & &
migration_incoming_get_current ( ) - > state = = MIGRATION_STATUS_ACTIVE ) {
yield_until_fd_readable ( rdma - > comp_channel - > fd ) ;
} else {
/* This is the source side, we're in a separate thread
* or destination prior to migration_fd_process_incoming ( )
* after postcopy , the destination also in a seprate thread .
* we can ' t yield ; so we have to poll the fd .
* But we need to be able to handle ' cancel ' or an error
* without hanging forever .
*/
while ( ! rdma - > error_state & & ! rdma - > received_error ) {
GPollFD pfds [ 1 ] ;
GPollFD pfds [ 2 ] ;
pfds [ 0 ] . fd = rdma - > comp_channel - > fd ;
pfds [ 0 ] . events = G_IO_IN | G_IO_HUP | G_IO_ERR ;
pfds [ 0 ] . revents = 0 ;
pfds [ 1 ] . fd = rdma - > channel - > fd ;
pfds [ 1 ] . events = G_IO_IN | G_IO_HUP | G_IO_ERR ;
pfds [ 1 ] . revents = 0 ;
/* 0.1s timeout, should be fine for a 'cancel' */
switch ( qemu_poll_ns ( pfds , 1 , 100 * 1000 * 1000 ) ) {
switch ( qemu_poll_ns ( pfds , 2 , 100 * 1000 * 1000 ) ) {
case 2 :
case 1 : /* fd active */
return 0 ;
if ( pfds [ 0 ] . revents ) {
return 0 ;
}
if ( pfds [ 1 ] . revents ) {
ret = rdma_get_cm_event ( rdma - > channel , & cm_event ) ;
if ( ! ret ) {
rdma_ack_cm_event ( cm_event ) ;
}
error_report ( " receive cm event while wait comp channel, "
" cm event is %d " , cm_event - > event ) ;
if ( cm_event - > event = = RDMA_CM_EVENT_DISCONNECTED | |
cm_event - > event = = RDMA_CM_EVENT_DEVICE_REMOVAL ) {
return - EPIPE ;
}
}
break ;
case 0 : /* Timeout, go around again */
break ;
@ -2323,10 +2358,22 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
rdma_destroy_id ( rdma - > cm_id ) ;
rdma - > cm_id = NULL ;
}
/* the destination side, listen_id and channel is shared */
if ( rdma - > listen_id ) {
rdma_destroy_id ( rdma - > listen_id ) ;
if ( ! rdma - > is_return_path ) {
rdma_destroy_id ( rdma - > listen_id ) ;
}
rdma - > listen_id = NULL ;
if ( rdma - > channel ) {
if ( ! rdma - > is_return_path ) {
rdma_destroy_event_channel ( rdma - > channel ) ;
}
rdma - > channel = NULL ;
}
}
if ( rdma - > channel ) {
rdma_destroy_event_channel ( rdma - > channel ) ;
rdma - > channel = NULL ;
@ -2555,6 +2602,25 @@ err_dest_init_create_listen_id:
}
static void qemu_rdma_return_path_dest_init ( RDMAContext * rdma_return_path ,
RDMAContext * rdma )
{
int idx ;
for ( idx = 0 ; idx < RDMA_WRID_MAX ; idx + + ) {
rdma_return_path - > wr_data [ idx ] . control_len = 0 ;
rdma_return_path - > wr_data [ idx ] . control_curr = NULL ;
}
/*the CM channel and CM id is shared*/
rdma_return_path - > channel = rdma - > channel ;
rdma_return_path - > listen_id = rdma - > listen_id ;
rdma - > return_path = rdma_return_path ;
rdma_return_path - > return_path = rdma ;
rdma_return_path - > is_return_path = true ;
}
static void * qemu_rdma_data_init ( const char * host_port , Error * * errp )
{
RDMAContext * rdma = NULL ;
@ -2595,12 +2661,20 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc,
{
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( ioc ) ;
QEMUFile * f = rioc - > file ;
RDMAContext * rdma = rioc - > rdma ;
RDMAContext * rdma ;
int ret ;
ssize_t done = 0 ;
size_t i ;
size_t len = 0 ;
rcu_read_lock ( ) ;
rdma = atomic_rcu_read ( & rioc - > rdmaout ) ;
if ( ! rdma ) {
rcu_read_unlock ( ) ;
return - EIO ;
}
CHECK_ERROR_STATE ( ) ;
/*
@ -2610,6 +2684,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc,
ret = qemu_rdma_write_flush ( f , rdma ) ;
if ( ret < 0 ) {
rdma - > error_state = ret ;
rcu_read_unlock ( ) ;
return ret ;
}
@ -2629,6 +2704,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc,
if ( ret < 0 ) {
rdma - > error_state = ret ;
rcu_read_unlock ( ) ;
return ret ;
}
@ -2637,6 +2713,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc,
}
}
rcu_read_unlock ( ) ;
return done ;
}
@ -2670,12 +2747,20 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc,
Error * * errp )
{
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( ioc ) ;
RDMAContext * rdma = rioc - > rdma ;
RDMAContext * rdma ;
RDMAControlHeader head ;
int ret = 0 ;
ssize_t i ;
size_t done = 0 ;
rcu_read_lock ( ) ;
rdma = atomic_rcu_read ( & rioc - > rdmain ) ;
if ( ! rdma ) {
rcu_read_unlock ( ) ;
return - EIO ;
}
CHECK_ERROR_STATE ( ) ;
for ( i = 0 ; i < niov ; i + + ) {
@ -2687,7 +2772,7 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc,
* were given and dish out the bytes until we run
* out of bytes .
*/
ret = qemu_rdma_fill ( rioc - > r dma , data , want , 0 ) ;
ret = qemu_rdma_fill ( rdma , data , want , 0 ) ;
done + = ret ;
want - = ret ;
/* Got what we needed, so go to next iovec */
@ -2709,25 +2794,28 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc,
if ( ret < 0 ) {
rdma - > error_state = ret ;
rcu_read_unlock ( ) ;
return ret ;
}
/*
* SEND was received with new bytes , now try again .
*/
ret = qemu_rdma_fill ( rioc - > r dma , data , want , 0 ) ;
ret = qemu_rdma_fill ( rdma , data , want , 0 ) ;
done + = ret ;
want - = ret ;
/* Still didn't get enough, so lets just return */
if ( want ) {
if ( done = = 0 ) {
rcu_read_unlock ( ) ;
return QIO_CHANNEL_ERR_BLOCK ;
} else {
break ;
}
}
}
rcu_read_unlock ( ) ;
return done ;
}
@ -2779,15 +2867,29 @@ qio_channel_rdma_source_prepare(GSource *source,
gint * timeout )
{
QIOChannelRDMASource * rsource = ( QIOChannelRDMASource * ) source ;
RDMAContext * rdma = rsource - > rioc - > rdma ;
RDMAContext * rdma ;
GIOCondition cond = 0 ;
* timeout = - 1 ;
rcu_read_lock ( ) ;
if ( rsource - > condition = = G_IO_IN ) {
rdma = atomic_rcu_read ( & rsource - > rioc - > rdmain ) ;
} else {
rdma = atomic_rcu_read ( & rsource - > rioc - > rdmaout ) ;
}
if ( ! rdma ) {
error_report ( " RDMAContext is NULL when prepare Gsource " ) ;
rcu_read_unlock ( ) ;
return FALSE ;
}
if ( rdma - > wr_data [ 0 ] . control_len ) {
cond | = G_IO_IN ;
}
cond | = G_IO_OUT ;
rcu_read_unlock ( ) ;
return cond & rsource - > condition ;
}
@ -2795,14 +2897,28 @@ static gboolean
qio_channel_rdma_source_check ( GSource * source )
{
QIOChannelRDMASource * rsource = ( QIOChannelRDMASource * ) source ;
RDMAContext * rdma = rsource - > rioc - > rdma ;
RDMAContext * rdma ;
GIOCondition cond = 0 ;
rcu_read_lock ( ) ;
if ( rsource - > condition = = G_IO_IN ) {
rdma = atomic_rcu_read ( & rsource - > rioc - > rdmain ) ;
} else {
rdma = atomic_rcu_read ( & rsource - > rioc - > rdmaout ) ;
}
if ( ! rdma ) {
error_report ( " RDMAContext is NULL when check Gsource " ) ;
rcu_read_unlock ( ) ;
return FALSE ;
}
if ( rdma - > wr_data [ 0 ] . control_len ) {
cond | = G_IO_IN ;
}
cond | = G_IO_OUT ;
rcu_read_unlock ( ) ;
return cond & rsource - > condition ;
}
@ -2813,14 +2929,28 @@ qio_channel_rdma_source_dispatch(GSource *source,
{
QIOChannelFunc func = ( QIOChannelFunc ) callback ;
QIOChannelRDMASource * rsource = ( QIOChannelRDMASource * ) source ;
RDMAContext * rdma = rsource - > rioc - > rdma ;
RDMAContext * rdma ;
GIOCondition cond = 0 ;
rcu_read_lock ( ) ;
if ( rsource - > condition = = G_IO_IN ) {
rdma = atomic_rcu_read ( & rsource - > rioc - > rdmain ) ;
} else {
rdma = atomic_rcu_read ( & rsource - > rioc - > rdmaout ) ;
}
if ( ! rdma ) {
error_report ( " RDMAContext is NULL when dispatch Gsource " ) ;
rcu_read_unlock ( ) ;
return FALSE ;
}
if ( rdma - > wr_data [ 0 ] . control_len ) {
cond | = G_IO_IN ;
}
cond | = G_IO_OUT ;
rcu_read_unlock ( ) ;
return ( * func ) ( QIO_CHANNEL ( rsource - > rioc ) ,
( cond & rsource - > condition ) ,
user_data ) ;
@ -2860,20 +2990,91 @@ static GSource *qio_channel_rdma_create_watch(QIOChannel *ioc,
return source ;
}
static void qio_channel_rdma_set_aio_fd_handler ( QIOChannel * ioc ,
AioContext * ctx ,
IOHandler * io_read ,
IOHandler * io_write ,
void * opaque )
{
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( ioc ) ;
if ( io_read ) {
aio_set_fd_handler ( ctx , rioc - > rdmain - > comp_channel - > fd ,
false , io_read , io_write , NULL , opaque ) ;
} else {
aio_set_fd_handler ( ctx , rioc - > rdmaout - > comp_channel - > fd ,
false , io_read , io_write , NULL , opaque ) ;
}
}
static int qio_channel_rdma_close ( QIOChannel * ioc ,
Error * * errp )
{
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( ioc ) ;
RDMAContext * rdmain , * rdmaout ;
trace_qemu_rdma_close ( ) ;
if ( rioc - > rdma ) {
if ( ! rioc - > rdma - > error_state ) {
rioc - > rdma - > error_state = qemu_file_get_error ( rioc - > file ) ;
rdmain = rioc - > rdmain ;
if ( rdmain ) {
atomic_rcu_set ( & rioc - > rdmain , NULL ) ;
}
rdmaout = rioc - > rdmaout ;
if ( rdmaout ) {
atomic_rcu_set ( & rioc - > rdmaout , NULL ) ;
}
synchronize_rcu ( ) ;
if ( rdmain ) {
qemu_rdma_cleanup ( rdmain ) ;
}
if ( rdmaout ) {
qemu_rdma_cleanup ( rdmaout ) ;
}
g_free ( rdmain ) ;
g_free ( rdmaout ) ;
return 0 ;
}
static int
qio_channel_rdma_shutdown ( QIOChannel * ioc ,
QIOChannelShutdown how ,
Error * * errp )
{
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( ioc ) ;
RDMAContext * rdmain , * rdmaout ;
rcu_read_lock ( ) ;
rdmain = atomic_rcu_read ( & rioc - > rdmain ) ;
rdmaout = atomic_rcu_read ( & rioc - > rdmain ) ;
switch ( how ) {
case QIO_CHANNEL_SHUTDOWN_READ :
if ( rdmain ) {
rdmain - > error_state = - 1 ;
}
break ;
case QIO_CHANNEL_SHUTDOWN_WRITE :
if ( rdmaout ) {
rdmaout - > error_state = - 1 ;
}
qemu_rdma_cleanup ( rioc - > rdma ) ;
g_free ( rioc - > rdma ) ;
rioc - > rdma = NULL ;
break ;
case QIO_CHANNEL_SHUTDOWN_BOTH :
default :
if ( rdmain ) {
rdmain - > error_state = - 1 ;
}
if ( rdmaout ) {
rdmaout - > error_state = - 1 ;
}
break ;
}
rcu_read_unlock ( ) ;
return 0 ;
}
@ -2916,11 +3117,24 @@ static size_t qemu_rdma_save_page(QEMUFile *f, void *opaque,
size_t size , uint64_t * bytes_sent )
{
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( opaque ) ;
RDMAContext * rdma = rioc - > rdma ;
RDMAContext * rdma ;
int ret ;
rcu_read_lock ( ) ;
rdma = atomic_rcu_read ( & rioc - > rdmaout ) ;
if ( ! rdma ) {
rcu_read_unlock ( ) ;
return - EIO ;
}
CHECK_ERROR_STATE ( ) ;
if ( migrate_get_current ( ) - > state = = MIGRATION_STATUS_POSTCOPY_ACTIVE ) {
rcu_read_unlock ( ) ;
return RAM_SAVE_CONTROL_NOT_SUPP ;
}
qemu_fflush ( f ) ;
if ( size > 0 ) {
@ -3002,12 +3216,45 @@ static size_t qemu_rdma_save_page(QEMUFile *f, void *opaque,
}
}
rcu_read_unlock ( ) ;
return RAM_SAVE_CONTROL_DELAYED ;
err :
rdma - > error_state = ret ;
rcu_read_unlock ( ) ;
return ret ;
}
static void rdma_accept_incoming_migration ( void * opaque ) ;
static void rdma_cm_poll_handler ( void * opaque )
{
RDMAContext * rdma = opaque ;
int ret ;
struct rdma_cm_event * cm_event ;
MigrationIncomingState * mis = migration_incoming_get_current ( ) ;
ret = rdma_get_cm_event ( rdma - > channel , & cm_event ) ;
if ( ret ) {
error_report ( " get_cm_event failed %d " , errno ) ;
return ;
}
rdma_ack_cm_event ( cm_event ) ;
if ( cm_event - > event = = RDMA_CM_EVENT_DISCONNECTED | |
cm_event - > event = = RDMA_CM_EVENT_DEVICE_REMOVAL ) {
error_report ( " receive cm event, cm event is %d " , cm_event - > event ) ;
rdma - > error_state = - EPIPE ;
if ( rdma - > return_path ) {
rdma - > return_path - > error_state = - EPIPE ;
}
if ( mis - > migration_incoming_co ) {
qemu_coroutine_enter ( mis - > migration_incoming_co ) ;
}
return ;
}
}
static int qemu_rdma_accept ( RDMAContext * rdma )
{
RDMACapabilities cap ;
@ -3102,7 +3349,15 @@ static int qemu_rdma_accept(RDMAContext *rdma)
}
}
qemu_set_fd_handler ( rdma - > channel - > fd , NULL , NULL , NULL ) ;
/* Accept the second connection request for return path */
if ( migrate_postcopy ( ) & & ! rdma - > is_return_path ) {
qemu_set_fd_handler ( rdma - > channel - > fd , rdma_accept_incoming_migration ,
NULL ,
( void * ) ( intptr_t ) rdma - > return_path ) ;
} else {
qemu_set_fd_handler ( rdma - > channel - > fd , rdma_cm_poll_handler ,
NULL , rdma ) ;
}
ret = rdma_accept ( rdma - > cm_id , & conn_param ) ;
if ( ret ) {
@ -3171,8 +3426,8 @@ static int qemu_rdma_registration_handle(QEMUFile *f, void *opaque)
RDMAControlHeader blocks = { . type = RDMA_CONTROL_RAM_BLOCKS_RESULT ,
. repeat = 1 } ;
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( opaque ) ;
RDMAContext * rdma = rioc - > rdma ;
RDMALocalBlocks * local = & rdma - > local_ram_blocks ;
RDMAContext * rdma ;
RDMALocalBlocks * local ;
RDMAControlHeader head ;
RDMARegister * reg , * registers ;
RDMACompress * comp ;
@ -3185,8 +3440,17 @@ static int qemu_rdma_registration_handle(QEMUFile *f, void *opaque)
int count = 0 ;
int i = 0 ;
rcu_read_lock ( ) ;
rdma = atomic_rcu_read ( & rioc - > rdmain ) ;
if ( ! rdma ) {
rcu_read_unlock ( ) ;
return - EIO ;
}
CHECK_ERROR_STATE ( ) ;
local = & rdma - > local_ram_blocks ;
do {
trace_qemu_rdma_registration_handle_wait ( ) ;
@ -3420,6 +3684,7 @@ out:
if ( ret < 0 ) {
rdma - > error_state = ret ;
}
rcu_read_unlock ( ) ;
return ret ;
}
@ -3433,10 +3698,18 @@ out:
static int
rdma_block_notification_handle ( QIOChannelRDMA * rioc , const char * name )
{
RDMAContext * rdma = rioc - > rdma ;
RDMAContext * rdma ;
int curr ;
int found = - 1 ;
rcu_read_lock ( ) ;
rdma = atomic_rcu_read ( & rioc - > rdmain ) ;
if ( ! rdma ) {
rcu_read_unlock ( ) ;
return - EIO ;
}
/* Find the matching RAMBlock in our local list */
for ( curr = 0 ; curr < rdma - > local_ram_blocks . nb_blocks ; curr + + ) {
if ( ! strcmp ( rdma - > local_ram_blocks . block [ curr ] . block_name , name ) ) {
@ -3447,6 +3720,7 @@ rdma_block_notification_handle(QIOChannelRDMA *rioc, const char *name)
if ( found = = - 1 ) {
error_report ( " RAMBlock '%s' not found on destination " , name ) ;
rcu_read_unlock ( ) ;
return - ENOENT ;
}
@ -3454,6 +3728,7 @@ rdma_block_notification_handle(QIOChannelRDMA *rioc, const char *name)
trace_rdma_block_notification_handle ( name , rdma - > next_src_index ) ;
rdma - > next_src_index + + ;
rcu_read_unlock ( ) ;
return 0 ;
}
@ -3476,14 +3751,27 @@ static int qemu_rdma_registration_start(QEMUFile *f, void *opaque,
uint64_t flags , void * data )
{
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( opaque ) ;
RDMAContext * rdma = rioc - > rdma ;
RDMAContext * rdma ;
rcu_read_lock ( ) ;
rdma = atomic_rcu_read ( & rioc - > rdmaout ) ;
if ( ! rdma ) {
rcu_read_unlock ( ) ;
return - EIO ;
}
CHECK_ERROR_STATE ( ) ;
if ( migrate_get_current ( ) - > state = = MIGRATION_STATUS_POSTCOPY_ACTIVE ) {
rcu_read_unlock ( ) ;
return 0 ;
}
trace_qemu_rdma_registration_start ( flags ) ;
qemu_put_be64 ( f , RAM_SAVE_FLAG_HOOK ) ;
qemu_fflush ( f ) ;
rcu_read_unlock ( ) ;
return 0 ;
}
@ -3496,12 +3784,24 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
{
Error * local_err = NULL , * * errp = & local_err ;
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( opaque ) ;
RDMAContext * rdma = rioc - > rdma ;
RDMAContext * rdma ;
RDMAControlHeader head = { . len = 0 , . repeat = 1 } ;
int ret = 0 ;
rcu_read_lock ( ) ;
rdma = atomic_rcu_read ( & rioc - > rdmaout ) ;
if ( ! rdma ) {
rcu_read_unlock ( ) ;
return - EIO ;
}
CHECK_ERROR_STATE ( ) ;
if ( migrate_get_current ( ) - > state = = MIGRATION_STATUS_POSTCOPY_ACTIVE ) {
rcu_read_unlock ( ) ;
return 0 ;
}
qemu_fflush ( f ) ;
ret = qemu_rdma_drain_cq ( f , rdma ) ;
@ -3530,6 +3830,7 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
qemu_rdma_reg_whole_ram_blocks : NULL ) ;
if ( ret < 0 ) {
ERROR ( errp , " receiving remote info! " ) ;
rcu_read_unlock ( ) ;
return ret ;
}
@ -3553,6 +3854,7 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
" not identical on both the source and destination. " ,
local - > nb_blocks , nb_dest_blocks ) ;
rdma - > error_state = - EINVAL ;
rcu_read_unlock ( ) ;
return - EINVAL ;
}
@ -3569,6 +3871,7 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
local - > block [ i ] . length ,
rdma - > dest_blocks [ i ] . length ) ;
rdma - > error_state = - EINVAL ;
rcu_read_unlock ( ) ;
return - EINVAL ;
}
local - > block [ i ] . remote_host_addr =
@ -3586,9 +3889,11 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
goto err ;
}
rcu_read_unlock ( ) ;
return 0 ;
err :
rdma - > error_state = ret ;
rcu_read_unlock ( ) ;
return ret ;
}
@ -3606,10 +3911,15 @@ static const QEMUFileHooks rdma_write_hooks = {
static void qio_channel_rdma_finalize ( Object * obj )
{
QIOChannelRDMA * rioc = QIO_CHANNEL_RDMA ( obj ) ;
if ( rioc - > rdma ) {
qemu_rdma_cleanup ( rioc - > rdma ) ;
g_free ( rioc - > rdma ) ;
rioc - > rdma = NULL ;
if ( rioc - > rdmain ) {
qemu_rdma_cleanup ( rioc - > rdmain ) ;
g_free ( rioc - > rdmain ) ;
rioc - > rdmain = NULL ;
}
if ( rioc - > rdmaout ) {
qemu_rdma_cleanup ( rioc - > rdmaout ) ;
g_free ( rioc - > rdmaout ) ;
rioc - > rdmaout = NULL ;
}
}
@ -3623,6 +3933,8 @@ static void qio_channel_rdma_class_init(ObjectClass *klass,
ioc_klass - > io_set_blocking = qio_channel_rdma_set_blocking ;
ioc_klass - > io_close = qio_channel_rdma_close ;
ioc_klass - > io_create_watch = qio_channel_rdma_create_watch ;
ioc_klass - > io_set_aio_fd_handler = qio_channel_rdma_set_aio_fd_handler ;
ioc_klass - > io_shutdown = qio_channel_rdma_shutdown ;
}
static const TypeInfo qio_channel_rdma_info = {
@ -3649,13 +3961,16 @@ static QEMUFile *qemu_fopen_rdma(RDMAContext *rdma, const char *mode)
}
rioc = QIO_CHANNEL_RDMA ( object_new ( TYPE_QIO_CHANNEL_RDMA ) ) ;
rioc - > rdma = rdma ;
if ( mode [ 0 ] = = ' w ' ) {
rioc - > file = qemu_fopen_channel_output ( QIO_CHANNEL ( rioc ) ) ;
rioc - > rdmaout = rdma ;
rioc - > rdmain = rdma - > return_path ;
qemu_file_set_hooks ( rioc - > file , & rdma_write_hooks ) ;
} else {
rioc - > file = qemu_fopen_channel_input ( QIO_CHANNEL ( rioc ) ) ;
rioc - > rdmain = rdma ;
rioc - > rdmaout = rdma - > return_path ;
qemu_file_set_hooks ( rioc - > file , & rdma_read_hooks ) ;
}
@ -3679,6 +3994,10 @@ static void rdma_accept_incoming_migration(void *opaque)
trace_qemu_rdma_accept_incoming_migration_accepted ( ) ;
if ( rdma - > is_return_path ) {
return ;
}
f = qemu_fopen_rdma ( rdma , " rb " ) ;
if ( f = = NULL ) {
ERROR ( errp , " could not qemu_fopen_rdma! " ) ;
@ -3693,7 +4012,7 @@ static void rdma_accept_incoming_migration(void *opaque)
void rdma_start_incoming_migration ( const char * host_port , Error * * errp )
{
int ret ;
RDMAContext * rdma ;
RDMAContext * rdma , * rdma_return_path ;
Error * local_err = NULL ;
trace_rdma_start_incoming_migration ( ) ;
@ -3720,12 +4039,24 @@ void rdma_start_incoming_migration(const char *host_port, Error **errp)
trace_rdma_start_incoming_migration_after_rdma_listen ( ) ;
/* initialize the RDMAContext for return path */
if ( migrate_postcopy ( ) ) {
rdma_return_path = qemu_rdma_data_init ( host_port , & local_err ) ;
if ( rdma_return_path = = NULL ) {
goto err ;
}
qemu_rdma_return_path_dest_init ( rdma_return_path , rdma ) ;
}
qemu_set_fd_handler ( rdma - > channel - > fd , rdma_accept_incoming_migration ,
NULL , ( void * ) ( intptr_t ) rdma ) ;
return ;
err :
error_propagate ( errp , local_err ) ;
g_free ( rdma ) ;
g_free ( rdma_return_path ) ;
}
void rdma_start_outgoing_migration ( void * opaque ,
@ -3733,6 +4064,7 @@ void rdma_start_outgoing_migration(void *opaque,
{
MigrationState * s = opaque ;
RDMAContext * rdma = qemu_rdma_data_init ( host_port , errp ) ;
RDMAContext * rdma_return_path = NULL ;
int ret = 0 ;
if ( rdma = = NULL ) {
@ -3753,6 +4085,32 @@ void rdma_start_outgoing_migration(void *opaque,
goto err ;
}
/* RDMA postcopy need a seprate queue pair for return path */
if ( migrate_postcopy ( ) ) {
rdma_return_path = qemu_rdma_data_init ( host_port , errp ) ;
if ( rdma_return_path = = NULL ) {
goto err ;
}
ret = qemu_rdma_source_init ( rdma_return_path ,
s - > enabled_capabilities [ MIGRATION_CAPABILITY_RDMA_PIN_ALL ] , errp ) ;
if ( ret ) {
goto err ;
}
ret = qemu_rdma_connect ( rdma_return_path , errp ) ;
if ( ret ) {
goto err ;
}
rdma - > return_path = rdma_return_path ;
rdma_return_path - > return_path = rdma ;
rdma_return_path - > is_return_path = true ;
}
trace_rdma_start_outgoing_migration_after_rdma_connect ( ) ;
s - > to_dst_file = qemu_fopen_rdma ( rdma , " wb " ) ;
@ -3760,4 +4118,5 @@ void rdma_start_outgoing_migration(void *opaque,
return ;
err :
g_free ( rdma ) ;
g_free ( rdma_return_path ) ;
}