 303e6f54f9
			
		
	
	
		303e6f54f9
		
	
	
	
	
		
			
			1. Add zero_pages field in MultiFDPacket_t. 2. Implements the zero page detection and handling on the multifd threads for non-compression, zlib and zstd compression backends. 3. Added a new value 'multifd' in ZeroPageDetection enumeration. 4. Adds zero page counters and updates multifd send/receive tracing format to track the newly added counters. Signed-off-by: Hao Xiang <hao.xiang@bytedance.com> Acked-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/r/20240311180015.3359271-5-hao.xiang@linux.dev Signed-off-by: Peter Xu <peterx@redhat.com>
		
			
				
	
	
		
			88 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Multifd zero page detection implementation.
 | |
|  *
 | |
|  * Copyright (c) 2024 Bytedance Inc
 | |
|  *
 | |
|  * Authors:
 | |
|  *  Hao Xiang <hao.xiang@bytedance.com>
 | |
|  *
 | |
|  * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | |
|  * See the COPYING file in the top-level directory.
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "qemu/cutils.h"
 | |
| #include "exec/ramblock.h"
 | |
| #include "migration.h"
 | |
| #include "multifd.h"
 | |
| #include "options.h"
 | |
| #include "ram.h"
 | |
| 
 | |
| static bool multifd_zero_page_enabled(void)
 | |
| {
 | |
|     return migrate_zero_page_detection() == ZERO_PAGE_DETECTION_MULTIFD;
 | |
| }
 | |
| 
 | |
| static void swap_page_offset(ram_addr_t *pages_offset, int a, int b)
 | |
| {
 | |
|     ram_addr_t temp;
 | |
| 
 | |
|     if (a == b) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     temp = pages_offset[a];
 | |
|     pages_offset[a] = pages_offset[b];
 | |
|     pages_offset[b] = temp;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * multifd_send_zero_page_detect: Perform zero page detection on all pages.
 | |
|  *
 | |
|  * Sorts normal pages before zero pages in p->pages->offset and updates
 | |
|  * p->pages->normal_num.
 | |
|  *
 | |
|  * @param p A pointer to the send params.
 | |
|  */
 | |
| void multifd_send_zero_page_detect(MultiFDSendParams *p)
 | |
| {
 | |
|     MultiFDPages_t *pages = p->pages;
 | |
|     RAMBlock *rb = pages->block;
 | |
|     int i = 0;
 | |
|     int j = pages->num - 1;
 | |
| 
 | |
|     if (!multifd_zero_page_enabled()) {
 | |
|         pages->normal_num = pages->num;
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Sort the page offset array by moving all normal pages to
 | |
|      * the left and all zero pages to the right of the array.
 | |
|      */
 | |
|     while (i <= j) {
 | |
|         uint64_t offset = pages->offset[i];
 | |
| 
 | |
|         if (!buffer_is_zero(rb->host + offset, p->page_size)) {
 | |
|             i++;
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         swap_page_offset(pages->offset, i, j);
 | |
|         ram_release_page(rb->idstr, offset);
 | |
|         j--;
 | |
|     }
 | |
| 
 | |
|     pages->normal_num = i;
 | |
| }
 | |
| 
 | |
| void multifd_recv_zero_page_process(MultiFDRecvParams *p)
 | |
| {
 | |
|     for (int i = 0; i < p->zero_num; i++) {
 | |
|         void *page = p->host + p->zero[i];
 | |
|         if (!buffer_is_zero(page, p->page_size)) {
 | |
|             memset(page, 0, p->page_size);
 | |
|         }
 | |
|     }
 | |
| }
 |