On Mon, Aug 17, 2026 at 10:24 PM Peter Xu <[email protected]> wrote:
>
> The unregister code was there since the first commit RDMA migration was
> merged, but it was never functioning.  Remove the dead code.
>
> Since the two control messages are the last ones, we don't even need to
> worry about compatibility of legacy RDMA control commands, we can directly
> remove the messages too.
>
> As a side effect, this patch closes a report by removing the code
> completely.
>
> Reported-by: Tristan (@TristanInSec)
> Closes: https://gitlab.com/qemu-project/qemu/-/work_items/4003
> Signed-off-by: Peter Xu <[email protected]>
Hi Peter, hi Yanfei,

The change looks fine, and I have also tested to ensure it doesn't
break compatibility with older versions. As already discussed,
removing this code could result in more MRs being used during
migration; however, once the migration is complete, they will be
unregistered, so there is no leak.

Reviewed-by: Jinpu Wang <[email protected]>
> ---
>  migration/rdma.c       | 133 -----------------------------------------
>  migration/trace-events |   7 ---
>  2 files changed, 140 deletions(-)
>
> diff --git a/migration/rdma.c b/migration/rdma.c
> index 62a509b236..eae4afd6df 100644
> --- a/migration/rdma.c
> +++ b/migration/rdma.c
> @@ -142,8 +142,6 @@ enum {
>      RDMA_CONTROL_REGISTER_REQUEST,    /* dynamic page registration */
>      RDMA_CONTROL_REGISTER_RESULT,     /* key to use after registration */
>      RDMA_CONTROL_REGISTER_FINISHED,   /* current iteration finished */
> -    RDMA_CONTROL_UNREGISTER_REQUEST,  /* dynamic UN-registration */
> -    RDMA_CONTROL_UNREGISTER_FINISHED, /* unpinning finished */
>      RDMA_CONTROL_NUM,
>  };
>
> @@ -232,8 +230,6 @@ static const char *control_desc(unsigned int rdma_control)
>          [RDMA_CONTROL_REGISTER_REQUEST] = "REGISTER REQUEST",
>          [RDMA_CONTROL_REGISTER_RESULT] = "REGISTER RESULT",
>          [RDMA_CONTROL_REGISTER_FINISHED] = "REGISTER FINISHED",
> -        [RDMA_CONTROL_UNREGISTER_REQUEST] = "UNREGISTER REQUEST",
> -        [RDMA_CONTROL_UNREGISTER_FINISHED] = "UNREGISTER FINISHED",
>      };
>
>      if (rdma_control >= RDMA_CONTROL_NUM) {
> @@ -370,9 +366,6 @@ typedef struct RDMAContext {
>      int total_registrations;
>      int total_writes;
>
> -    int unregister_current, unregister_next;
> -    uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
> -
>      GHashTable *blockmap;
>
>      /* the RDMAContext for return path */
> @@ -1186,91 +1179,6 @@ static int qemu_rdma_reg_control(RDMAContext *rdma, 
> int idx)
>      return -1;
>  }
>
> -/*
> - * Perform a non-optimized memory unregistration after every transfer
> - * for demonstration purposes, only if pin-all is not requested.
> - *
> - * Potential optimizations:
> - * 1. Start a new thread to run this function continuously
> -        - for bit clearing
> -        - and for receipt of unregister messages
> - * 2. Use an LRU.
> - * 3. Use workload hints.
> - */
> -static int qemu_rdma_unregister_waiting(RDMAContext *rdma)
> -{
> -    Error *err = NULL;
> -
> -    while (rdma->unregistrations[rdma->unregister_current]) {
> -        int ret;
> -        uint64_t wr_id = rdma->unregistrations[rdma->unregister_current];
> -        uint64_t chunk =
> -            (wr_id & RDMA_WRID_CHUNK_MASK) >> RDMA_WRID_CHUNK_SHIFT;
> -        uint64_t index =
> -            (wr_id & RDMA_WRID_BLOCK_MASK) >> RDMA_WRID_BLOCK_SHIFT;
> -        RDMALocalBlock *block =
> -            &(rdma->local_ram_blocks.block[index]);
> -        RDMARegister reg = { .current_index = index };
> -        RDMAControlHeader resp = { .type = RDMA_CONTROL_UNREGISTER_FINISHED,
> -                                 };
> -        RDMAControlHeader head = { .len = sizeof(RDMARegister),
> -                                   .type = RDMA_CONTROL_UNREGISTER_REQUEST,
> -                                   .repeat = 1,
> -                                 };
> -
> -        trace_qemu_rdma_unregister_waiting_proc(chunk,
> -                                                rdma->unregister_current);
> -
> -        rdma->unregistrations[rdma->unregister_current] = 0;
> -        rdma->unregister_current++;
> -
> -        if (rdma->unregister_current == RDMA_SIGNALED_SEND_MAX) {
> -            rdma->unregister_current = 0;
> -        }
> -
> -
> -        /*
> -         * Unregistration is speculative (because migration is 
> single-threaded
> -         * and we cannot break the protocol's inifinband message ordering).
> -         * Thus, if the memory is currently being used for transmission,
> -         * then abort the attempt to unregister and try again
> -         * later the next time a completion is received for this memory.
> -         */
> -        clear_bit(chunk, block->unregister_bitmap);
> -
> -        if (test_bit(chunk, block->transit_bitmap)) {
> -            trace_qemu_rdma_unregister_waiting_inflight(chunk);
> -            continue;
> -        }
> -
> -        trace_qemu_rdma_unregister_waiting_send(chunk);
> -
> -        ret = ibv_dereg_mr(block->pmr[chunk]);
> -        block->pmr[chunk] = NULL;
> -        block->remote_keys[chunk] = 0;
> -
> -        if (ret != 0) {
> -            error_report("unregistration chunk failed: %s",
> -                         strerror(ret));
> -            return -1;
> -        }
> -        rdma->total_registrations--;
> -
> -        reg.key.chunk = chunk;
> -        register_to_network(rdma, &reg);
> -        ret = qemu_rdma_exchange_send(rdma, &head, (uint8_t *) &reg,
> -                                      &resp, NULL, NULL, &err);
> -        if (ret < 0) {
> -            error_report_err(err);
> -            return -1;
> -        }
> -
> -        trace_qemu_rdma_unregister_waiting_complete(chunk);
> -    }
> -
> -    return 0;
> -}
> -
>  static uint64_t qemu_rdma_make_wrid(uint64_t wr_id, uint64_t index,
>                                           uint64_t chunk)
>  {
> @@ -2757,8 +2665,6 @@ static int qemu_rdma_drain_cq(RDMAContext *rdma)
>          }
>      }
>
> -    qemu_rdma_unregister_waiting(rdma);
> -
>      return 0;
>  }
>
> @@ -3336,10 +3242,6 @@ int rdma_registration_handle(QEMUFile *f)
>                                 .type = RDMA_CONTROL_REGISTER_RESULT,
>                                 .repeat = 0,
>                               };
> -    RDMAControlHeader unreg_resp = { .len = 0,
> -                               .type = RDMA_CONTROL_UNREGISTER_FINISHED,
> -                               .repeat = 0,
> -                             };
>      RDMAControlHeader blocks = { .type = RDMA_CONTROL_RAM_BLOCKS_RESULT,
>                                   .repeat = 1 };
>      QIOChannelRDMA *rioc;
> @@ -3552,41 +3454,6 @@ int rdma_registration_handle(QEMUFile *f)
>              ret = qemu_rdma_post_send_control(rdma,
>                              (uint8_t *) results, &reg_resp, &err);
>
> -            if (ret < 0) {
> -                error_report_err(err);
> -                goto err;
> -            }
> -            break;
> -        case RDMA_CONTROL_UNREGISTER_REQUEST:
> -            trace_rdma_registration_handle_unregister(head.repeat);
> -            unreg_resp.repeat = head.repeat;
> -            registers = (RDMARegister *) rdma->wr_data[idx].control_curr;
> -
> -            for (int count = 0; count < head.repeat; count++) {
> -                reg = &registers[count];
> -                network_to_register(reg);
> -
> -                trace_rdma_registration_handle_unregister_loop(count,
> -                           reg->current_index, reg->key.chunk);
> -
> -                block = &(rdma->local_ram_blocks.block[reg->current_index]);
> -
> -                ret = ibv_dereg_mr(block->pmr[reg->key.chunk]);
> -                block->pmr[reg->key.chunk] = NULL;
> -
> -                if (ret != 0) {
> -                    error_report("rdma unregistration chunk failed: %s",
> -                                 strerror(errno));
> -                    goto err;
> -                }
> -
> -                rdma->total_registrations--;
> -
> -                
> trace_rdma_registration_handle_unregister_success(reg->key.chunk);
> -            }
> -
> -            ret = qemu_rdma_post_send_control(rdma, NULL, &unreg_resp, &err);
> -
>              if (ret < 0) {
>                  error_report_err(err);
>                  goto err;
> diff --git a/migration/trace-events b/migration/trace-events
> index af0e784535..d1fe8f1382 100644
> --- a/migration/trace-events
> +++ b/migration/trace-events
> @@ -244,10 +244,6 @@ qemu_rdma_advise_mr(const char *name, uint32_t len, 
> uint64_t addr, const char *r
>  qemu_rdma_resolve_host_trying(const char *host, const char *ip) "Trying %s 
> => %s"
>  qemu_rdma_signal_unregister_append(uint64_t chunk, int pos) "Appending 
> unregister chunk %" PRIu64 " at position %d"
>  qemu_rdma_signal_unregister_already(uint64_t chunk) "Unregister chunk %" 
> PRIu64 " already in queue"
> -qemu_rdma_unregister_waiting_inflight(uint64_t chunk) "Cannot unregister 
> inflight chunk: %" PRIu64
> -qemu_rdma_unregister_waiting_proc(uint64_t chunk, int pos) "Processing 
> unregister for chunk: %" PRIu64 " at position %d"
> -qemu_rdma_unregister_waiting_send(uint64_t chunk) "Sending unregister for 
> chunk: %" PRIu64
> -qemu_rdma_unregister_waiting_complete(uint64_t chunk) "Unregister for chunk: 
> %" PRIu64 " complete."
>  qemu_rdma_write_flush(int sent) "sent total: %d"
>  qemu_rdma_write_one_block(int count, int block, uint64_t chunk, uint64_t 
> current, uint64_t len, int nb_sent, int nb_chunks) "(%d) Not clobbering: 
> block: %d chunk %" PRIu64 " current %" PRIu64 " len %" PRIu64 " %d %d"
>  qemu_rdma_write_one_post(uint64_t chunk, long addr, long remote, uint32_t 
> len) "Posting chunk: %" PRIu64 ", addr: 0x%lx remote: 0x%lx, bytes %" PRIu32
> @@ -266,9 +262,6 @@ rdma_registration_handle_ram_blocks_loop(const char 
> *name, uint64_t offset, uint
>  rdma_registration_handle_register(int requests) "%d requests"
>  rdma_registration_handle_register_loop(int req, int index, uint64_t addr, 
> uint64_t chunks) "Registration request (%d): index %d, current_addr %" PRIu64 
> " chunks: %" PRIu64
>  rdma_registration_handle_register_rkey(int rkey) "0x%x"
> -rdma_registration_handle_unregister(int requests) "%d requests"
> -rdma_registration_handle_unregister_loop(int count, int index, uint64_t 
> chunk) "Unregistration request (%d): index %d, chunk %" PRIu64
> -rdma_registration_handle_unregister_success(uint64_t chunk) "%" PRIu64
>  rdma_registration_handle_wait(void) ""
>  rdma_registration_start(uint64_t flags) "%" PRIu64
>  rdma_registration_stop(uint64_t flags) "%" PRIu64
> --
> 2.54.0
>

Reply via email to